diff --git a/jikimo_sale_multiple_supply_methods/__init__.py b/jikimo_sale_multiple_supply_methods/__init__.py
index 9cb6cca1..62b89387 100644
--- a/jikimo_sale_multiple_supply_methods/__init__.py
+++ b/jikimo_sale_multiple_supply_methods/__init__.py
@@ -7,11 +7,16 @@ from odoo import api, SUPERUSER_ID
def _data_install(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
# 获取所有需要设置的产品模板
- env.ref('jikimo_sale_multiple_supply_methods.product_product_purchase').product_tmpl_id.write({'active': False})
- env.ref('jikimo_sale_multiple_supply_methods.product_product_manual_processing').product_tmpl_id.write({'active': False, 'single_manufacturing': True})
- env.ref('jikimo_sale_multiple_supply_methods.product_product_default').product_tmpl_id.write({'active': False})
- env.ref('jikimo_sale_multiple_supply_methods.product_product_raw_material_customer_provided').product_tmpl_id.write({'active': False})
- env.ref('jikimo_sale_multiple_supply_methods.product_product_outsourcing').product_tmpl_id.write({'active': False})
+ env.ref('jikimo_sale_multiple_supply_methods.product_template_purchase').product_variant_id.write({'active': False, 'is_bfm': True})
+ env.ref('jikimo_sale_multiple_supply_methods.product_template_manual_processing').product_variant_id.write({'active': False, 'single_manufacturing': True, 'is_bfm': True})
+ env.ref('jikimo_sale_multiple_supply_methods.product_template_default').product_variant_id.write({'active': False, 'is_bfm': True})
+ env.ref('jikimo_sale_multiple_supply_methods.product_template_raw_material_customer_provided').product_variant_id.write({'active': False})
+ env.ref('jikimo_sale_multiple_supply_methods.product_template_outsourcing').product_variant_id.write({'active': False, 'is_bfm': True})
+ env.ref('sf_dlm.product_embryo_sf_self_machining').product_tmpl_id.write({'categ_type': '坯料'})
+ env.ref('sf_dlm.product_template_sf').product_tmpl_id.write({'categ_type': '成品'})
+ env.ref('sf_dlm.product_embryo_sf_outsource').product_tmpl_id.write({'categ_type': '坯料'})
+ env.ref('sf_dlm.product_embryo_sf_purchase').product_tmpl_id.write({'categ_type': '坯料'})
+
# 为三步制造增加规则
warehouse = env['stock.warehouse'].search([('company_id', '=', env.company.id)], limit=1)
product_route_id = warehouse.pbm_route_id
@@ -121,3 +126,18 @@ def _create_or_update_stock_rule(env, rule_data):
# 如果不存在,创建新记录
env['stock.rule'].create(rule_data)
+def _data_uninstall(cr, registry):
+ env = api.Environment(cr, SUPERUSER_ID, {})
+ warehouse = env['stock.warehouse'].search([('company_id', '=', env.company.id)], limit=1)
+ product_route_id = warehouse.pbm_route_id
+ resupply_route_id = warehouse.subcontracting_route_id
+ mto_route_id = env.ref('stock.route_warehouse0_mto')
+ # Fail unlink means that the route is used somewhere (e.g. route_id on stock.rule). In this case
+ # we don't try to do anything.
+ try:
+ with env.cr.savepoint():
+ env['stock.rule'].search([('name', 'in', ('WH: 原料存货区 → 制造前', 'WH: 坯料存货区 → 制造前', 'WH: 制造后 → 坯料存货区', 'WH: 制造后 → 成品存货区')), ('route_id', '=', product_route_id.id)]).unlink()
+ env['stock.rule'].search([('name', 'in', ('WH: 原料存货区 → 外包位置 (MTO)', 'WH: 坯料存货区 → 外包位置 (MTO)')), ('route_id', '=', mto_route_id.id)]).unlink()
+ env['stock.rule'].search([('name', '=', 'WH: 坯料存货区 → 外包位置'), ('route_id', '=', resupply_route_id.id)]).unlink()
+ except:
+ pass
\ No newline at end of file
diff --git a/jikimo_sale_multiple_supply_methods/__manifest__.py b/jikimo_sale_multiple_supply_methods/__manifest__.py
index 78507e37..a7d39ac7 100644
--- a/jikimo_sale_multiple_supply_methods/__manifest__.py
+++ b/jikimo_sale_multiple_supply_methods/__manifest__.py
@@ -6,7 +6,7 @@
'author': 'fox',
'website': '',
'category': '',
- 'depends': ['product', 'sf_dlm', 'sale_stock', 'sf_sale'],
+ 'depends': ['sf_dlm', 'sale_stock', 'sf_sale'],
"data": [
'security/ir.model.access.csv',
'data/stock_routes.xml',
@@ -19,6 +19,7 @@
# ],
},
'post_init_hook': '_data_install',
+ 'uninstall_hook': '_data_uninstall',
'application': True,
'installable': True,
'auto_install': False,
diff --git a/jikimo_sale_multiple_supply_methods/controllers/main.py b/jikimo_sale_multiple_supply_methods/controllers/main.py
index 13113ac0..9127f80e 100644
--- a/jikimo_sale_multiple_supply_methods/controllers/main.py
+++ b/jikimo_sale_multiple_supply_methods/controllers/main.py
@@ -19,7 +19,8 @@ class JikimoSaleRoutePicking(Sf_Bf_Connect):
res = {'status': 1, 'factory_order_no': ''}
# _logger.info('get_bfm_process_order_list:%s' % kw['order_number'])
try:
- product_id = request.env.ref('jikimo_sale_multiple_supply_methods.product_product_default').sudo()
+ product_id = request.env.ref('jikimo_sale_multiple_supply_methods.product_template_default').with_context(active_test=False).sudo().product_variant_id
+ _logger.info('product_id:%s' % product_id)
company_id = request.env.ref('base.main_company').sudo()
bfm_process_order_list = json.loads(kw['bfm_process_order_list'])
order_id = request.env['sale.order'].with_user(request.env.ref("base.user_admin")).sale_order_create(
@@ -27,12 +28,11 @@ class JikimoSaleRoutePicking(Sf_Bf_Connect):
kw['delivery_end_date'], kw['payments_way'], kw['pay_way'], state='draft')
i = 1
# 给sale_order的default_code字段赋值
- aa = request.env['sale.order'].sudo().search([('name', '=', order_id.name)])
- _logger.info('get_bfm_process_or===================================:%s' % order_id.name)
- aa.default_code = kw['order_number']
+ # aa = request.env['sale.order'].sudo().search([('name', '=', order_id.name)])
+ # _logger.info('get_bfm_process_or===================================:%s' % order_id.name)
+ order_id.default_code = kw['order_number']
if kw.get('logistics_way'):
- aa.logistics_way = kw['logistics_way']
- _logger.info('get_bfm_process_order_listaaaaaaaaaaaaaaaaaaaaaaaaaaaa================:%s' % aa.default_code)
+ order_id.logistics_way = kw['logistics_way']
for item in bfm_process_order_list:
product = request.env['product.template'].sudo().product_create(product_id, item, order_id,
kw['order_number'], i)
diff --git a/jikimo_sale_multiple_supply_methods/data/product_data.xml b/jikimo_sale_multiple_supply_methods/data/product_data.xml
index 40c8ca63..dc9b70a7 100644
--- a/jikimo_sale_multiple_supply_methods/data/product_data.xml
+++ b/jikimo_sale_multiple_supply_methods/data/product_data.xml
@@ -1,7 +1,7 @@
-
+
人工线下加工模板
@@ -15,11 +15,11 @@
true
serial
- true
+
true
-
+
成品外购模板
@@ -30,10 +30,10 @@
- true
+
-
+
成品委外加工模板
@@ -44,10 +44,10 @@
- true
+
-
+
成品初始化模板
@@ -57,7 +57,7 @@
- true
+
@@ -65,7 +65,7 @@
-
+
坯料客供料模板
@@ -79,12 +79,20 @@
+
-
- 坯料加工模板(人工线下加工)
+
true
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jikimo_sale_multiple_supply_methods/models/quick_easy_order.py b/jikimo_sale_multiple_supply_methods/models/quick_easy_order.py
new file mode 100644
index 00000000..89d3a6d8
--- /dev/null
+++ b/jikimo_sale_multiple_supply_methods/models/quick_easy_order.py
@@ -0,0 +1,71 @@
+from datetime import datetime
+from odoo import models
+
+import logging
+import base64
+import hashlib
+
+_logger = logging.getLogger(__name__)
+
+
+class QuickEasyOrder(models.Model):
+ _inherit = 'quick.easy.order'
+
+ def distribute_to_factory(self, obj):
+ """
+ 多供货方式,重写派单到工厂
+ :return:
+ """
+ try:
+ _logger.info('---------派单到工厂-------')
+ res = {'bfm_process_order_list': []}
+ for item in obj:
+ attachment = item.upload_model_file[0]
+ base64_data = base64.b64encode(attachment.datas)
+ base64_datas = base64_data.decode('utf-8')
+ barcode = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest()
+ # logging.info('model_file-size: %s' % len(item.model_file))
+ res['bfm_process_order_list'].append({
+ 'model_long': item.model_length,
+ 'model_width': item.model_width,
+ 'model_height': item.model_height,
+ 'model_volume': item.model_volume,
+ 'model_machining_precision': item.machining_precision,
+ 'model_name': attachment.name,
+ 'model_data': base64_datas,
+ 'model_file': base64.b64encode(item.model_file).decode('utf-8'),
+ 'texture_code': item.material_id.materials_no,
+ 'texture_type_code': item.material_model_id.materials_no,
+ # 'surface_process_code': self.env['jikimo.surface.process']._json_surface_process_code(item),
+ 'process_parameters_code': self.env[
+ 'sf.production.process.parameter']._json_production_process_item_code(
+ item),
+ 'price': item.price,
+ 'number': item.quantity,
+ 'total_amount': item.price,
+ 'remark': '',
+ 'manual_quotation': True,
+ 'barcode': barcode,
+ 'part_number': item.part_drawing_number,
+ 'machining_drawings_name': '',
+ 'quality_standard_name': '',
+ 'machining_drawings_mimetype': '',
+ 'quality_standard_mimetype': '',
+ 'machining_drawings': item.machining_drawings,
+ 'quality_standard': '',
+ 'part_name': '',
+ })
+ company_id = self.env.ref('base.main_company').sudo()
+ product_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_default').sudo().with_context(active_test=False).product_variant_id
+ # user_id = request.env.ref('base.user_admin').sudo()
+ order_id = self.env['sale.order'].sale_order_create(company_id, 'XXXXX', 'XXXXX', 'XXXXX',
+ str(datetime.now()), '现结', '支付宝', state='draft')
+ order_id.default_code = obj.name
+ i = 1
+ for item in res['bfm_process_order_list']:
+ product = self.env['product.template'].sudo().product_create(product_id, item, order_id,
+ obj.name, i)
+ order_id.with_user(self.env.ref("base.user_admin")).sale_order_create_line(product, item)
+ return order_id
+ except Exception as e:
+ return UserError('工厂创建销售订单和产品失败,请联系管理员')
diff --git a/jikimo_sale_multiple_supply_methods/models/sale_order.py b/jikimo_sale_multiple_supply_methods/models/sale_order.py
index 822958ec..cd8fa749 100644
--- a/jikimo_sale_multiple_supply_methods/models/sale_order.py
+++ b/jikimo_sale_multiple_supply_methods/models/sale_order.py
@@ -21,25 +21,28 @@ class SaleOrder(models.Model):
self.state = 'supply method'
def action_confirm(self):
+ # 判断是否所有产品都选择了供货方式
+ filter_line = self.order_line.filtered(lambda line: not line.supply_method)
+ if filter_line:
+ raise UserError('当前订单内(%s)产品未选择路线,请选择后重试' % ','.join(filter_line.mapped('product_id.name')))
+
for line in self.order_line:
- if not line.supply_method:
- raise UserError('请先选择供货方式')
bom_type = ''
# 根据供货方式修改成品模板
if line.supply_method == 'automation':
bom_type = 'normal'
- product_template_id = self.env.ref('sf_dlm.product_template_sf').sudo()
+ product_template_id = self.env.ref('sf_dlm.product_template_sf').sudo().product_tmpl_id
elif line.supply_method == 'outsourcing':
bom_type = 'subcontract'
- product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_product_outsourcing').sudo()
+ product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_outsourcing').sudo()
elif line.supply_method == 'purchase':
- product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_product_purchase').sudo()
+ product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_purchase').sudo()
elif line.supply_method == 'manual':
bom_type = 'normal'
- product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_product_manual_processing').sudo()
+ product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_manual_processing').sudo()
# 复制成品模板上的属性
- line.product_id.product_tmpl_id.copy_template(product_template_id.product_tmpl_id)
+ line.product_id.product_tmpl_id.copy_template(product_template_id)
order_id = self
product = line.product_id
@@ -52,6 +55,8 @@ class SaleOrder(models.Model):
'model_height': product.height,
'price': product.list_price,
}
+ # 获取成品名结尾-n的n
+ product_seria = int(product.name.split('-')[-1])
# 成品供货方式为采购则不生成bom
if line.supply_method != 'purchase':
bom_data = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).get_bom(product)
@@ -63,12 +68,12 @@ class SaleOrder(models.Model):
# 当成品上带有客供料选项时,生成坯料时选择“客供料”路线
if line.is_incoming_material:
# 将成品模板的内容复制到成品上
- customer_provided_embryo = self.env.ref('jikimo_sale_multiple_supply_methods.product_product_raw_material_customer_provided').sudo()
+ customer_provided_embryo = self.env.ref('jikimo_sale_multiple_supply_methods.product_tempalte_raw_material_customer_provided').sudo()
# 创建坯料,客供料的批量不需要创建bom
material_customer_provided_embryo = self.env['product.template'].sudo().no_bom_product_create(
- customer_provided_embryo,
+ customer_provided_embryo.with_context(active_test=False).product_variant_id,
item,
- order_id, 'material_customer_provided', 0, product)
+ order_id, 'material_customer_provided', product_seria, product)
# 成品配置bom
product_bom_material_customer_provided = self.env['mrp.bom'].with_user(
self.env.ref("base.user_admin")).bom_create(
@@ -81,7 +86,7 @@ class SaleOrder(models.Model):
self_machining_embryo = self.env['product.template'].sudo().no_bom_product_create(
self_machining_id,
item,
- order_id, 'self_machining', 0, product)
+ order_id, 'self_machining', product_seria, product)
# 创建坯料的bom
self_machining_bom = self.env['mrp.bom'].with_user(
self.env.ref("base.user_admin")).bom_create(
@@ -105,7 +110,7 @@ class SaleOrder(models.Model):
item,
order_id,
'subcontract',
- 0, product)
+ product_seria, product)
if outsource_embryo == -3:
raise UserError('该订单模型的材料型号暂未设置获取方式和供应商,请先配置再进行分配')
# 创建坯料的bom
@@ -127,7 +132,7 @@ class SaleOrder(models.Model):
purchase_embryo = self.env['product.template'].sudo().no_bom_product_create(purchase_id,
item,
order_id,
- 'purchase', 0,
+ 'purchase', product_seria,
product)
if purchase_embryo == -3:
raise UserError('该订单模型的材料型号暂未设置获取方式和供应商,请先配置再进行分配')
diff --git a/jikimo_sale_multiple_supply_methods/views/sale_order_views.xml b/jikimo_sale_multiple_supply_methods/views/sale_order_views.xml
index 3021f301..2ea9a835 100644
--- a/jikimo_sale_multiple_supply_methods/views/sale_order_views.xml
+++ b/jikimo_sale_multiple_supply_methods/views/sale_order_views.xml
@@ -22,7 +22,7 @@
confirm_to_supply_method
-
+
draft,sent,supply method,sale
@@ -30,17 +30,14 @@
-
-
-
-
- jikimo.sale.order.search.inherit.quotation
- sale.order
- primary
-
-
-
-
+
+ {'invisible': [('state', '!=', 'draft')]}
+
+
+ {'invisible': [('state', '!=', 'draft')]}
+
+
+ {'invisible': ['|','&',('check_status', '!=', 'approved'),('state', 'in', ['draft','cancel','supply method']),'&',('check_status', '=', 'approved'),('state', 'in', ['sale','cancel','supply method'])]}
@@ -51,8 +48,8 @@
primary
-
-
+
+ [('state', 'in', ('draft', 'sent')), ('user_id', '=', uid)]
@@ -60,8 +57,8 @@
-
-
+
+
@@ -69,6 +66,7 @@
ir.actions.act_window
sale.order
tree,kanban,form,calendar,pivot,graph,activity
+
{'search_default_supply_method': 1}
@@ -83,22 +81,27 @@
id="sale.sale_menu_root"
groups="sf_base.group_production_engineer,sf_base.group_sale_director,sf_base.group_sale_salemanager"
/>
-
-
+
+
+
+
+
+
+
+
+
diff --git a/sf_base/models/common.py b/sf_base/models/common.py
index 63b269ec..4152c119 100644
--- a/sf_base/models/common.py
+++ b/sf_base/models/common.py
@@ -56,7 +56,7 @@ class MrsMaterialModel(models.Model):
finish_machining = fields.Float("精加工Vc(m/min)")
remark = fields.Text("备注")
gain_way = fields.Selection(
- [("自加工", "自加工"), ("外协", "外协"), ("采购", "采购")],
+ [("自加工", "自加工"), ("外协", "委外加工"), ("采购", "采购")],
default="", string="获取方式")
supplier_ids = fields.One2many('sf.supplier.sort', 'materials_model_id', string='供应商')
active = fields.Boolean('有效', default=True)
diff --git a/sf_dlm_management/views/product_template_management_view.xml b/sf_dlm_management/views/product_template_management_view.xml
index 59f2c0a1..7f0e9ad5 100644
--- a/sf_dlm_management/views/product_template_management_view.xml
+++ b/sf_dlm_management/views/product_template_management_view.xml
@@ -65,6 +65,9 @@
attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}"
domain="[('fixture_model_id','=',fixture_model_id)]"/>
+
+
+
diff --git a/sf_machine_connect/views/WorkCenterBarcodes.xml b/sf_machine_connect/views/WorkCenterBarcodes.xml
index 97fee70e..90058b59 100644
--- a/sf_machine_connect/views/WorkCenterBarcodes.xml
+++ b/sf_machine_connect/views/WorkCenterBarcodes.xml
@@ -10,6 +10,8 @@
+
+
diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py
index da1e497e..2bde02d9 100644
--- a/sf_manufacturing/__manifest__.py
+++ b/sf_manufacturing/__manifest__.py
@@ -12,6 +12,7 @@
'website': 'https://www.sf.jikimo.com',
'depends': ['sf_base', 'sf_maintenance', 'web_widget_model_viewer', 'sf_warehouse','jikimo_attachment_viewer', 'jikimo_sale_multiple_supply_methods'],
'data': [
+ 'data/cron_data.xml',
'data/stock_data.xml',
'data/empty_racks_data.xml',
'data/panel_data.xml',
diff --git a/sf_manufacturing/data/cron_data.xml b/sf_manufacturing/data/cron_data.xml
new file mode 100644
index 00000000..36e5bcf9
--- /dev/null
+++ b/sf_manufacturing/data/cron_data.xml
@@ -0,0 +1,29 @@
+
+
+
+ 工期状态变更
+
+ code
+ model._corn_update_construction_period_status()
+ 12
+ hours
+ -1
+
+
+
+
+
+
+ 交期状态变更
+
+ code
+ model._corn_update_delivery_status()
+ 12
+ hours
+ -1
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sf_manufacturing/models/model_type.py b/sf_manufacturing/models/model_type.py
index 27ebfb03..d08b024b 100644
--- a/sf_manufacturing/models/model_type.py
+++ b/sf_manufacturing/models/model_type.py
@@ -8,17 +8,20 @@ class ModelType(models.Model):
name = fields.Char('名称')
embryo_tolerance = fields.Integer('坯料容余')
product_routing_tmpl_ids = fields.One2many('sf.product.model.type.routing.sort', 'product_model_type_id',
- '成品工序模板')
+ '成品工序模板(自动化产线加工')
embryo_routing_tmpl_ids = fields.One2many('sf.embryo.model.type.routing.sort', 'embryo_model_type_id',
- '坯料工序模板')
+ '坯料工序模板(人工线下加工)')
surface_technics_routing_tmpl_ids = fields.One2many('sf.surface_technics.model.type.routing.sort',
'surface_technics_model_type_id',
'表面工艺工序模板')
+ manual_product_routing_tmpl_ids = fields.One2many('sf.manual.product.model.type.routing.sort',
+ 'manual_product_model_type_id',
+ '成品工序模板(人工线下加工)')
class ProductModelTypeRoutingSort(models.Model):
_name = 'sf.product.model.type.routing.sort'
- _description = '成品工序排序'
+ _description = '成品工序排序(自动化产线加工)'
sequence = fields.Integer('Sequence')
route_workcenter_id = fields.Many2one('mrp.routing.workcenter',
@@ -65,3 +68,18 @@ class SurfaceTechnicsModelTypeRoutingSort(models.Model):
'route_model_type_uniq', 'unique (route_workcenter_id,surface_technics_model_type_id)',
'表面工艺工序不能重复!')
]
+
+class ManualProductModelTypeRoutingSort(models.Model):
+ _name = 'sf.manual.product.model.type.routing.sort'
+ _description = '成品工序排序(人工线下加工)'
+
+ sequence = fields.Integer('Sequence')
+ route_workcenter_id = fields.Many2one('mrp.routing.workcenter')
+ is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat')
+ routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
+ workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
+ manual_product_model_type_id = fields.Many2one('sf.model.type')
+
+ _sql_constraints = [
+ ('route_model_type_uniq', 'unique (route_workcenter_id,manual_product_model_type_id)', '成品工序不能重复!')
+ ]
\ No newline at end of file
diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py
index d2374541..66cfb98f 100644
--- a/sf_manufacturing/models/mrp_production.py
+++ b/sf_manufacturing/models/mrp_production.py
@@ -34,6 +34,95 @@ class MrpProduction(models.Model):
tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True)
tool_state_remark2 = fields.Text(string='功能刀具状态备注(无效刀)', readonly=True)
+ def _compute_default_delivery_status(self):
+ try:
+ if self.state == 'cancel':
+ return False
+ if not self.deadline_of_delivery:
+ return False
+ hours = self.get_hours_diff()
+ if hours >= 48:
+ return '正常'
+ elif hours > 0 and hours < 48 and self.state != 'done':
+ return '预警'
+ elif hours > 0 and hours < 48 and self.state == 'done':
+ return '正常'
+ else:
+ return '已逾期'
+ except Exception as e:
+ logging.error("Error processing production ID {}: {}".format(self.id, e))
+ raise e
+
+ @api.depends('state', 'deadline_of_delivery')
+ def _compute_delivery_status(self):
+ for production in self:
+ delivery_status = production._compute_default_delivery_status()
+ if delivery_status and production.delivery_status != delivery_status:
+ production.delivery_status = delivery_status
+
+ delivery_status = fields.Selection([('正常', '正常'), ('预警', '预警'), ('已逾期', '已逾期')], string='交期状态',
+ store=True,
+ compute='_compute_delivery_status',
+ default=lambda self: self._compute_default_delivery_status())
+
+ def get_page_all_records(self, model_name, func, domain, page_size=100):
+ # 获取模型对象
+ model = self.env[model_name].sudo()
+
+ # 初始化分页参数
+ page_number = 1
+ while True:
+ # 计算偏移量
+ offset = (page_number - 1) * page_size
+
+ # 获取当前页的数据
+ records = model.search(domain, limit=page_size, offset=offset)
+
+ # 如果没有更多记录,退出循环
+ if not records:
+ break
+
+ # 将当前页的数据添加到结果列表
+ func(records)
+ # 增加页码
+ page_number += 1
+
+ def run_compute_delivery_status(self, records):
+ records._compute_delivery_status()
+
+ def _corn_update_delivery_status(self):
+ need_list = [
+ 'draft',
+ 'technology_to_confirmed',
+ 'confirmed',
+ 'pending_cam',
+ 'progress',
+ 'rework',
+ 'scrap',
+ 'to_close',
+ ]
+ # previous_workorder = self.env['mrp.production'].search([('state', 'in', need_list)])
+ self.get_page_all_records('mrp.production', self.run_compute_delivery_status,
+ [('state', 'in', need_list)], 100)
+
+ def get_hours_diff(self):
+ # 获取当前日期和时间
+ current_datetime = fields.Datetime.now()
+
+ # 将 date_field 转换为 datetime 对象
+ if self.deadline_of_delivery:
+ date_obj = fields.Date.from_string(self.deadline_of_delivery)
+ # 将 date 对象转换为 datetime 对象,设置时间为 00:00:00
+ date_obj = datetime.datetime.combine(date_obj, datetime.time.min)
+
+ # 计算两个日期之间的差值
+ delta = date_obj - current_datetime
+
+ # 返回差值的小时数
+ return int(delta.total_seconds() / 3600)
+ else:
+ return 0.0
+
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
def _compute_deadline_of_delivery(self):
for production in self:
@@ -612,20 +701,6 @@ class MrpProduction(models.Model):
for workorder in production.workorder_ids:
workorder.duration_expected = workorder._get_duration_expected()
- # 生成采购单
- def get_subcontract_purchase(self):
- production_all = self.sorted(lambda x: x.id)
- for production in production_all:
- for special in production.technology_design_ids:
- if special.process_parameters_id.gain_way == '外协':
- product_id_to_production_names = {}
- grouped_product_ids = {k: list(g) for k, g in
- groupby(production_all, key=lambda x: x.product_id.id)}
- for product_id, pd in grouped_product_ids.items():
- product_id_to_production_names[product_id] = [p.name for p in pd]
- self.env['purchase.order'].get_purchase_order(special.process_parameters_id,
- special.production_id,
- product_id_to_production_names)
# 外协出入库单处理
def get_subcontract_pick_purchase(self):
@@ -800,6 +875,7 @@ class MrpProduction(models.Model):
if td_ids:
work.sequence = td_ids[0].sequence
+
def _reset_work_order_sequence_1(self):
"""
工单工序排序方法(旧)
diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py
index 0ed8b4b0..074ca01e 100644
--- a/sf_manufacturing/models/mrp_workorder.py
+++ b/sf_manufacturing/models/mrp_workorder.py
@@ -144,6 +144,88 @@ class ResMrpWorkOrder(models.Model):
tag_type = fields.Selection([("重新加工", "重新加工")], string="标签", tracking=True)
+ def _compute_default_construction_period_status(self):
+ need_list=['pending', 'waiting', 'ready', 'progress', 'to be detected','done']
+ try:
+ if self.state not in need_list:
+ return False
+ if not self.date_planned_finished:
+ return False
+ hours = self.get_hours_diff()
+ if hours >= 12:
+ return '正常'
+ elif hours > 0 and hours < 12 and self.state!='done':
+ return '预警'
+ elif hours > 0 and hours < 12 and self.state=='done':
+ return '正常'
+ else:
+ return '已逾期'
+ except Exception as e:
+ logging.error("Error processing production ID {}: {}".format(self.id, e))
+ raise e
+
+ @api.depends('state', 'date_planned_finished')
+ def _compute_construction_period_status(self):
+ for worker in self:
+ construction_period_status = worker._compute_default_construction_period_status()
+ if construction_period_status and worker.construction_period_status!=construction_period_status:
+ worker.construction_period_status = construction_period_status
+
+ construction_period_status = fields.Selection([('正常', '正常'), ('预警', '预警'), ('已逾期', '已逾期')],
+ string='工期状态',
+ store=True,
+ compute='_compute_construction_period_status',
+ default=lambda
+ self: self._compute_default_construction_period_status())
+
+ def get_page_all_records(self, model_name, func, domain, page_size=100):
+ # 获取模型对象
+ model = self.env[model_name].sudo()
+
+ # 初始化分页参数
+ page_number = 1
+ while True:
+ # 计算偏移量
+ offset = (page_number - 1) * page_size
+
+ # 获取当前页的数据
+ records = model.search(domain, limit=page_size, offset=offset)
+
+ # 如果没有更多记录,退出循环
+ if not records:
+ break
+
+ # 将当前页的数据添加到结果列表
+ func(records)
+ # 增加页码
+ page_number += 1
+ def run_compute_construction_period_status(self,records):
+ records._compute_construction_period_status()
+ def _corn_update_construction_period_status(self):
+ need_list=['pending', 'waiting', 'ready', 'progress', 'to be detected']
+ # need_list = [
+ # 'progress',
+ # 'to be detected']
+ self.get_page_all_records('mrp.workorder',self.run_compute_construction_period_status,[('state', 'in', need_list)],100)
+
+ def get_hours_diff(self):
+ # 获取当前日期和时间
+ current_datetime = fields.Datetime.now()
+
+ # 将 date_field 转换为 datetime 对象
+ if self.date_planned_finished:
+ date_obj = fields.Datetime.from_string(self.date_planned_finished)
+ # 将 date 对象转换为 datetime 对象,设置时间为 00:00:00
+ # date_obj = datetime.datetime.combine(date_obj, datetime.time.min)
+
+ # 计算两个日期之间的差值
+ delta = date_obj - current_datetime
+
+ # 返回差值的小时数
+ return int(delta.total_seconds() / 3600)
+ else:
+ return 0.0
+
@api.depends('name', 'production_id.name')
def _compute_surface_technics_picking_ids(self):
for workorder in self:
diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py
index 6c2f77c0..f363cc53 100644
--- a/sf_manufacturing/models/product_template.py
+++ b/sf_manufacturing/models/product_template.py
@@ -859,7 +859,7 @@ class ResProductMo(models.Model):
item['model_width'] + model_type.embryo_tolerance) * (
item['model_height'] + model_type.embryo_tolerance),
'product_model_type_id': model_type.id,
- # 'model_processing_panel': 'R',
+ 'model_processing_panel': item['processing_panel_detail'],
'model_machining_precision': item['model_machining_precision'],
'model_code': item['barcode'],
'length': item['model_long'],
@@ -934,6 +934,7 @@ class ResProductMo(models.Model):
# if surface_technology:
# no_bom_copy_product_id.route_ids |= surface_technology
no_bom_copy_product_id.product_tmpl_id.active = True
+ logging.info('no_bom_copy_product_id[is_manual_processing]:%s' % no_bom_copy_product_id.is_manual_processing)
materials_id = self.env['sf.production.materials'].search(
[('materials_no', '=', item['texture_code'])])
materials_type_id = self.env['sf.materials.model'].search(
@@ -959,7 +960,7 @@ class ResProductMo(models.Model):
'materials_type_id': materials_type_id.id,
'single_manufacturing': product_id.single_manufacturing,
'is_bfm': True,
- 'active': True
+ 'active': True,
}
# 外协和采购生成的坯料需要根据材料型号绑定供应商
if route_type == 'subcontract' or route_type == 'purchase':
diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py
index 5eb03ae3..e0d51bea 100644
--- a/sf_manufacturing/models/stock.py
+++ b/sf_manufacturing/models/stock.py
@@ -294,10 +294,10 @@ class StockRule(models.Model):
# 为同一个product_id创建一个生产订单名称列表
product_id_to_production_names[product_id] = [production.name for production in all_production]
for production_item in productions:
- production_programming = self.env['mrp.production'].search(
- [('product_id.id', '=', production_item.product_id.id),
- ('origin', '=', production_item.origin)],
- limit=1, order='id asc')
+ # production_programming = self.env['mrp.production'].search(
+ # [('product_id.id', '=', production_item.product_id.id),
+ # ('origin', '=', production_item.origin)],
+ # limit=1, order='id asc')
if production_item.product_id.id in product_id_to_production_names:
# 同一个产品多个制造订单对应一个编程单和模型库
# 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
@@ -455,6 +455,12 @@ class ProductionLot(models.Model):
if product.categ_id.name == '刀具':
return self.env['stock.lot'].get_tool_generate_lot_names1(company, product)
else:
+ # 对last_serial的name进行检测,如果不是以产品名称+数字的形式的就重新搜索
+ if product.name.split('[')[0] not in last_serial.name:
+ last_serial = self.env['stock.lot'].search(
+ [('company_id', '=', company.id), ('product_id', '=', product.id),
+ ('name', 'ilike', product.name.split('[')[0])],
+ limit=1, order='name desc')
return self.env['stock.lot'].generate_lot_names1(product.name, last_serial.name, 2)[1]
now = datetime.now().strftime("%Y%m%d")
if product.cutting_tool_model_id:
@@ -775,10 +781,11 @@ class ReStockMove(models.Model):
self.next_serial = self._get_tool_next_serial(self.company_id, self.product_id, self.origin)
else:
self.next_serial = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id)
+ if self.picking_type_id.sequence_code == 'DL' and not self.move_line_nosuggest_ids:
+ self.action_assign_serial_show_details()
elif self.product_id.tracking == "lot":
self._put_tool_lot(self.company_id, self.product_id, self.origin)
- if not self.move_line_nosuggest_ids:
- self._generate_serial_numbers()
+
return {
'name': _('Detailed Operations'),
diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv
index d63a0a63..b9d0710f 100644
--- a/sf_manufacturing/security/ir.model.access.csv
+++ b/sf_manufacturing/security/ir.model.access.csv
@@ -175,5 +175,6 @@ access_sf_production_technology_re_adjust_wizard_group_plan_dispatch,sf_producti
access_sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,model_sf_production_technology_re_adjust_wizard,sf_base.group_sf_mrp_manager,1,1,1,0
access_sf_production_technology_re_adjust_wizard_group_production_engineer,sf_production_technology_re_adjust_wizard_group_production_engineer,model_sf_production_technology_re_adjust_wizard,sf_base.group_production_engineer,1,1,1,0
-
-
+access_sf_manual_product_model_type_routing_sort_group_sf_mrp_user,sf_manual_product_model_type_routing_sort,model_sf_manual_product_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
+access_sf_manual_product_model_type_routing_sort_manager,sf_manual_product_model_type_routing_sort,model_sf_manual_product_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,0
+access_sf_manual_product_model_type_routing_sort_group_plan_dispatch,sf_manual_product_model_type_routing_sort_group_plan_dispatch,model_sf_manual_product_model_type_routing_sort,sf_base.group_plan_dispatch,1,0,0,0
diff --git a/sf_manufacturing/views/model_type_view.xml b/sf_manufacturing/views/model_type_view.xml
index 09877a83..56d5f94c 100644
--- a/sf_manufacturing/views/model_type_view.xml
+++ b/sf_manufacturing/views/model_type_view.xml
@@ -44,6 +44,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml
index d50c600b..f88182cb 100644
--- a/sf_manufacturing/views/mrp_production_addional_change.xml
+++ b/sf_manufacturing/views/mrp_production_addional_change.xml
@@ -57,6 +57,16 @@
+
+
+
+
+ 1
+
+
@@ -347,8 +357,6 @@
-
-
-
+
+
diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml
index c2853758..5055b7fa 100644
--- a/sf_manufacturing/views/mrp_workorder_view.xml
+++ b/sf_manufacturing/views/mrp_workorder_view.xml
@@ -32,8 +32,10 @@
-
+
@@ -257,11 +259,12 @@
-