From 1e172cb4e35970885e0b76d5cd1cce3fc85514e7 Mon Sep 17 00:00:00 2001 From: hujiaying Date: Tue, 27 Aug 2024 17:24:04 +0800 Subject: [PATCH 01/39] =?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 3624ef47553183cbae6a58866e76874e4c1be67e Mon Sep 17 00:00:00 2001 From: liaodanlong Date: Fri, 30 Aug 2024 16:30:34 +0800 Subject: [PATCH 02/39] =?UTF-8?q?=E9=94=80=E5=94=AE=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E4=BB=B7=E6=A0=BC=E9=97=AE=E9=A2=98=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/views/mrp_workorder_view.xml | 2 +- sf_mrs_connect/models/res_config_setting.py | 78 ++++++++++++++++++- .../views/res_config_settings_views.xml | 15 ++++ 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index 457ac122..a41cad09 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -37,7 +37,7 @@ - + diff --git a/sf_mrs_connect/models/res_config_setting.py b/sf_mrs_connect/models/res_config_setting.py index 159e8d48..e1bd6de1 100644 --- a/sf_mrs_connect/models/res_config_setting.py +++ b/sf_mrs_connect/models/res_config_setting.py @@ -1,8 +1,11 @@ # -*- coding: utf-8 -*- # Part of SmartGo. See LICENSE file for full copyright and licensing details. import logging + +import requests + from odoo import api, fields, models -from odoo.exceptions import ValidationError +from odoo.exceptions import ValidationError, UserError _logger = logging.getLogger(__name__) @@ -144,3 +147,76 @@ class ResConfigSettings(models.TransientModel): ir_config.set_param("ftp_user", self.ftp_user or "") ir_config.set_param("ftp_password", self.ftp_password or "") ir_config.set_param("enable_tool_presetter", self.enable_tool_presetter or False) + + def sync_sale_price(self): + self.get_page_all_records(self.sale_order_price_process) + + def sale_order_price_process(self, datas): + if not datas: + return + try: + convert_sale_data = map(lambda data: + {'name': data.name, 'order_lines': { + '%s/%s/%s/%s/±%s/' % ( + order_line.product_template_id.model_long, order_line.product_template_id.model_width, order_line.product_template_id.model_height, + order_line.product_template_id.model_volume, + order_line.product_template_id.model_machining_precision, + ): order_line.price_unit for order_line in + data.order_line + } + }, + datas) + config = self.env['res.config.settings'].get_values() + url = config['bfm_url_new'] + '/api/sync/order/price' + json_data = { + 'params': { + 'data': list(convert_sale_data), + }, + } + response = requests.post(url, json=json_data, data=None) + response = response.json() + if not response.get('error'): + result = response.get('result') + for need_change_sale_data in result: + res_order_lines_map = need_change_sale_data.get('order_lines') + if not res_order_lines_map: + continue + need_change_sale_order = self.env['sale.order'].sudo().search([('name', '=', need_change_sale_data.get('name'))]) + + for need_change_sale_order_line in need_change_sale_order.order_line: + order_line_uniq='%s/%s/%s/%s/±%s/' % ( + need_change_sale_order_line.product_template_id.model_long, need_change_sale_order_line.product_template_id.model_width, + need_change_sale_order_line.product_template_id.model_height, + need_change_sale_order_line.product_template_id.model_volume, + need_change_sale_order_line.product_template_id.model_machining_precision, + ) + if not res_order_lines_map.get(order_line_uniq): + continue + need_change_sale_order_line.write({'price_unit': res_order_lines_map.get(order_line_uniq)}) + else: + logging.error('同步销售订单价格失败 {}'.format(response.text)) + raise UserError('同步销售订单价格失败') + except Exception as e: + raise UserError(e) + + def get_page_all_records(self, func, page_size=100): + # 获取模型对象 + model = self.env['sale.order'].sudo() + + # 初始化分页参数 + page_number = 1 + while True: + # 计算偏移量 + offset = (page_number - 1) * page_size + + # 获取当前页的数据 + records = model.search([], limit=page_size, offset=offset) + + # 如果没有更多记录,退出循环 + if not records: + break + + # 将当前页的数据添加到结果列表 + func(records) + # 增加页码 + page_number += 1 \ No newline at end of file diff --git a/sf_mrs_connect/views/res_config_settings_views.xml b/sf_mrs_connect/views/res_config_settings_views.xml index 05e5be41..651e6f15 100644 --- a/sf_mrs_connect/views/res_config_settings_views.xml +++ b/sf_mrs_connect/views/res_config_settings_views.xml @@ -129,6 +129,21 @@ +
+

销售订单价格同步

+
+
+
+
+
+
+
+
+
+
From 0ca6d46a7bfc81b094a217484a39879d4edbbb70 Mon Sep 17 00:00:00 2001 From: hujiaying Date: Sat, 31 Aug 2024 21:09:56 +0800 Subject: [PATCH 03/39] =?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 fc1cdf4d0eae06756c78ea73de9686e013c6e61d Mon Sep 17 00:00:00 2001 From: hujiaying Date: Mon, 2 Sep 2024 19:02:53 +0800 Subject: [PATCH 04/39] =?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 6e9c326a52f74df2d02fdc6d0f0c167a1dc33ec4 Mon Sep 17 00:00:00 2001 From: liaodanlong Date: Tue, 3 Sep 2024 13:56:16 +0800 Subject: [PATCH 05/39] =?UTF-8?q?=E6=99=BA=E8=83=BD=E5=B7=A5=E5=8E=82?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=90=8C=E6=AD=A5=E4=BB=BB=E5=8A=A1=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=8F=90=E7=A4=BA=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_mrs_connect/models/res_config_setting.py | 2 +- sf_mrs_connect/models/sync_common.py | 2 +- sf_tool_management/models/functional_tool_enroll.py | 8 ++++---- sf_warehouse/models/sync_common.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sf_mrs_connect/models/res_config_setting.py b/sf_mrs_connect/models/res_config_setting.py index e1bd6de1..ead17af5 100644 --- a/sf_mrs_connect/models/res_config_setting.py +++ b/sf_mrs_connect/models/res_config_setting.py @@ -89,7 +89,7 @@ class ResConfigSettings(models.TransientModel): _logger.info("同步刀具物料每齿走刀量完成") except Exception as e: - _logger.info("捕获错误信息:%s" % e) + _logger.info("sf_all_sync error: %s" % e) raise ValidationError("数据错误导致同步失败,请联系管理员") @api.model diff --git a/sf_mrs_connect/models/sync_common.py b/sf_mrs_connect/models/sync_common.py index e812bd03..2f77c7e6 100644 --- a/sf_mrs_connect/models/sync_common.py +++ b/sf_mrs_connect/models/sync_common.py @@ -73,7 +73,7 @@ class MrStaticResourceDataSync(models.Model): self.env['sf.feed.per.tooth'].sync_feed_per_tooth_yesterday() _logger.info("同步刀具物料每齿走刀量完成") except Exception as e: - logging.info("捕获错误信息:%s" % e) + logging.info("同步静态资源库失败:%s" % e) raise ValidationError("数据错误导致同步失败,请联系管理员") diff --git a/sf_tool_management/models/functional_tool_enroll.py b/sf_tool_management/models/functional_tool_enroll.py index ba3553e1..ab391511 100644 --- a/sf_tool_management/models/functional_tool_enroll.py +++ b/sf_tool_management/models/functional_tool_enroll.py @@ -50,7 +50,7 @@ class ToolDatasync(models.Model): # self.env['sf.real.time.distribution.of.functional.tools'].sudo().sync_enroll_functional_tool_real_time_distribution_all() # logging.info("功能刀具安全库存每日同步成功") except Exception as e: - logging.info("捕获错误信息:%s" % e) + logging.info("刀具物料、刀具信息同步失败:%s" % e) raise ValidationError("数据错误导致同步失败,请联系管理员") @@ -312,7 +312,7 @@ class FunctionalToolWarning(models.Model): else: logging.info('没有注册功能刀具预警信息') except Exception as e: - logging.info("捕获错误信息:%s" % e) + logging.info("功能刀具预警同步失败:%s" % e) class StockMoveLine(models.Model): @@ -373,7 +373,7 @@ class StockMoveLine(models.Model): else: logging.info('没有注册功能刀具出入库记录信息') except Exception as e: - logging.info("捕获错误信息:%s" % e) + logging.info("出入库记录信息同步失败:%s" % e) class RealTimeDistributionFunctionalTools(models.Model): @@ -446,4 +446,4 @@ class RealTimeDistributionFunctionalTools(models.Model): else: logging.info('没有注册功能刀具出入库记录信息') except Exception as e: - logging.info("捕获错误信息:%s" % e) + logging.info("实时功能刀具同步失败:%s" % e) diff --git a/sf_warehouse/models/sync_common.py b/sf_warehouse/models/sync_common.py index aaa186f9..d8f075dd 100644 --- a/sf_warehouse/models/sync_common.py +++ b/sf_warehouse/models/sync_common.py @@ -139,5 +139,5 @@ class MrsShelfLocationDataSync(models.Model): location_id.product_sn_id = False except Exception as e: - logging.info("捕获错误信息:%s" % e) + logging.info("库区信息同步失败:%s" % e) raise ValidationError("数据错误导致同步失败,请联系管理员") From 589035d42bcbdcccdcf07e56e5132cdcfdb158aa Mon Sep 17 00:00:00 2001 From: hujiaying Date: Tue, 3 Sep 2024 19:14:48 +0800 Subject: [PATCH 06/39] =?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 69578ab054c49fac5775f9fdfecf0c24bd0e3b53 Mon Sep 17 00:00:00 2001 From: hujiaying Date: Wed, 4 Sep 2024 17:28:26 +0800 Subject: [PATCH 07/39] =?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 005a7bb68ea634e38b10a314f471a07483609c10 Mon Sep 17 00:00:00 2001 From: guanhuan Date: Thu, 5 Sep 2024 08:51:36 +0800 Subject: [PATCH 08/39] =?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 09/39] =?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 10/39] =?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 11/39] =?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 12/39] =?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工单的时间去计算之前的其他工单的开始结束时间 From dba8d233485af72192c850734e1c879be22b8892 Mon Sep 17 00:00:00 2001 From: liaodanlong Date: Mon, 9 Sep 2024 17:11:33 +0800 Subject: [PATCH 21/39] =?UTF-8?q?=E9=94=80=E5=94=AE=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E4=BB=B7=E6=A0=BC=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_mrs_connect/models/res_config_setting.py | 24 +++++++-------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/sf_mrs_connect/models/res_config_setting.py b/sf_mrs_connect/models/res_config_setting.py index ead17af5..04693fa7 100644 --- a/sf_mrs_connect/models/res_config_setting.py +++ b/sf_mrs_connect/models/res_config_setting.py @@ -157,12 +157,7 @@ class ResConfigSettings(models.TransientModel): try: convert_sale_data = map(lambda data: {'name': data.name, 'order_lines': { - '%s/%s/%s/%s/±%s/' % ( - order_line.product_template_id.model_long, order_line.product_template_id.model_width, order_line.product_template_id.model_height, - order_line.product_template_id.model_volume, - order_line.product_template_id.model_machining_precision, - ): order_line.price_unit for order_line in - data.order_line + str(i): str(value.price_unit) for i, value in enumerate(data.order_line) } }, datas) @@ -182,17 +177,14 @@ class ResConfigSettings(models.TransientModel): if not res_order_lines_map: continue need_change_sale_order = self.env['sale.order'].sudo().search([('name', '=', need_change_sale_data.get('name'))]) - - for need_change_sale_order_line in need_change_sale_order.order_line: - order_line_uniq='%s/%s/%s/%s/±%s/' % ( - need_change_sale_order_line.product_template_id.model_long, need_change_sale_order_line.product_template_id.model_width, - need_change_sale_order_line.product_template_id.model_height, - need_change_sale_order_line.product_template_id.model_volume, - need_change_sale_order_line.product_template_id.model_machining_precision, - ) - if not res_order_lines_map.get(order_line_uniq): + for index,need_change_sale_order_line in enumerate(need_change_sale_order.order_line): + if not res_order_lines_map.get(str(index)): continue - need_change_sale_order_line.write({'price_unit': res_order_lines_map.get(order_line_uniq)}) + order_line = self.env['sale.order.line'].browse(need_change_sale_order_line.id) + new_price = res_order_lines_map.get(str(index)) + if order_line: + # 修改单价 + order_line.write({'remark': new_price}) else: logging.error('同步销售订单价格失败 {}'.format(response.text)) raise UserError('同步销售订单价格失败') From 7ac7077f8c2f4c5dce425bd2ccb012495602d36c Mon Sep 17 00:00:00 2001 From: liaodanlong Date: Mon, 9 Sep 2024 17:36:23 +0800 Subject: [PATCH 22/39] =?UTF-8?q?bom=E7=89=A9=E6=96=99=E6=B8=85=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_base/views/tool_views.xml | 8 +- sf_tool_management/__manifest__.py | 7 +- sf_tool_management/models/__init__.py | 4 +- .../models/functional_cutting_tool_model.py | 6 ++ sf_tool_management/models/jikimo_bom.py | 96 +++++++++++++++++++ sf_tool_management/models/tool_inventory.py | 34 +++++++ .../security/ir.model.access.csv | 3 + sf_tool_management/views/jikimo_bom.xml | 51 ++++++++++ sf_tool_management/views/tool_inventory.xml | 15 +++ sf_tool_management/views/tool_views.xml | 18 ++++ sf_tool_management/wizard/__init__.py | 1 + .../wizard/jikimo_bom_wizard.py | 28 ++++++ .../wizard/jikimo_bom_wizard.xml | 33 +++++++ 13 files changed, 298 insertions(+), 6 deletions(-) create mode 100644 sf_tool_management/models/functional_cutting_tool_model.py create mode 100644 sf_tool_management/models/jikimo_bom.py create mode 100644 sf_tool_management/models/tool_inventory.py create mode 100644 sf_tool_management/views/jikimo_bom.xml create mode 100644 sf_tool_management/views/tool_inventory.xml create mode 100644 sf_tool_management/views/tool_views.xml create mode 100644 sf_tool_management/wizard/jikimo_bom_wizard.py create mode 100644 sf_tool_management/wizard/jikimo_bom_wizard.xml diff --git a/sf_base/views/tool_views.xml b/sf_base/views/tool_views.xml index 87dbd94c..b90d1a5c 100644 --- a/sf_base/views/tool_views.xml +++ b/sf_base/views/tool_views.xml @@ -80,10 +80,10 @@ sf.cutter.function.tree sf.functional.cutting.tool.model - - - - + + + +
diff --git a/sf_tool_management/__manifest__.py b/sf_tool_management/__manifest__.py index a1a88fb0..97c26e40 100644 --- a/sf_tool_management/__manifest__.py +++ b/sf_tool_management/__manifest__.py @@ -10,7 +10,7 @@ """, 'category': 'sf', 'website': 'https://www.sf.jikimo.com', - 'depends': ['sf_manufacturing'], + 'depends': ['sf_manufacturing', 'sf_base'], 'data': [ 'security/group_security.xml', 'security/ir.model.access.csv', @@ -24,6 +24,11 @@ 'views/menu_view.xml', 'views/stock.xml', 'data/tool_data.xml', + 'wizard/jikimo_bom_wizard.xml', + 'views/tool_inventory.xml', + 'views/jikimo_bom.xml', + 'views/tool_views.xml', + ], 'demo': [ ], diff --git a/sf_tool_management/models/__init__.py b/sf_tool_management/models/__init__.py index 90776ca7..e4f2a622 100644 --- a/sf_tool_management/models/__init__.py +++ b/sf_tool_management/models/__init__.py @@ -8,4 +8,6 @@ from . import fixture_material_search from . import fixture_enroll from . import temporary_data_processing_methods from . import stock - +from . import jikimo_bom +from . import tool_inventory +from . import functional_cutting_tool_model \ No newline at end of file diff --git a/sf_tool_management/models/functional_cutting_tool_model.py b/sf_tool_management/models/functional_cutting_tool_model.py new file mode 100644 index 00000000..9b5a5002 --- /dev/null +++ b/sf_tool_management/models/functional_cutting_tool_model.py @@ -0,0 +1,6 @@ +from odoo import models, fields + + +class SyncFunctionalCuttingToolModel(models.Model): + _inherit = 'sf.functional.cutting.tool.model' + cutting_tool_type_ids = fields.Many2many('sf.cutting.tool.type', string='整体式刀具物料') \ No newline at end of file diff --git a/sf_tool_management/models/jikimo_bom.py b/sf_tool_management/models/jikimo_bom.py new file mode 100644 index 00000000..5272d4f0 --- /dev/null +++ b/sf_tool_management/models/jikimo_bom.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +from xml import etree + +from odoo import models, fields, api, Command +from odoo.http import request + + +class jikimo_bom(models.Model): + _name = 'jikimo.bom' + _description = '功能刀具物料清单' + tool_inventory_id = fields.Many2one('sf.tool.inventory', '功能刀具清单') + tool_name = fields.Char(related="tool_inventory_id.name", string='功能刀具名称') + functional_cutting_tool_model_id = fields.Many2one(related='tool_inventory_id.functional_cutting_tool_model_id', + string='功能刀具类型') + tool_groups_id = fields.Many2one(related='tool_inventory_id.tool_groups_id', string='刀具组') + tool_length = fields.Float(related='tool_inventory_id.tool_length', string='刀具总长(mm)') + diameter = fields.Float(related='tool_inventory_id.diameter', string='直径(mm)') + angle = fields.Float(related='tool_inventory_id.angle', string='R角(mm)') + extension = fields.Float(related='tool_inventory_id.extension', string='伸出长度(mm)') + product_ids = fields.Many2many('product.product', string='产品') + knife_handle_model = fields.Selection(related='tool_inventory_id.knife_handle_model', string='使用刀柄型号') + options = fields.Char('产品清单') + + def name_get(self): + result = [] + for bom in self: + result.append((bom.id, '功能刀具物料清单')) + return result + def bom_product_domains(self, assembly_options): + self.options = assembly_options + cutting_tool_materials = self.env['sf.cutting.tool.material'].search( + [('name', 'in', assembly_options.split('+'))]) + domains = [] + for index, option in enumerate(cutting_tool_materials): + domain = ['&',('cutting_tool_material_id', '=', option.id), + ("cutting_tool_type_id", "in", + self.tool_inventory_id.functional_cutting_tool_model_id.cutting_tool_type_ids.ids)] + if option.name == '刀柄': + domain = ['&']+domain+[ ("cutting_tool_taper_shank_model", "=", self.tool_inventory_id.knife_handle_model)] + + if option.name == '整体式刀具': + domain=['&']+domain+[ + '|', + # 刀具直径 + ('cutting_tool_blade_diameter', '=', self.tool_inventory_id.diameter), + + # r角 + ('cutting_tool_blade_tip_working_size', '=', self.tool_inventory_id.angle)] + if option.name == '刀杆': + domain = ['&'] + domain + [ + ("cutting_tool_cutter_arbor_diameter", "=", self.tool_inventory_id.diameter)] + if option.name == '刀片': + domain = ['&'] + domain + [ + ("cutting_tool_blade_tip_circular_arc_radius", "=", self.tool_inventory_id.angle)] + if option.name == '刀盘': + domain = ['&'] + domain + [ + ("cutting_tool_cutter_head_diameter", "=", self.tool_inventory_id.diameter)] + domains=domains+domain + if index != 0: + domains = ['|'] + domains + # wqwqwe = self.env['product.product'].search(ddd) + # product = self.env['product.product'].search(domain) + # if product: + # products = products + product + return domains + + def generate_bill_materials(self, assembly_options): + domains=self.bom_product_domains(assembly_options) + products = self.env['product.product'].search(domains) + if products: + self.product_ids = [Command.set(products.ids)] + # if option.name == '刀盘': + # hilt = self.env['product.product'].search( + # [('cutting_tool_blade_diameter', '=', self.tool_inventory_id.diameter), + # ('cutting_tool_material_id', '=', option.id)]) + # self.product_ids = [Command.set(hilt.ids)]k + + +class jikimo_bom_line(models.Model): + _name = 'jikimo.bom.line' + _description = 'jikimo.bom.line' + + name = fields.Char() + + +class ProductProduct(models.Model): + _inherit = 'product.product' + + def search(self, args, offset=0, limit=None, order=None, count=False): + # 你可以在这里修改 `args` 以调整搜索条件 + # 例如,添加额外的搜索条件 + if self.env.context.get('jikimo_bom_product'): + bom_id = self.env['jikimo.bom'].browse(request.session.get('jikimo_bom_product').get('bom_id')) + domains = bom_id.bom_product_domains(bom_id.options) + args=args+domains + return super(ProductProduct, self).search(args, offset=offset, limit=limit, order=order, count=count) diff --git a/sf_tool_management/models/tool_inventory.py b/sf_tool_management/models/tool_inventory.py new file mode 100644 index 00000000..db15834a --- /dev/null +++ b/sf_tool_management/models/tool_inventory.py @@ -0,0 +1,34 @@ +from odoo import models, fields +from odoo.http import request + + +class ToolInventory(models.Model): + _inherit = 'sf.tool.inventory' + _description = '功能刀具清单' + knife_handle_model = fields.Selection([('BT30', 'BT30'), ('BT40', 'BT40'), ('BT50', 'BT50'), ('GSK30', 'GSK30'), ('GSK40', 'GSK40'), ('GSK50', 'GSK50')], string='使用刀柄型号') + jikimo_bom_ids = fields.One2many('jikimo.bom','tool_inventory_id', 'bom单') + def bom_mainfest(self): + + jikimo_bom_ids = self.mapped('jikimo_bom_ids') + if not jikimo_bom_ids: + self._bom_mainfest() + return self.bom_mainfest() + request.session['jikimo_bom_product'] = {'bom_id': int(self.jikimo_bom_ids)} + # context = dict(self.env.context) + # context.update({'jikimo_bom_product': self.jikimo_bom_ids.options}) + # if self.functional_cutting_tool_model_id.cutting_tool_type_ids: + # context.update({'jikimo_bom_product_cutting_tool_type': self.functional_cutting_tool_model_id.cutting_tool_type_ids.ids}) + return { + 'type': 'ir.actions.act_window', + 'name': '刀具组装清单', + 'res_model': 'jikimo.bom', + 'view_mode': 'form', + 'view_id': self.env.ref('sf_tool_management.view_jikimo_bom_form').id, + 'res_id': int(self.jikimo_bom_ids), + 'target': 'current', # Use 'new' to open in a new window/tab + # {'jikimo_bom_product': self.jikimo_bom_ids.options} + } + + # 创建bom单 + def _bom_mainfest(self): + self.env['jikimo.bom'].create({'tool_inventory_id':self.id}) \ No newline at end of file diff --git a/sf_tool_management/security/ir.model.access.csv b/sf_tool_management/security/ir.model.access.csv index 26b45aeb..8c188464 100644 --- a/sf_tool_management/security/ir.model.access.csv +++ b/sf_tool_management/security/ir.model.access.csv @@ -38,3 +38,6 @@ access_sf_fixture_material_search_group_plan_dispatch,sf.fixture.material.search access_sf_functional_tool_dismantle,sf.functional.tool.dismantle,model_sf_functional_tool_dismantle,base.group_user,1,1,1,0 access_sf_functional_tool_dismantle_group_sf_tool_user,sf.functional.tool.dismantle_group_sf_tool_user,model_sf_functional_tool_dismantle,sf_base.group_sf_tool_user,1,1,1,0 access_sf_functional_tool_dismantle_group_plan_dispatch,sf.functional.tool.dismantle_group_plan_dispatch,model_sf_functional_tool_dismantle,sf_base.group_plan_dispatch,1,0,0,0 + +access_jikimo_bom,jikimo.bom,model_jikimo_bom,base.group_user,1,1,1,1 +access_jikimo_bom_wizard,jikimo.bom.wizard,model_jikimo_bom_wizard,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/sf_tool_management/views/jikimo_bom.xml b/sf_tool_management/views/jikimo_bom.xml new file mode 100644 index 00000000..bb1454df --- /dev/null +++ b/sf_tool_management/views/jikimo_bom.xml @@ -0,0 +1,51 @@ + + + + bom物料清单 + jikimo.bom + tree,form + + + jikimo.bom.form + jikimo.bom + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
\ No newline at end of file diff --git a/sf_tool_management/views/tool_inventory.xml b/sf_tool_management/views/tool_inventory.xml new file mode 100644 index 00000000..f7fbc6b5 --- /dev/null +++ b/sf_tool_management/views/tool_inventory.xml @@ -0,0 +1,15 @@ + + + + sf.tool.inventory.inherit.tree + sf.tool.inventory + + + + +