From 1e172cb4e35970885e0b76d5cd1cce3fc85514e7 Mon Sep 17 00:00:00 2001 From: hujiaying Date: Tue, 27 Aug 2024 17:24:04 +0800 Subject: [PATCH 01/23] =?UTF-8?q?=E5=A4=84=E7=90=86=E4=BB=A3=E5=8F=91?= =?UTF-8?q?=E8=B4=A7=E4=B8=8B=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_stock/__init__.py | 4 +++ sf_stock/__manifest__.py | 36 +++++++++++++++++++++++++ sf_stock/controllers/__init__.py | 3 +++ sf_stock/controllers/controllers.py | 21 +++++++++++++++ sf_stock/demo/demo.xml | 30 +++++++++++++++++++++ sf_stock/models/__init__.py | 3 +++ sf_stock/models/stock_picking.py | 39 +++++++++++++++++++++++++++ sf_stock/security/ir.model.access.csv | 2 ++ sf_stock/views/stock_picking.xml | 5 ++++ 9 files changed, 143 insertions(+) create mode 100644 sf_stock/__init__.py create mode 100644 sf_stock/__manifest__.py create mode 100644 sf_stock/controllers/__init__.py create mode 100644 sf_stock/controllers/controllers.py create mode 100644 sf_stock/demo/demo.xml create mode 100644 sf_stock/models/__init__.py create mode 100644 sf_stock/models/stock_picking.py create mode 100644 sf_stock/security/ir.model.access.csv create mode 100644 sf_stock/views/stock_picking.xml diff --git a/sf_stock/__init__.py b/sf_stock/__init__.py new file mode 100644 index 00000000..511a0ca3 --- /dev/null +++ b/sf_stock/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import controllers +from . import models \ No newline at end of file diff --git a/sf_stock/__manifest__.py b/sf_stock/__manifest__.py new file mode 100644 index 00000000..f22004e5 --- /dev/null +++ b/sf_stock/__manifest__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +{ + 'name': "sf_stock", + + 'summary': """ + Short (1 phrase/line) summary of the module's purpose, used as + subtitle on modules listing or apps.openerp.com""", + + 'description': """ + Long description of module's purpose + """, + + 'author': "My Company", + 'website': "https://www.yourcompany.com", + + # Categories can be used to filter modules in modules listing + # Check https://github.com/odoo/odoo/blob/16.0/odoo/addons/base/data/ir_module_category_data.xml + # for the full list + 'category': 'Uncategorized', + 'version': '0.1', + + # any module necessary for this one to work correctly + 'depends': ['sf_sale', 'stock'], + + # always loaded + 'data': [ + # 'security/ir.model.access.csv', + 'views/stock_picking.xml', + ], + # only loaded in demonstration mode + 'demo': [ + 'demo/demo.xml', + ], + 'installable': True, + 'application': True, +} diff --git a/sf_stock/controllers/__init__.py b/sf_stock/controllers/__init__.py new file mode 100644 index 00000000..457bae27 --- /dev/null +++ b/sf_stock/controllers/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import controllers \ No newline at end of file diff --git a/sf_stock/controllers/controllers.py b/sf_stock/controllers/controllers.py new file mode 100644 index 00000000..af35ee1d --- /dev/null +++ b/sf_stock/controllers/controllers.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# from odoo import http + + +# class SfStock(http.Controller): +# @http.route('/sf_stock/sf_stock', auth='public') +# def index(self, **kw): +# return "Hello, world" + +# @http.route('/sf_stock/sf_stock/objects', auth='public') +# def list(self, **kw): +# return http.request.render('sf_stock.listing', { +# 'root': '/sf_stock/sf_stock', +# 'objects': http.request.env['sf_stock.sf_stock'].search([]), +# }) + +# @http.route('/sf_stock/sf_stock/objects/', auth='public') +# def object(self, obj, **kw): +# return http.request.render('sf_stock.object', { +# 'object': obj +# }) diff --git a/sf_stock/demo/demo.xml b/sf_stock/demo/demo.xml new file mode 100644 index 00000000..726c51be --- /dev/null +++ b/sf_stock/demo/demo.xml @@ -0,0 +1,30 @@ + + + + + \ No newline at end of file diff --git a/sf_stock/models/__init__.py b/sf_stock/models/__init__.py new file mode 100644 index 00000000..c62a4dff --- /dev/null +++ b/sf_stock/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import stock_picking \ No newline at end of file diff --git a/sf_stock/models/stock_picking.py b/sf_stock/models/stock_picking.py new file mode 100644 index 00000000..a28fbb5b --- /dev/null +++ b/sf_stock/models/stock_picking.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +import json +import requests +from odoo import models, fields, api + +from odoo.exceptions import UserError +import logging + +_logger = logging.getLogger(__name__) + + +class StockPicking(models.Model): + _inherit = 'stock.picking' + + # 重写验证,下发发货到bfm + def button_validate(self): + info = super(StockPicking, self).button_validate() + if self.picking_type_id.code == 'outgoing': + self.send_to_bfm() + return info + + def send_to_bfm(self): + # 下发发货到bfm + config = self.env['res.config.settings'].get_values() + json1 = { + 'params': { + 'name': self.origin, + 'send_no': self.name, + 'qty_done': self.move_line_ids.qty_done, + }, + } + url1 = config['bfm_url_new'] + '/api/stock/deliver_goods' + r = requests.post(url1, json=json1, data=None) + if r.status_code == 200: + result = json.loads(r.json()['result']) + if result['code'] != 200: + raise UserError(result['message'] or '工厂发货下发bfm失败') + else: + raise UserError('工厂发货下发bfm失败') diff --git a/sf_stock/security/ir.model.access.csv b/sf_stock/security/ir.model.access.csv new file mode 100644 index 00000000..af1bcbaf --- /dev/null +++ b/sf_stock/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_sf_stock_sf_stock,sf_stock.sf_stock,model_sf_stock_sf_stock,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/sf_stock/views/stock_picking.xml b/sf_stock/views/stock_picking.xml new file mode 100644 index 00000000..7750ca76 --- /dev/null +++ b/sf_stock/views/stock_picking.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file From 0ca6d46a7bfc81b094a217484a39879d4edbbb70 Mon Sep 17 00:00:00 2001 From: hujiaying Date: Sat, 31 Aug 2024 21:09:56 +0800 Subject: [PATCH 02/23] =?UTF-8?q?=E4=BF=AE=E6=94=B9sf=E4=B8=8B=E5=8F=91?= =?UTF-8?q?=E6=AC=A0=E5=8D=95=EF=BC=8Cbfm=E6=8E=A5=E6=94=B6=E4=B8=8B?= =?UTF-8?q?=E5=8F=91=E6=AC=A0=E5=8D=95=EF=BC=8C=E5=8F=8A=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=8F=91=E8=B4=A7=E5=8D=95=E7=9A=84=E5=85=B3=E7=B3=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_stock/models/__init__.py | 3 +- .../models/stock_backorder_confirmation.py | 27 ++++++++++ sf_stock/models/stock_picking.py | 53 +++++++++++++++++-- 3 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 sf_stock/models/stock_backorder_confirmation.py diff --git a/sf_stock/models/__init__.py b/sf_stock/models/__init__.py index c62a4dff..313cb109 100644 --- a/sf_stock/models/__init__.py +++ b/sf_stock/models/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- -from . import stock_picking \ No newline at end of file +from . import stock_picking +from . import stock_backorder_confirmation \ No newline at end of file diff --git a/sf_stock/models/stock_backorder_confirmation.py b/sf_stock/models/stock_backorder_confirmation.py new file mode 100644 index 00000000..4e894381 --- /dev/null +++ b/sf_stock/models/stock_backorder_confirmation.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +import json +import requests +from odoo import models, fields, api + +from odoo.exceptions import UserError +import logging +from odoo.tools import date_utils + +_logger = logging.getLogger(__name__) + + +class StockBackorderConfirmation(models.TransientModel): + _inherit = 'stock.backorder.confirmation' + + # 继承创建欠单 + def process(self): + info = super(StockBackorderConfirmation, self).process() + _logger.info("创建欠单") + # 下发创建欠单到bfm + + return info + + # 继承取消创建欠单 + def process_cancel_backorder(self): + info = super(StockBackorderConfirmation, self).process_cancel_backorder() + return info diff --git a/sf_stock/models/stock_picking.py b/sf_stock/models/stock_picking.py index a28fbb5b..fdb22c21 100644 --- a/sf_stock/models/stock_picking.py +++ b/sf_stock/models/stock_picking.py @@ -5,6 +5,7 @@ from odoo import models, fields, api from odoo.exceptions import UserError import logging +from odoo.tools import date_utils _logger = logging.getLogger(__name__) @@ -15,22 +16,64 @@ class StockPicking(models.Model): # 重写验证,下发发货到bfm def button_validate(self): info = super(StockPicking, self).button_validate() - if self.picking_type_id.code == 'outgoing': + if self.picking_type_code == 'outgoing': self.send_to_bfm() return info + def deal_move_ids(self, send_move_ids): + move_ids = [] # 本次发货单 + if send_move_ids: + for item in send_move_ids: + val = { + 'name': item.product_id.upload_model_file.display_name, + 'quantity_done': item.quantity_done, + 'date': date_utils.json_default(item.date) if item.date else None, + 'description_picking': item.description_picking, + 'date_deadline': date_utils.json_default(item.date_deadline) if item.date_deadline else None, + 'product_uom_qty': item.product_uom_qty, + 'sequence': item.sequence, + 'price_unit': item.price_unit, + 'priority': item.priority + } + move_ids.append(val) + return move_ids + + def deal_send_backorder_id(self, backorder_ids1): + backorder_ids = [] + if backorder_ids1: + for item in backorder_ids1: + val = { + 'receiverName': item.receiverName, + 'name': item.sale_id.default_code, + 'send_no': item.name, + 'scheduled_date': date_utils.json_default(item.scheduled_date) if item.scheduled_date else None, + 'date': date_utils.json_default(item.date) if item.date else None, + 'date_deadline': date_utils.json_default(item.date_deadline) if item.date_deadline else None, + 'move_ids': self.deal_move_ids(item.move_ids), + } + backorder_ids.append(val) + return backorder_ids + def send_to_bfm(self): # 下发发货到bfm config = self.env['res.config.settings'].get_values() - json1 = { + + data = { 'params': { - 'name': self.origin, + 'receiverName': self.receiverName, + 'name': self.sale_id.default_code, 'send_no': self.name, - 'qty_done': self.move_line_ids.qty_done, + 'scheduled_date': date_utils.json_default(self.scheduled_date) if self.scheduled_date else None, + 'date': date_utils.json_default(self.date) if self.date else None, + 'date_deadline': date_utils.json_default(self.date_deadline) if self.date_deadline else None, + 'move_ids': self.deal_move_ids(self.move_ids), + 'backorder_id': self.deal_send_backorder_id(self.backorder_id), + 'backorder_ids': self.deal_send_backorder_id(self.backorder_ids) + }, } url1 = config['bfm_url_new'] + '/api/stock/deliver_goods' - r = requests.post(url1, json=json1, data=None) + r = requests.post(url1, json=data, data=None) if r.status_code == 200: result = json.loads(r.json()['result']) if result['code'] != 200: From 09ee1c26b1d059631255ca60c38edf0f2842c36a Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Mon, 2 Sep 2024 17:33:06 +0800 Subject: [PATCH 03/23] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8A=A5=E5=BA=9F-?= =?UTF-8?q?=E5=A4=96=E5=8D=8F=E5=85=A5=E5=BA=93=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 41 ++++++++++------------- sf_manufacturing/models/mrp_workorder.py | 2 +- sf_manufacturing/models/stock.py | 8 ++++- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 5095556d..405baf38 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -779,7 +779,8 @@ class MrpProduction(models.Model): routing_workcenter = self.env['mrp.routing.workcenter'].sudo().search( [('name', '=', work.routing_type)]) - work.write({'date_planned_start': date_planned_start, 'date_planned_finished': date_planned_end,'duration_expected':routing_workcenter.time_cycle}) + work.write({'date_planned_start': date_planned_start, 'date_planned_finished': date_planned_end, + 'duration_expected': routing_workcenter.time_cycle}) # 修改标记已完成方法 def button_mark_done1(self): @@ -1078,27 +1079,22 @@ class MrpProduction(models.Model): productions.write({'programming_no': self.programming_no, 'is_remanufacture': True}) # productions.procurement_group_id.mrp_production_ids.move_dest_ids.write( # {'group_id': self.env['procurement.group'].search([('name', '=', sale_order.name)])}) - stock_picking = None - pc_picking = self.env['stock.picking'].search( - [('origin', '=', productions.name), ('name', 'ilike', 'WH/PC/')]) - stock_picking = pc_picking - int_picking = self.env['stock.picking'].search( - [('origin', '=', productions.name), ('name', 'ilike', 'WH/INT/')]) - stock_picking |= int_picking - for pick in stock_picking: - if pick.move_ids: - product_type_id = pick.move_ids[0].product_id.categ_id - if product_type_id.name == '坯料': - location_id = self.env['stock.location'].search([('name', '=', '坯料存货区')]) - if not location_id: - logging.info(f'没有搜索到【坯料存货区】: {location_id}') - break - if pick.picking_type_id.name == '内部调拨': - if pick.location_dest_id.product_type != product_type_id: - pick.location_dest_id = location_id.id - elif pick.picking_type_id.name == '生产发料': - if pick.location_id.product_type != product_type_id: - pick.location_id = location_id.id + stock_picking_remanufacture = self.env['stock.picking'].search([('origin', '=', productions.name)]) + for pick in stock_picking_remanufacture: + if pick.name.startswith('WH/PC/') or pick.name.startswith('WH/INT/'): + if pick.move_ids: + product_type_id = pick.move_ids[0].product_id.categ_id + if product_type_id.name == '坯料': + location_id = self.env['stock.location'].search([('name', '=', '坯料存货区')]) + if not location_id: + logging.info(f'没有搜索到【坯料存货区】: {location_id}') + break + if pick.picking_type_id.name == '内部调拨': + if pick.location_dest_id.product_type != product_type_id: + pick.location_dest_id = location_id.id + elif pick.picking_type_id.name == '生产发料': + if pick.location_id.product_type != product_type_id: + pick.location_id = location_id.id scarp_process_parameter_workorder = self.env['mrp.workorder'].search( [('surface_technics_parameters_id', '!=', False), ('production_id', '=', self.id), ('is_subcontract', '=', True)]) @@ -1111,7 +1107,6 @@ class MrpProduction(models.Model): for process_item in scarp_process_parameter_workorder: if purchase_item.product_id.categ_type == '表面工艺': if purchase_item.product_id.server_product_process_parameters_id == process_item.surface_technics_parameters_id: - print(purchase_orders.origin.find(productions.name)) if purchase_orders.origin.find(productions.name) == -1: purchase_orders.origin += ',' + productions.name if item['is_reprogramming'] is False: diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index c3842d30..8934711f 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1100,7 +1100,7 @@ class ResMrpWorkOrder(models.Model): [('barcode', 'ilike', 'VL-SPOC')]).id), ('origin', '=', self.production_id.name)]) if move_out.state != 'done': - move_out.write({'state': 'assigned'}) + move_out.write({'state': 'assigned', 'production_id': False}) self.env['stock.move.line'].create(move_out.get_move_line(self.production_id, self)) # move_out._action_assign() diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index b9483a17..9d4e3161 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -574,6 +574,7 @@ class StockPicking(models.Model): ('origin', '=', self.origin), ('picking_id', '=', self.id)]) if self.location_id == move_in.location_id and self.location_dest_id == move_in.location_dest_id: if move_out.origin == move_in.origin: + move_in.write({'production_id': False}) if move_out.picking_id.state != 'done': raise UserError( _('该入库单对应的单号为%s的出库单还未完成,不能进行验证操作!' % move_out.picking_id.name)) @@ -659,6 +660,11 @@ class ReStockMove(models.Model): return move_values def _get_new_picking_values_Res(self, item, sorted_workorders, rescode): + picking_type_id = self.mapped('picking_type_id').id + if rescode == 'WH/OCOUT/': + picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_out').id + elif rescode == 'WH/OCIN/': + picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_in').id return { 'name': self.env['stock.picking']._get_name_Res(rescode), 'origin': item.name, @@ -667,7 +673,7 @@ class ReStockMove(models.Model): 'user_id': False, 'move_type': self.mapped('group_id').move_type or 'direct', 'partner_id': sorted_workorders.supplier_id.id, - 'picking_type_id': self.mapped('picking_type_id').id, + 'picking_type_id': picking_type_id, 'location_id': self.mapped('location_id').id, 'location_dest_id': self.mapped('location_dest_id').id, 'state': 'confirmed', From fc1cdf4d0eae06756c78ea73de9686e013c6e61d Mon Sep 17 00:00:00 2001 From: hujiaying Date: Mon, 2 Sep 2024 19:02:53 +0800 Subject: [PATCH 04/23] =?UTF-8?q?=E8=81=94=E8=B0=83=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=8C=E5=A4=84=E7=90=86=E4=BF=AE=E6=94=B9?= =?UTF-8?q?sf=E4=B8=8B=E5=8F=91=E4=BB=A3=E5=8F=91=E8=B4=A7=EF=BC=8Cbfm?= =?UTF-8?q?=E6=8E=A5=E6=94=B6=E4=BB=A3=E5=8F=91=E8=B4=A7=E6=B6=88=E6=81=AF?= =?UTF-8?q?=EF=BC=8C=E4=B8=8B=E5=8F=91=E5=88=B0=E5=86=85=E9=83=A8=E7=AE=A1?= =?UTF-8?q?=E7=90=86=EF=BC=8C=E5=A4=84=E7=90=86=E9=87=87=E8=B4=AD=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E4=BB=A3=E5=8F=91=E8=B4=A7=E6=95=B0=E9=87=8F=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=8F=8A=E5=88=9B=E5=BB=BA=E6=AC=A0=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_stock/models/stock_picking.py | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/sf_stock/models/stock_picking.py b/sf_stock/models/stock_picking.py index fdb22c21..b995f812 100644 --- a/sf_stock/models/stock_picking.py +++ b/sf_stock/models/stock_picking.py @@ -20,8 +20,9 @@ class StockPicking(models.Model): self.send_to_bfm() return info - def deal_move_ids(self, send_move_ids): + def deal_move_ids(self, send_move_ids, send_move_line_ids): move_ids = [] # 本次发货单 + move_line_ids = [] # 本次发货单行 if send_move_ids: for item in send_move_ids: val = { @@ -33,15 +34,28 @@ class StockPicking(models.Model): 'product_uom_qty': item.product_uom_qty, 'sequence': item.sequence, 'price_unit': item.price_unit, - 'priority': item.priority + 'priority': item.priority, + 'state': item.state, } move_ids.append(val) - return move_ids + for item in send_move_line_ids: + val = { + 'qty_done': item.qty_done, + 'reserved_qty': item.reserved_qty, + 'reserved_uom_qty': item.reserved_uom_qty, + 'date': date_utils.json_default(item.date) if item.date else None, + 'description_picking': item.description_picking, + 'state': item.state, + } + move_line_ids.append(val) + return move_ids, move_line_ids def deal_send_backorder_id(self, backorder_ids1): backorder_ids = [] + if backorder_ids1: for item in backorder_ids1: + move_ids, move_line_ids = self.deal_move_ids(item.move_ids, item.move_line_ids) val = { 'receiverName': item.receiverName, 'name': item.sale_id.default_code, @@ -49,7 +63,9 @@ class StockPicking(models.Model): 'scheduled_date': date_utils.json_default(item.scheduled_date) if item.scheduled_date else None, 'date': date_utils.json_default(item.date) if item.date else None, 'date_deadline': date_utils.json_default(item.date_deadline) if item.date_deadline else None, - 'move_ids': self.deal_move_ids(item.move_ids), + 'move_ids': move_ids, + 'move_line_ids': move_line_ids, + 'state': item.state, } backorder_ids.append(val) return backorder_ids @@ -57,7 +73,7 @@ class StockPicking(models.Model): def send_to_bfm(self): # 下发发货到bfm config = self.env['res.config.settings'].get_values() - + move_ids, move_line_ids = self.deal_move_ids(self.move_ids, self.move_line_ids) data = { 'params': { 'receiverName': self.receiverName, @@ -66,13 +82,17 @@ class StockPicking(models.Model): 'scheduled_date': date_utils.json_default(self.scheduled_date) if self.scheduled_date else None, 'date': date_utils.json_default(self.date) if self.date else None, 'date_deadline': date_utils.json_default(self.date_deadline) if self.date_deadline else None, - 'move_ids': self.deal_move_ids(self.move_ids), + 'move_ids': move_ids, + 'move_line_ids': move_line_ids, + 'state': self.state, 'backorder_id': self.deal_send_backorder_id(self.backorder_id), 'backorder_ids': self.deal_send_backorder_id(self.backorder_ids) }, } url1 = config['bfm_url_new'] + '/api/stock/deliver_goods' + json_str = json.dumps(data) + print('json_str', json_str) r = requests.post(url1, json=data, data=None) if r.status_code == 200: result = json.loads(r.json()['result']) From 589035d42bcbdcccdcf07e56e5132cdcfdb158aa Mon Sep 17 00:00:00 2001 From: hujiaying Date: Tue, 3 Sep 2024 19:14:48 +0800 Subject: [PATCH 05/23] =?UTF-8?q?=E5=A4=84=E7=90=86=E9=87=87=E8=B4=AD?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E4=BB=A3=E5=8F=91=E8=B4=A7=E6=95=B0=E9=87=8F?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8F=8A=E5=88=9B=E5=BB=BA=E6=AC=A0=E5=8D=95?= =?UTF-8?q?=EF=BC=8C=E5=A4=84=E7=90=86sf=E5=8F=91=E8=B4=A7=E5=8D=95?= =?UTF-8?q?=E4=B8=8B=E5=8F=91=E4=B8=8D=E9=9C=80=E8=A6=81=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E6=AC=A0=E5=8D=95=EF=BC=8C=E5=A4=84=E7=90=86bfm=E5=8F=91?= =?UTF-8?q?=E8=B4=A7=E5=8D=95=E4=B8=8B=E5=8F=91=E5=86=85=E9=83=A8=E7=AE=A1?= =?UTF-8?q?=E7=90=86=EF=BC=8C=E5=86=85=E9=83=A8=E7=AE=A1=E7=90=86=E5=A4=84?= =?UTF-8?q?=E7=90=86=E4=B8=8D=E9=9C=80=E8=A6=81=E5=88=9B=E5=BB=BA=E6=AC=A0?= =?UTF-8?q?=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_stock/models/__init__.py | 3 +-- .../models/stock_backorder_confirmation.py | 27 ------------------- sf_stock/models/stock_picking.py | 10 +++++-- 3 files changed, 9 insertions(+), 31 deletions(-) delete mode 100644 sf_stock/models/stock_backorder_confirmation.py diff --git a/sf_stock/models/__init__.py b/sf_stock/models/__init__.py index 313cb109..c62a4dff 100644 --- a/sf_stock/models/__init__.py +++ b/sf_stock/models/__init__.py @@ -1,4 +1,3 @@ # -*- coding: utf-8 -*- -from . import stock_picking -from . import stock_backorder_confirmation \ No newline at end of file +from . import stock_picking \ No newline at end of file diff --git a/sf_stock/models/stock_backorder_confirmation.py b/sf_stock/models/stock_backorder_confirmation.py deleted file mode 100644 index 4e894381..00000000 --- a/sf_stock/models/stock_backorder_confirmation.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -import json -import requests -from odoo import models, fields, api - -from odoo.exceptions import UserError -import logging -from odoo.tools import date_utils - -_logger = logging.getLogger(__name__) - - -class StockBackorderConfirmation(models.TransientModel): - _inherit = 'stock.backorder.confirmation' - - # 继承创建欠单 - def process(self): - info = super(StockBackorderConfirmation, self).process() - _logger.info("创建欠单") - # 下发创建欠单到bfm - - return info - - # 继承取消创建欠单 - def process_cancel_backorder(self): - info = super(StockBackorderConfirmation, self).process_cancel_backorder() - return info diff --git a/sf_stock/models/stock_picking.py b/sf_stock/models/stock_picking.py index b995f812..37f24bf0 100644 --- a/sf_stock/models/stock_picking.py +++ b/sf_stock/models/stock_picking.py @@ -13,6 +13,8 @@ _logger = logging.getLogger(__name__) class StockPicking(models.Model): _inherit = 'stock.picking' + cancel_backorder_ids = fields.Boolean(default=False, string='是否取消后置单据') + # 重写验证,下发发货到bfm def button_validate(self): info = super(StockPicking, self).button_validate() @@ -63,6 +65,7 @@ class StockPicking(models.Model): 'scheduled_date': date_utils.json_default(item.scheduled_date) if item.scheduled_date else None, 'date': date_utils.json_default(item.date) if item.date else None, 'date_deadline': date_utils.json_default(item.date_deadline) if item.date_deadline else None, + 'date_done': date_utils.json_default(item.date_done) if item.date_done else None, 'move_ids': move_ids, 'move_line_ids': move_line_ids, 'state': item.state, @@ -71,23 +74,26 @@ class StockPicking(models.Model): return backorder_ids def send_to_bfm(self): + skip_backorder = self.env.context.get('skip_backorder') # 下发发货到bfm config = self.env['res.config.settings'].get_values() move_ids, move_line_ids = self.deal_move_ids(self.move_ids, self.move_line_ids) data = { 'params': { 'receiverName': self.receiverName, + 'priority': self.priority, 'name': self.sale_id.default_code, 'send_no': self.name, 'scheduled_date': date_utils.json_default(self.scheduled_date) if self.scheduled_date else None, 'date': date_utils.json_default(self.date) if self.date else None, 'date_deadline': date_utils.json_default(self.date_deadline) if self.date_deadline else None, + 'date_done': date_utils.json_default(self.date_done) if self.date_done else None, 'move_ids': move_ids, 'move_line_ids': move_line_ids, 'state': self.state, 'backorder_id': self.deal_send_backorder_id(self.backorder_id), - 'backorder_ids': self.deal_send_backorder_id(self.backorder_ids) - + 'backorder_ids': self.deal_send_backorder_id(self.backorder_ids), + 'cancel_backorder_ids': skip_backorder, }, } url1 = config['bfm_url_new'] + '/api/stock/deliver_goods' From 04c0d687636af151803b1abd4fc8a95d3daad9b8 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Wed, 4 Sep 2024 14:58:04 +0800 Subject: [PATCH 06/23] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=9A=82=E6=97=B6?= =?UTF-8?q?=E5=8E=BB=E6=8E=89=E8=BA=AB=E4=BB=BD=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/controllers/controllers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py index 632e9e4c..719ac481 100644 --- a/sf_manufacturing/controllers/controllers.py +++ b/sf_manufacturing/controllers/controllers.py @@ -477,7 +477,7 @@ class Manufacturing_Connect(http.Controller): logging.info('LocationChange error:%s' % e) return json.JSONEncoder().encode(res) - @http.route('/AutoDeviceApi/AGVToProduct', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False, + @http.route('/AutoDeviceApi/AGVToProduct', type='json', auth='none', methods=['GET', 'POST'], csrf=False, cors="*") def AGVToProduct(self, **kw): """ @@ -549,7 +549,7 @@ class Manufacturing_Connect(http.Controller): logging.info('AGVToProduct error:%s' % e) return json.JSONEncoder().encode(res) - @http.route('/AutoDeviceApi/AGVDownProduct', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False, + @http.route('/AutoDeviceApi/AGVDownProduct', type='json', auth='none', methods=['GET', 'POST'], csrf=False, cors="*") def AGVDownProduct(self, **kw): """ From 511bed47ff6233211a94bb8d15b627e61351db04 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Wed, 4 Sep 2024 16:58:55 +0800 Subject: [PATCH 07/23] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=BF=94=E5=B7=A5-?= =?UTF-8?q?=E4=BF=9D=E7=95=99=E8=A3=85=E5=A4=B9=E6=B5=8B=E9=87=8F=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/product_template.py | 4 +- sf_manufacturing/views/mrp_workorder_view.xml | 4 +- sf_manufacturing/wizard/rework_wizard.py | 54 +++++++++++++++---- .../wizard/rework_wizard_views.xml | 26 +++++---- sf_sale/models/quick_easy_order.py | 4 +- sf_sale/models/quick_easy_order_old.py | 4 +- 6 files changed, 68 insertions(+), 28 deletions(-) diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index 071f1167..37fa02bd 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -9,8 +9,8 @@ from odoo.exceptions import ValidationError, UserError from odoo.modules import get_resource_path -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file class ResProductMo(models.Model): diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index a802266f..512534d4 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -486,8 +486,8 @@ - - + + = 1 and self.programming_state == '已编程': @@ -149,9 +183,7 @@ class ReworkWizard(models.TransientModel): 'cmm_ids': new_cnc_workorder.cmm_ids.sudo()._json_cmm_program(panel.name, ret), 'cnc_worksheet': cnc_rework.cnc_worksheet}) - new_pre_workorder = self.production_id.workorder_ids.filtered(lambda - p: p.routing_type == '装夹预调' and p.processing_panel == panel.name and p.state not in ( - 'rework', 'done')) + if new_pre_workorder: pre_rework = max(self.production_id.workorder_ids.filtered( lambda pr: pr.processing_panel == panel.name and pr.state in ( diff --git a/sf_manufacturing/wizard/rework_wizard_views.xml b/sf_manufacturing/wizard/rework_wizard_views.xml index 8ba3f4dd..d8cf0fb9 100644 --- a/sf_manufacturing/wizard/rework_wizard_views.xml +++ b/sf_manufacturing/wizard/rework_wizard_views.xml @@ -14,17 +14,25 @@ + +
+ 保留装夹测量数据 + + +
- 注意: 该制造订单产品已申请重新编程次数为,且当前编程状态为 - + + 注意: 该制造订单产品已申请重新编程次数为,且当前编程状态为 + +
申请重新编程 diff --git a/sf_sale/models/quick_easy_order.py b/sf_sale/models/quick_easy_order.py index 081807a4..cb1886a1 100644 --- a/sf_sale/models/quick_easy_order.py +++ b/sf_sale/models/quick_easy_order.py @@ -8,8 +8,8 @@ from datetime import datetime import requests from odoo import http from odoo.http import request -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file from odoo import models, fields, api from odoo.modules import get_resource_path from odoo.exceptions import ValidationError, UserError diff --git a/sf_sale/models/quick_easy_order_old.py b/sf_sale/models/quick_easy_order_old.py index 3ae65db3..92f6cda2 100644 --- a/sf_sale/models/quick_easy_order_old.py +++ b/sf_sale/models/quick_easy_order_old.py @@ -6,8 +6,8 @@ import os from datetime import datetime from stl import mesh # from OCC.Core.GProp import GProp_GProps -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file from odoo.addons.sf_base.commons.common import Common from odoo import models, fields, api from odoo.modules import get_resource_path From 69578ab054c49fac5775f9fdfecf0c24bd0e3b53 Mon Sep 17 00:00:00 2001 From: hujiaying Date: Wed, 4 Sep 2024 17:28:26 +0800 Subject: [PATCH 08/23] =?UTF-8?q?bfm=E6=96=B0=E5=A2=9E=E5=BA=93=E5=AD=98?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=EF=BC=8C=E4=BB=A3=E5=8F=91=E8=B4=A7=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=EF=BC=8C=E5=A4=84=E7=90=86sf=E4=B8=80=E6=AC=A1?= =?UTF-8?q?=E6=80=A7=E5=8F=91=E8=B4=A7=EF=BC=8Cbfm=E7=94=9F=E6=88=90?= =?UTF-8?q?=E4=BB=A3=E5=8F=91=E8=B4=A7=E5=90=8D=E5=AD=97=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_stock/models/stock_picking.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sf_stock/models/stock_picking.py b/sf_stock/models/stock_picking.py index 37f24bf0..82ce7ea5 100644 --- a/sf_stock/models/stock_picking.py +++ b/sf_stock/models/stock_picking.py @@ -69,6 +69,7 @@ class StockPicking(models.Model): 'move_ids': move_ids, 'move_line_ids': move_line_ids, 'state': item.state, + 'move_type': item.move_type, } backorder_ids.append(val) return backorder_ids @@ -94,6 +95,7 @@ class StockPicking(models.Model): 'backorder_id': self.deal_send_backorder_id(self.backorder_id), 'backorder_ids': self.deal_send_backorder_id(self.backorder_ids), 'cancel_backorder_ids': skip_backorder, + 'move_type': self.move_type, }, } url1 = config['bfm_url_new'] + '/api/stock/deliver_goods' From ca1060ada5570873f13ed38b5b7ebce259fcbfbb Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Wed, 4 Sep 2024 17:33:54 +0800 Subject: [PATCH 09/23] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/product_template.py | 4 ++-- sf_sale/models/quick_easy_order.py | 4 ++-- sf_sale/models/quick_easy_order_old.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index 37fa02bd..071f1167 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -9,8 +9,8 @@ from odoo.exceptions import ValidationError, UserError from odoo.modules import get_resource_path -# from OCC.Extend.DataExchange import read_step_file -# from OCC.Extend.DataExchange import write_stl_file +from OCC.Extend.DataExchange import read_step_file +from OCC.Extend.DataExchange import write_stl_file class ResProductMo(models.Model): diff --git a/sf_sale/models/quick_easy_order.py b/sf_sale/models/quick_easy_order.py index cb1886a1..081807a4 100644 --- a/sf_sale/models/quick_easy_order.py +++ b/sf_sale/models/quick_easy_order.py @@ -8,8 +8,8 @@ from datetime import datetime import requests from odoo import http from odoo.http import request -# from OCC.Extend.DataExchange import read_step_file -# from OCC.Extend.DataExchange import write_stl_file +from OCC.Extend.DataExchange import read_step_file +from OCC.Extend.DataExchange import write_stl_file from odoo import models, fields, api from odoo.modules import get_resource_path from odoo.exceptions import ValidationError, UserError diff --git a/sf_sale/models/quick_easy_order_old.py b/sf_sale/models/quick_easy_order_old.py index 92f6cda2..3ae65db3 100644 --- a/sf_sale/models/quick_easy_order_old.py +++ b/sf_sale/models/quick_easy_order_old.py @@ -6,8 +6,8 @@ import os from datetime import datetime from stl import mesh # from OCC.Core.GProp import GProp_GProps -# from OCC.Extend.DataExchange import read_step_file -# from OCC.Extend.DataExchange import write_stl_file +from OCC.Extend.DataExchange import read_step_file +from OCC.Extend.DataExchange import write_stl_file from odoo.addons.sf_base.commons.common import Common from odoo import models, fields, api from odoo.modules import get_resource_path From a7e1c89e660d8cc38292c4145fbe7c746321b4e5 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Wed, 4 Sep 2024 17:36:41 +0800 Subject: [PATCH 10/23] =?UTF-8?q?=E8=BF=98=E5=8E=9F=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/views/mrp_workorder_view.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index 512534d4..a802266f 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -486,8 +486,8 @@
- - + +
Date: Wed, 4 Sep 2024 17:43:48 +0800 Subject: [PATCH 11/23] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=BF=94=E5=B7=A5?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/wizard/rework_wizard.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sf_manufacturing/wizard/rework_wizard.py b/sf_manufacturing/wizard/rework_wizard.py index 51d40ac3..4698a994 100644 --- a/sf_manufacturing/wizard/rework_wizard.py +++ b/sf_manufacturing/wizard/rework_wizard.py @@ -63,11 +63,12 @@ class ReworkWizard(models.TransientModel): for panel in self.processing_panel_id: panel_workorder = self.production_id.workorder_ids.filtered( lambda ap: ap.processing_panel == panel.name and ap.state != 'rework') - rework_clamp_workorder = max(panel_workorder.filtered( - lambda rp: rp.processing_panel == panel.name and rp.routing_type == '装夹预调' and rp.state in [ - 'done', 'rework'])) if panel_workorder: panel_workorder.write({'state': 'rework'}) + rework_clamp_workorder = max(panel_workorder.filtered( + lambda + rp: rp.processing_panel == panel.name and rp.routing_type == '装夹预调' and rp.state in [ + 'done', 'rework'])) # panel_workorder.filtered( # lambda wo: wo.routing_type == '装夹预调').workpiece_delivery_ids.filtered( # lambda wd: wd.status == '待下发').write({'status': '已取消'}) From 005a7bb68ea634e38b10a314f471a07483609c10 Mon Sep 17 00:00:00 2001 From: guanhuan Date: Thu, 5 Sep 2024 08:51:36 +0800 Subject: [PATCH 12/23] =?UTF-8?q?=E5=BB=BA=E7=AB=8B=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E7=BB=B4=E4=BF=9D=E6=A0=87=E5=87=86,=E5=BB=BA=E7=AB=8B?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E7=BB=B4=E4=BF=9D=E6=A0=87=E5=87=86=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sf_equipment_maintenance_standards.py | 1 + .../equipment_maintenance_standards_views.xml | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/sf_maintenance/models/sf_equipment_maintenance_standards.py b/sf_maintenance/models/sf_equipment_maintenance_standards.py index 92d075e1..0cd3c81c 100644 --- a/sf_maintenance/models/sf_equipment_maintenance_standards.py +++ b/sf_maintenance/models/sf_equipment_maintenance_standards.py @@ -24,6 +24,7 @@ class SfEquipmentSaintenanceStandards(models.Model): remark = fields.Char('备注') maintenance_type = fields.Selection([('保养', '保养'), ("检修", "检修")], string='类型', default='保养') name = fields.Char(string='名称') + active = fields.Boolean(default=True) @api.model_create_multi def create(self, vals_list): diff --git a/sf_maintenance/views/equipment_maintenance_standards_views.xml b/sf_maintenance/views/equipment_maintenance_standards_views.xml index 1af9bfc5..1389633b 100644 --- a/sf_maintenance/views/equipment_maintenance_standards_views.xml +++ b/sf_maintenance/views/equipment_maintenance_standards_views.xml @@ -6,15 +6,16 @@ equipment.maintenance.standards.form equipment.maintenance.standards -
+ - - - - - - + + + + + + + @@ -50,7 +51,8 @@ equipment.maintenance.standards.tree equipment.maintenance.standards - + + From eff39a39e3c66d818cca84be838610ba325d2fe9 Mon Sep 17 00:00:00 2001 From: hujiaying Date: Thu, 5 Sep 2024 09:24:45 +0800 Subject: [PATCH 13/23] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20cloud=E7=AB=AF?= =?UTF-8?q?=E6=96=B0=E5=BB=BA=E8=A1=A8=E9=9D=A2=E5=B7=A5=E8=89=BA=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E5=BF=85=E5=A1=AB=E5=8F=82=E6=95=B0=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E5=A1=AB=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_base/views/common_view.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sf_base/views/common_view.xml b/sf_base/views/common_view.xml index 334eaa32..691eb208 100644 --- a/sf_base/views/common_view.xml +++ b/sf_base/views/common_view.xml @@ -26,19 +26,19 @@ - - + + - - - + + + - + From 54d9902ae45eac3bf20334156f8615f8f612b950 Mon Sep 17 00:00:00 2001 From: hujiaying Date: Thu, 5 Sep 2024 09:26:05 +0800 Subject: [PATCH 14/23] =?UTF-8?q?=E6=92=A4=E5=9B=9E=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_base/views/common_view.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/sf_base/views/common_view.xml b/sf_base/views/common_view.xml index 691eb208..28f228f1 100644 --- a/sf_base/views/common_view.xml +++ b/sf_base/views/common_view.xml @@ -12,7 +12,6 @@ - sf.production.process.parameter From 00809d88f606fb4fb8eecf478f67e18200bcded4 Mon Sep 17 00:00:00 2001 From: hujiaying Date: Thu, 5 Sep 2024 09:53:32 +0800 Subject: [PATCH 15/23] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=89=93=E5=8D=B0?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_bf_connect/models/process_status.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_bf_connect/models/process_status.py b/sf_bf_connect/models/process_status.py index f4c4d859..111254c7 100644 --- a/sf_bf_connect/models/process_status.py +++ b/sf_bf_connect/models/process_status.py @@ -53,7 +53,7 @@ class StatusChange(models.Model): if not ret.get('error'): logging.info('接口已经执行=============') else: - logging.error('工厂加工同步订单状态失败 {}'.format(ret.text)) + logging.error('工厂加工同步订单状态失败 {}'.format(ret)) raise UserError('工厂加工同步订单状态失败') except UserError as e: logging.error('工厂加工同步订单状态失败 {}'.format(e)) From 5f218e69d4793d9915c5b5c8db111a120631a5a7 Mon Sep 17 00:00:00 2001 From: hujiaying Date: Thu, 5 Sep 2024 17:39:09 +0800 Subject: [PATCH 16/23] =?UTF-8?q?=E8=AE=A1=E5=88=92=E6=8E=92=E7=A8=8B?= =?UTF-8?q?=E8=80=83=E8=99=91CNC=E7=94=9F=E4=BA=A7=E7=BA=BF=E6=97=A5?= =?UTF-8?q?=E4=BA=A7=E8=83=BD=E7=9A=84=E4=BC=98=E5=8C=96=E9=9C=80=E6=B1=82?= =?UTF-8?q?,=E6=96=B0=E5=A2=9E=E5=8F=AF=E7=94=A8=E6=9C=BA=E5=8F=B0?= =?UTF-8?q?=E6=95=B0=E9=87=8F=EF=BC=8C=E5=8D=95=E5=8F=B0=E5=B0=8F=E6=97=B6?= =?UTF-8?q?=E4=BA=A7=E8=83=BD=EF=BC=8C=E6=97=A5=E6=9C=89=E6=95=88=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=97=B6=E9=95=BF=E8=AE=A1=E7=AE=97=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workcenter.py | 45 +++++++- .../views/mrp_workcenter_views.xml | 101 +++++++++++------- 2 files changed, 103 insertions(+), 43 deletions(-) diff --git a/sf_manufacturing/models/mrp_workcenter.py b/sf_manufacturing/models/mrp_workcenter.py index 03597980..ecb29ad7 100644 --- a/sf_manufacturing/models/mrp_workcenter.py +++ b/sf_manufacturing/models/mrp_workcenter.py @@ -1,6 +1,6 @@ import datetime from collections import defaultdict -from odoo import fields, models +from odoo import fields, models, api from odoo.addons.resource.models.resource import Intervals @@ -41,14 +41,16 @@ class ResWorkcenter(models.Model): oee_target = fields.Float( string='OEE Target', help="Overall Effective Efficiency Target in percentage", default=90, tracking=True) - oee = fields.Float(compute='_compute_oee', help='Overall Equipment Effectiveness, based on the last month', store=True) + oee = fields.Float(compute='_compute_oee', help='Overall Equipment Effectiveness, based on the last month', + store=True) time_start = fields.Float('Setup Time', tracking=True) time_stop = fields.Float('Cleanup Time', tracking=True) costs_hour = fields.Float(string='Cost per hour', help='Hourly processing cost.', default=0.0, tracking=True) equipment_status = fields.Selection( - [("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"), ("封存(报废)", "封存(报废)")], + [("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"), + ("封存(报废)", "封存(报废)")], string="设备状态", related='equipment_id.state') # @api.depends('equipment_id') @@ -127,6 +129,43 @@ class ResWorkcenter(models.Model): # AGV是否可配送 is_agv_scheduling = fields.Boolean(string="AGV所属区域", tracking=True) + # 生产线优化 + available_machine_number = fields.Integer(string="可用机台数量") + single_machine_capacity = fields.Float(string="单台小时产能") + production_line_hour_capacity = fields.Float(string="生产线小时产能", readonly=True, + _compute='_compute_production_line_hour_capacity') + effective_working_hours_day = fields.Float(string="日有效工作时长", default=0, readonly=True, + _compute='_compute_effective_working_hours_day') + default_capacity = fields.Float( + '生产线日产能', default=2.0, _compute='_compute_production_line_day_capacity', readonly=True) + + # 计算生产线日产能 + @api.depends('production_line_hour_capacity', 'effective_working_hours_day') + def _compute_production_line_day_capacity(self): + for record in self: + record.default_capacity = round( + record.production_line_hour_capacity * record.effective_working_hours_day, 2) + + # 计算日有效工作时长 + @api.depends('attendance_ids', 'attendance_ids.hour_to', 'attendance_ids.hour_from') + def _compute_effective_working_hours_day(self): + for record in self: + attendance_ids = record.resource_calendar_id.attendance_ids.filter( + lambda r: r.dayofweek == datetime.now().weekday()) + if attendance_ids: + for attendance_id in attendance_ids: + if attendance_id.hour_from and attendance_id.hour_to: + record.effective_working_hours_day += attendance_id.hour_to - attendance_id.hour_from + else: + record.effective_working_hours_day = 0 + + # 计算生产线小时产能 + @api.depends('single_machine_capacity', 'available_machine_number') + def _compute_production_line_hour_capacity(self): + for record in self: + record.production_line_hour_capacity = round( + record.single_machine_capacity * record.available_machine_number, 2) + class ResWorkcenterProductivity(models.Model): _inherit = 'mrp.workcenter.productivity' diff --git a/sf_manufacturing/views/mrp_workcenter_views.xml b/sf_manufacturing/views/mrp_workcenter_views.xml index d0b4bee6..aad35d04 100644 --- a/sf_manufacturing/views/mrp_workcenter_views.xml +++ b/sf_manufacturing/views/mrp_workcenter_views.xml @@ -6,9 +6,9 @@ mrp.production - - - + + +
- 产线日产能 + 1 + + + + - - - - - - + diff --git a/sf_plan/models/custom_plan.py b/sf_plan/models/custom_plan.py index a1c57f2a..c4043d33 100644 --- a/sf_plan/models/custom_plan.py +++ b/sf_plan/models/custom_plan.py @@ -199,7 +199,7 @@ class sf_production_plan(models.Model): if not record.production_line_id: raise ValidationError("未选择生产线") else: - date_planned_start = date_planned_start + timedelta(hours=8) # 转换为北京时间 + is_schedule = self.deal_processing_schedule(date_planned_start) if not is_schedule: raise ValidationError("排程失败") @@ -262,16 +262,17 @@ class sf_production_plan(models.Model): production_lines = workcenter_ids.filtered(lambda b: "自动生产线" in b.name) if not production_lines: # 判断是否配置了自动生产线 raise UserError('生产线没有配置自动生产线') + if date_planned_start < datetime.now(): # 判断计划开始时间是否小于当前时间 + raise UserError('计划开始时间不能小于当前时间') if all(not production_line.deal_with_workcenter_calendar(date_planned_start) for production_line in production_lines): # 判断计划开始时间是否在配置的工作中心的工作日历内 - raise UserError('当前计划开始时间不能预约排程') - if not production_lines.deal_production_lines_available(date_planned_start): # 判断生产线是否可排程 - raise UserError('当前计划开始时间不能预约排程,生产线没有可排程的资源') + raise UserError('当前计划开始时间不能预约排程,请在工作时间内排程') + if not production_lines.deal_available_default_capacity(date_planned_start): # 判断生产线是否可排程 + raise UserError('当前计划开始时间不能预约排程,生产线今日没有可排程的资源') + if not production_lines.deal_available_single_machine_capacity(date_planned_start): # 判断生产线是否可排程 + raise UserError('当前计划开始时间不能预约排程,生产线该时间段没有可排程的资源') return True - - - def calculate_plan_time_before(self, item, workorder_id_list): """ 根据CNC工单的时间去计算之前的其他工单的开始结束时间