diff --git a/quality_control/views/quality_views.xml b/quality_control/views/quality_views.xml index f7a1a3dc..fbd917b2 100644 --- a/quality_control/views/quality_views.xml +++ b/quality_control/views/quality_views.xml @@ -1033,7 +1033,7 @@ name="Overview" action="quality_alert_team_action" parent="menu_quality_root" - sequence="5"/> + sequence="5" active="False"/> sequence + delivery_warning == 'warning' + delivery_warning == 'overdue' + fullscreen--> current [('state', '!=', 'cancel'),('schedule_state', '=', '已排')] - {'search_default_product': 1, 'search_default_workcenter_id': active_id} + {'search_default_product': 1, 'search_default_workcenter_id': + active_id,'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1} +

没有工单要做! @@ -244,7 +246,7 @@ - @@ -283,6 +285,8 @@ + + @@ -616,6 +620,12 @@ + + + + + + diff --git a/sf_message/__manifest__.py b/sf_message/__manifest__.py index 416b2641..2e8dfd30 100644 --- a/sf_message/__manifest__.py +++ b/sf_message/__manifest__.py @@ -11,11 +11,12 @@ """, 'category': 'sf', 'website': 'https://www.sf.jikimo.com', - 'depends': ['sale', 'purchase', 'sf_plan', 'jikimo_message_notify', 'stock', 'mrp'], + 'depends': ['sale', 'purchase', 'sf_plan', 'jikimo_message_notify', 'stock', 'sf_quality', 'mrp'], 'data': [ 'data/bussiness_node.xml', - # 'data/cron_data.xml', + 'data/cron_data.xml', 'data/template_data.xml', + 'security/ir.model.access.csv', ], 'test': [ diff --git a/sf_message/controllers/__init__.py b/sf_message/controllers/__init__.py index deec4a8b..12a7e529 100644 --- a/sf_message/controllers/__init__.py +++ b/sf_message/controllers/__init__.py @@ -1 +1 @@ -from . import main \ No newline at end of file +from . import main diff --git a/sf_message/data/bussiness_node.xml b/sf_message/data/bussiness_node.xml index 66b24aa7..d9ac9ae1 100644 --- a/sf_message/data/bussiness_node.xml +++ b/sf_message/data/bussiness_node.xml @@ -12,15 +12,16 @@ sale.order - - - - + + 销售订单逾期预警 + sale.order + + + + 销售订单已逾期 + sale.order + - - - - 调拨入库 @@ -66,33 +67,49 @@ - - - - - - - - - - - - + + 装夹预调工单逾期预警 + mrp.workorder + + + 装夹预调工单已逾期 + mrp.workorder + - - - - + + CNC加工工单逾期预警 + mrp.workorder + + + CNC工单已逾期 + mrp.workorder + - - - - + + 解除装夹工单逾期预警 + mrp.workorder + + + + 解除装夹工单已逾期 + mrp.workorder + + + + 表面工艺工单逾期预警 + mrp.workorder + + + + 表面工艺工单已逾期 + mrp.workorder + + + + 待质量判定 + quality.cnc.test + - - - - \ No newline at end of file diff --git a/sf_message/data/cron_data.xml b/sf_message/data/cron_data.xml index f69dce7b..f095c9bd 100644 --- a/sf_message/data/cron_data.xml +++ b/sf_message/data/cron_data.xml @@ -1,24 +1,11 @@ - 销售订单逾期预警 + 检查销售订单是否已逾期预警和逾期 code - model._overdue_warning_func() - 1 - minutes - -1 - - - - - - - 销售订单已逾期 - - code - model._overdue_func() - 1 + model._overdue_or_warning_func() + 10 minutes -1 @@ -27,11 +14,11 @@ - 装夹预调工单逾期预警 + 检查工单是否已逾期预警和逾期 code - model._overdue_warning_func() - 1 + model._overdue_or_warning_func() + 10 minutes -1 @@ -39,122 +26,17 @@ - - 工单已逾期 + + 检查工单是否完成并恢复正常时效 code - model._overdue_func() - 1 + model._recover_time_warning_func() + 10 minutes -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sf_message/data/template_data.xml b/sf_message/data/template_data.xml index fd5ba389..f511d338 100644 --- a/sf_message/data/template_data.xml +++ b/sf_message/data/template_data.xml @@ -2,7 +2,7 @@ - + 待接单 sale.order @@ -16,7 +16,7 @@ - 确认接单 + 待排程提醒 sale.order @@ -27,6 +27,31 @@ 事项:{{mrp_production_count}}个制造订单待计划排程 + + + 销售订单逾期预警 + + sale.order + + markdown + normal + ### 销售订单逾期预警 +事项:共有[{{warning_num}}]({{url}})个销售订单有逾期风险 + + + + + 销售订单已逾期 + + sale.order + + markdown + urgent + ### 销售订单已逾期提醒 +事项:共有[{{overdue_num}}]({{url}})个销售订单已逾期 + + + 坯料采购提醒 @@ -63,6 +88,102 @@ 事项:共{{number}}个工单已下发,请查收知悉 + + 装夹预调工单逾期预警 + + mrp.workorder + + markdown + timing + normal + ### 工单逾期预警 +事项:共有[{{warning_num}}]({{url}})工单有逾期风险 + + + + 装夹预调工单已逾期 + + mrp.workorder + + markdown + timing + normal + ### 工单已逾期提醒 +事项:共有[{{overdue_num}}]({{url}})工单已逾期 + + + + CNC加工工单逾期预警 + + mrp.workorder + + markdown + timing + normal + ### 工单逾期预警 +事项:共有[{{warning_num}}]({{url}})工单有逾期风险 + + + + CNC加工工单已逾期 + + mrp.workorder + + markdown + timing + normal + ### 工单已逾期提醒 +事项:共有[{{overdue_num}}]({{url}})工单已逾期 + + + + 解除装夹工单逾期预警 + + mrp.workorder + + markdown + timing + normal + ### 工单逾期预警 +事项:共有[{{warning_num}}]({{url}})工单有逾期风险 + + + + 解除装夹工单已逾期 + + mrp.workorder + + markdown + timing + normal + ### 工单已逾期提醒 +事项:共有[{{overdue_num}}]({{url}})工单已逾期 + + + + 表面工艺工单逾期预警 + + mrp.workorder + + markdown + timing + normal + ### 工单逾期预警 +事项:共有[{{warning_num}}]({{url}})工单有逾期风险 + + + + 表面工艺工单已逾期 + + mrp.workorder + + markdown + timing + normal + ### 工单已逾期提醒 +事项:共有[{{overdue_num}}]({{url}})工单已逾期 + + @@ -132,5 +253,16 @@ 单号:发料出库单[{{name}}]({{request_url}}) 事项:销售订单{{sale_order_name}}已全部产出并入库,请及时发货 + + + 待质量判定 + + quality.cnc.test + + markdown + normal + ### 待质量判定提醒 +事项:共有[{{judge_num}}]({{url}})个工单需判定质量结果 + \ No newline at end of file diff --git a/sf_message/models/__init__.py b/sf_message/models/__init__.py index 2ff5461b..25702b1e 100644 --- a/sf_message/models/__init__.py +++ b/sf_message/models/__init__.py @@ -8,3 +8,4 @@ from . import sf_message_purchase from . import sf_message_workorder from . import sf_message_functional_tool_dismantle from . import sf_message_mrp_production +from . import sf_message_quality_cnc_test diff --git a/sf_message/models/sf_message_quality_cnc_test.py b/sf_message/models/sf_message_quality_cnc_test.py new file mode 100644 index 00000000..0ddc1391 --- /dev/null +++ b/sf_message/models/sf_message_quality_cnc_test.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +import logging +from datetime import datetime, timedelta +from odoo import models, fields, api, _ + + +class SFMessageQualityCncTest(models.Model): + _name = 'quality.cnc.test' + _inherit = ['quality.cnc.test', 'jikimo.message.dispatch'] + + def create(self, vals_list): + res = super(SFMessageQualityCncTest, self).create(vals_list) + if res: + try: + logging.info('add_queue res:%s' % res) + res.add_queue('待质量判定') + except Exception as e: + logging.info('add_queue error:%s' % e) + return res + + # 继承并重写jikimo.message.dispatch的_get_message() + def _get_message(self, message_queue_ids): + contents = [] + url = self.env['ir.config_parameter'].get_param('web.base.url') + i = 0 + for item in message_queue_ids: + if item.message_template_id.bussiness_node_id.name == '待质量判定': + content = item.message_template_id.content + i += 1 + if i >= 1: + action_id = self.env.ref('sf_quality.action_quality_cnc_test').id + url_with_id = f"{url}/web#view_type=list&action={action_id}" + content_template = content.replace('{{judge_num}}', str(i)) + content_template = content_template.replace('{{url}}', url_with_id) + contents.append(content_template) + return contents diff --git a/sf_message/models/sf_message_sale.py b/sf_message/models/sf_message_sale.py index d684cf7d..13a5f796 100644 --- a/sf_message/models/sf_message_sale.py +++ b/sf_message/models/sf_message_sale.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import logging +from datetime import datetime, timedelta from odoo import models, fields, api, _ @@ -12,6 +13,7 @@ class SFMessageSale(models.Model): res = super(SFMessageSale, self).create(vals_list) if res: try: + logging.info('add_queue res:%s' % res) res.add_queue('待接单') except Exception as e: logging.info('add_queue error:%s' % e) @@ -42,16 +44,20 @@ class SFMessageSale(models.Model): # 继承并重写jikimo.message.dispatch的_get_message() def _get_message(self, message_queue_ids): contents = [] + bussiness_node = None url = self.env['ir.config_parameter'].get_param('web.base.url') + current_time_strf = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + current_time = self.env['sf.sync.common'].sudo().get_add_time(current_time_strf) + current_time_datetime = datetime.strptime(current_time, '%Y-%m-%d %H:%M:%S') + time_range = timedelta(minutes=2) + i = 0 for item in message_queue_ids: - # 待接单的处理 if item.message_template_id.bussiness_node_id.name == '待接单': content = super(SFMessageSale, self)._get_message(item) action_id = self.env.ref('sale.action_quotations_with_onboarding').id - url = f"{url}/web#id={item.res_id}&view_type=form&action={action_id}" - content = content[0].replace('{{url}}', url) + url_with_id = f"{url}/web#id={item.res_id}&view_type=form&action={action_id}" + content = content[0].replace('{{url}}', url_with_id) contents.append(content) - # 确认接单的处理 elif item.message_template_id.bussiness_node_id.name == '确认接单': content = super(SFMessageSale, self)._get_message(item) sale_order_line = self.env['sale.order.line'].search([('order_id', '=', int(item.res_id))]) @@ -59,16 +65,77 @@ class SFMessageSale(models.Model): sale_order_line[ 0].product_id.name action_id = self.env.ref('sf_plan.sf_production_plan_action1').id - url = f"{url}/web#view_type=list&action={action_id}" - content = content[0].replace('{{product_id}}', product).replace('{{url}}', url) + url_with_id = f"{url}/web#view_type=list&action={action_id}" + content = content[0].replace('{{product_id}}', product).replace('{{url}}', url_with_id) contents.append(content) + elif item.message_template_id.bussiness_node_id.name in ['销售订单逾期预警', '销售订单已逾期']: + bussiness_node = item.message_template_id.bussiness_node_id.name + for reminder_time in item.message_template_id.reminder_time_ids: + content = item.message_template_id.content + target_time = datetime.combine(current_time_datetime.date(), datetime.min.time()).replace( + hour=reminder_time.time_point, + minute=0, + second=0, + microsecond=0 + ) + logging.info(current_time) + logging.info(target_time) + if target_time - time_range <= current_time_datetime <= target_time + time_range: + search_condition = [ + ('delivery_warning', '=', 'warning')] if bussiness_node == '销售订单逾期预警' else [ + ('delivery_warning', '=', 'overdue')] + record = self.sudo().search(search_condition + [('id', '=', int(item.res_id))]) + if record: + i += 1 + if i >= 1: + action_id = self.env.ref('sale.action_orders').id + url_with_id = f"{url}/web#view_type=list&action={action_id}" + content_template = content.replace('{{url}}', url_with_id) + if bussiness_node == '销售订单逾期预警': + content = content_template.replace('{{warning_num}}', str(i)) + elif bussiness_node == '销售订单已逾期': + content = content_template.replace('{{overdue_num}}', str(i)) + contents.append(content) return contents - # # 销售订单逾期预警 - # def _overdue_warning_func(self): - # sale_order_ - # return 1 - # - # # 销售订单已逾期 - # def _overdue_func(self): - # return 1 + # # 销售订单逾期预警和已逾期 + def _overdue_or_warning_func(self): + today = datetime.today().date() + deadline_check = today + timedelta(days=1) + logging.info(f"today: {today}, deadline_check: {deadline_check}") + sale_order = self.sudo().search([('state', 'in', ['sale']), ('deadline_of_delivery', '!=', False)]) + for item in sale_order: + production = self.env['mrp.production'].search([('origin', '=', item.name)]) + production_not_done = production.filtered(lambda p: p.state not in ['done', 'scrap', 'cancel']) + production_done_count = len(production.filtered(lambda p: p.state in ['done', 'scrap', 'cancel'])) + if len(production_not_done) != item.mrp_production_count: + if deadline_check == item.deadline_of_delivery: + item.delivery_warning = 'warning' + elif today == item.deadline_of_delivery: + item.delivery_warning = 'overdue' + elif production_done_count == item.mrp_production_count: + if item.delivery_status in ['pending', 'partial']: + if deadline_check == item.deadline_of_delivery: + item.delivery_warning = 'warning' + elif today == item.deadline_of_delivery: + item.delivery_warning = 'overdue' + else: + continue + overdue_orders = self.sudo().search([('delivery_warning', 'in', ['warning', 'overdue'])]) + for wo in overdue_orders: + message_template = self.env["jikimo.message.template"].search([ + ("model", "=", self._name), + ("bussiness_node_id", "=", self.env.ref('sf_message.bussiness_sale_order_overdue_warning').id) + ]) + sale_order_has = self.env['jikimo.message.queue'].search([ + ('res_id', '=', wo.id), + ('message_status', '=', 'pending'), + ('message_template_id', '=', message_template.id) + ]) + if not sale_order_has: + if wo.delivery_warning == 'warning': + wo.add_queue('销售订单逾期预警') + elif wo.delivery_warning == 'overdue': + wo.add_queue('销售订单已逾期') + + diff --git a/sf_message/models/sf_message_workorder.py b/sf_message/models/sf_message_workorder.py index 59e3a0fc..e432938c 100644 --- a/sf_message/models/sf_message_workorder.py +++ b/sf_message/models/sf_message_workorder.py @@ -1,3 +1,4 @@ +from datetime import datetime, timedelta from odoo import models, fields, api, _ import logging, json import requests @@ -6,6 +7,7 @@ from urllib.parse import urlencode _logger = logging.getLogger(__name__) + class SFMessageWork(models.Model): _name = 'mrp.workorder' _inherit = ['mrp.workorder', 'jikimo.message.dispatch'] @@ -23,6 +25,17 @@ class SFMessageWork(models.Model): def _get_message(self, message_queue_ids): contents = [] product_id = [] + bussiness_node = None + url = self.env['ir.config_parameter'].get_param('web.base.url') + current_time_strf = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + current_time = self.env['sf.sync.common'].sudo().get_add_time(current_time_strf) + current_time_datetime = datetime.strptime(current_time, '%Y-%m-%d %H:%M:%S') + time_range = timedelta(minutes=2) + template_names = { + '预警': ['装夹预调工单逾期预警', 'CNC加工工单逾期预警', '解除装夹工单逾期预警', '表面工艺工单逾期预警'], + '已逾期': ['装夹预调工单已逾期', 'CNC加工工单已逾期', '解除装夹工单已逾期', '表面工艺工单已逾期'] + } + i = 0 for message_queue_id in message_queue_ids: if message_queue_id.message_template_id.name == '工单已下发通知': content = message_queue_id.message_template_id.content @@ -37,6 +50,37 @@ class SFMessageWork(models.Model): '{{request_url}}', url) product_id.append(mrp_workorder_line.product_id.id) contents.append(content) + elif message_queue_id.message_template_id.name in template_names['预警'] + template_names['已逾期']: + item = message_queue_id.message_template_id + bussiness_node = item.bussiness_node_id.name + for reminder_time in item.reminder_time_ids: + content = item.content + target_time = datetime.combine(current_time_datetime.date(), datetime.min.time()).replace( + hour=reminder_time.time_point, + minute=0, + second=0, + microsecond=0 + ) + logging.info(current_time) + logging.info(target_time) + logging.info(target_time - time_range) + logging.info(target_time + time_range) + if target_time - time_range <= current_time_datetime <= target_time + time_range: + search_condition = [ + ('delivery_warning', '=', 'warning')] if bussiness_node in template_names['预警'] else [ + ('delivery_warning', '=', 'overdue')] + record = self.sudo().search(search_condition + [('id', '=', int(item.res_id))]) + if record: + i += 1 + if i >= 1: + action_id = self.env.ref('sf_manufacturing.mrp_workorder_action_tablet').id + url_with_id = f"{url}/web#view_type=list&action={action_id}" + content_template = content.replace('{{url}}', url_with_id) + if bussiness_node in template_names['预警']: + content = content_template.replace('{{warning_num}}', str(i)) + elif bussiness_node in template_names['已逾期']: + content = content_template.replace('{{overdue_num}}', str(i)) + contents.append(content) return contents def request_url(self): @@ -52,3 +96,58 @@ class SFMessageWork(models.Model): full_url = url + "/web#" + query_string return full_url + def _overdue_or_warning_func(self): + workorders = self.env['mrp.workorder'].search([("state", "in", ["ready", "progress", "to be detected"])]) + grouped_workorders = {} + for workorder in workorders: + routing_type = workorder.routing_type + if routing_type not in grouped_workorders: + grouped_workorders[routing_type] = [] + grouped_workorders[routing_type].append(workorder) + for routing_type, orders in grouped_workorders.items(): + print(f"Routing Type: {routing_type}, Orders: {len(orders)}") + for item in orders: + if item.date_planned_finished: + current_time_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + current_time_datetime = datetime.strptime(current_time_str, '%Y-%m-%d %H:%M:%S') + date_planned_finished_str = self.env['sf.sync.common'].sudo().get_add_time( + item.date_planned_finished.strftime("%Y-%m-%d %H:%M:%S")) + date_planned_finished = datetime.strptime(date_planned_finished_str, '%Y-%m-%d %H:%M:%S') + logging.info(f"Workorder: {item.production_id.name}, Current Time: {current_time_datetime}, " + f"Planned Finish: {date_planned_finished}") + twelve_hours_ago = current_time_datetime - timedelta(hours=12) + if current_time_datetime >= date_planned_finished: + item.delivery_warning = 'overdue' + elif twelve_hours_ago <= current_time_datetime <= date_planned_finished: + item.delivery_warning = 'warning' + business_node_ids = { + '装夹预调': self.env.ref('sf_message.bussiness_mrp_workorder_pre_overdue_warning').id, + 'CNC加工': self.env.ref('sf_message.bussiness_mrp_workorder_cnc_overdue_warning').id, + '解除装夹': self.env.ref('sf_message.bussiness_mrp_workorder_unclamp_overdue_warning').id, + '表面工艺': self.env.ref('sf_message.bussiness_mrp_workorder_surface_overdue_warning').id, + } + message_templates = {key: self.env["jikimo.message.template"].sudo().search([ + ("model", "=", self._name), + ("bussiness_node_id", "=", business_node_ids[key]) + ]) for key in business_node_ids} + for item in orders: + if item.delivery_warning in ['overdue', 'warning']: + bussiness_node_id = business_node_ids.get(item.routing_type) + if bussiness_node_id and message_templates[item.routing_type]: + message_queue_ids = self.env["jikimo.message.queue"].sudo().search([ + ("message_template_id", "=", message_templates[item.routing_type].id), + ("message_status", "=", "pending"), + ("res_id", "=", item.id) + ]) + if not message_queue_ids: + overdue_message = '工单已逾期' if item.delivery_warning == 'overdue' else '工单逾期预警' + queue_method_name = f'add_queue' + # 构建参数列表,其中包含item.routing_type和overdue_message + args = [f'{item.routing_type}{overdue_message}'] + # 获取add_queue方法并调用它,传入参数列表 + getattr(item, queue_method_name)(*args) + + def _recover_time_warning_func(self): + workorder_done = self.env['mrp.workorder'].search([("state", "=", "done")]) + workorder_overdue = workorder_done.filtered(lambda x: x.delivery_warning in ['overdue', 'warning']) + workorder_overdue.write({'delivery_warning': 'normal'}) diff --git a/sf_message/security/ir.model.access.csv b/sf_message/security/ir.model.access.csv index cb42c911..05a7366c 100644 --- a/sf_message/security/ir.model.access.csv +++ b/sf_message/security/ir.model.access.csv @@ -1,22 +1,28 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_jikimo_message_template_group_sale_salemanager,jikimo_message_template,model_jikimo_message_template,sf_base.group_sale_salemanager,1,1,1,0 -access_jikimo_message_template_group_purchase,jikimo_message_template,model_jikimo_message_template,sf_base.group_purchase,1,1,1,0 -access_jikimo_message_template_group_sf_stock_user,jikimo_message_template,model_jikimo_message_template,sf_base.group_sf_stock_user,1,1,1,0 -access_jikimo_message_template_group_sf_order_user,jikimo_message_template,model_jikimo_message_template,sf_base.group_sf_order_user,1,1,1,0 -access_jikimo_message_template_group_sf_tool_user,jikimo_message_template,model_jikimo_message_template,sf_base.group_sf_tool_user,1,1,1,0 +access_jikimo_message_template_group_sale_salemanager,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_sale_salemanager,1,1,1,0 +access_jikimo_message_template_group_purchase,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_purchase,1,1,1,0 +access_jikimo_message_template_group_sf_stock_user,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_sf_stock_user,1,1,1,0 +access_jikimo_message_template_group_sf_order_user,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_sf_order_user,1,1,1,0 +access_jikimo_message_template_group_sf_tool_user,jikimo_message_template,jikimo_message_notify.model_jikimo_message_template,sf_base.group_sf_tool_user,1,1,1,0 -access_jikimo_message_bussiness_node_group_sale_salemanager,jikimo_message_bussiness_node,model_jikimo_message_bussiness_node,sf_base.group_sale_salemanager,1,1,1,0 -access_jikimo_message_bussiness_node_group_purchase,jikimo_message_bussiness_node,model_jikimo_message_bussiness_node,sf_base.group_purchase,1,1,1,0 -access_jikimo_message_bussiness_node_group_sf_stock_user,jikimo_message_bussiness_node,model_jikimo_message_bussiness_node,sf_base.group_sf_stock_user,1,1,1,0 -access_jikimo_message_bussiness_node_group_sf_order_user,jikimo_message_bussiness_node,model_jikimo_message_bussiness_node,sf_base.group_sf_order_user,1,1,1,0 -access_jikimo_message_bussiness_node_group_sf_tool_user,jikimo_message_bussiness_node,model_jikimo_message_bussiness_node,sf_base.group_sf_tool_user,1,1,1,0 +access_jikimo_message_bussiness_node_group_sale_salemanager,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sale_salemanager,1,1,1,0 +access_jikimo_message_bussiness_node_group_purchase,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_purchase,1,1,1,0 +access_jikimo_message_bussiness_node_group_sf_stock_user,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sf_stock_user,1,1,1,0 +access_jikimo_message_bussiness_node_group_sf_order_user,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sf_order_user,1,1,1,0 +access_jikimo_message_bussiness_node_group_sf_tool_user,jikimo_message_bussiness_node,jikimo_message_notify.model_jikimo_message_bussiness_node,sf_base.group_sf_tool_user,1,1,1,0 -access_jikimo_message_queue_group_sale_salemanager,jikimo_message_queue,model_jikimo_message_queue,sf_base.group_sale_salemanager,1,1,1,0 -access_jikimo_message_queue_group_purchase,jikimo_message_queue,model_jikimo_message_queue,sf_base.group_purchase,1,1,1,0 -access_jikimo_message_queue_group_sf_stock_user,jikimo_message_queue,model_jikimo_message_queue,sf_base.group_sf_stock_user,1,1,1,0 -access_jikimo_message_queue_group_sf_order_user,jikimo_message_queue,model_jikimo_message_queue,sf_base.group_sf_order_user,1,1,1,0 -access_jikimo_message_queue_group_sf_tool_user,jikimo_message_queue,model_jikimo_message_queue,sf_base.group_sf_tool_user,1,1,1,0 +access_jikimo_message_queue_group_sale_salemanager,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sale_salemanager,1,1,1,0 +access_jikimo_message_queue_group_purchase,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_purchase,1,1,1,0 +access_jikimo_message_queue_group_sf_stock_user,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sf_stock_user,1,1,1,0 +access_jikimo_message_queue_group_sf_order_user,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sf_order_user,1,1,1,0 +access_jikimo_message_queue_group_sf_tool_user,jikimo_message_queue,jikimo_message_notify.model_jikimo_message_queue,sf_base.group_sf_tool_user,1,1,1,0 + +access_jikimo_message_reminder_time_group_sale_salemanager,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sale_salemanager,1,1,1,0 +access_jikimo_message_reminder_time_group_purchase,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_purchase,1,1,1,0 +access_jikimo_message_reminder_time_group_sf_stock_user,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sf_stock_user,1,1,1,0 +access_jikimo_message_reminder_time_group_sf_order_user,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sf_order_user,1,1,1,0 +access_jikimo_message_reminder_time_group_sf_tool_user,jikimo_message_reminder_time,jikimo_message_notify.model_jikimo_message_reminder_time,sf_base.group_sf_tool_user,1,1,1,0 diff --git a/sf_message/views/sf_message_sale_view.xml b/sf_message/views/sf_message_sale_view.xml new file mode 100644 index 00000000..6de01920 --- /dev/null +++ b/sf_message/views/sf_message_sale_view.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/sf_message/views/sf_message_template_view.xml b/sf_message/views/sf_message_template_view.xml deleted file mode 100644 index 21920b64..00000000 --- a/sf_message/views/sf_message_template_view.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - sf.message.template.view.form - message.template - -

- -
-
- - - - - - - - - -
-
-
- - - - sf.message.template.view.tree - message.template - - - - - - - - - - - - - - - sf.message.template.search.view - message.template - - - - - - - - - - - - 消息模板 - message.template - tree,form - - - - - - - \ No newline at end of file diff --git a/sf_quality/__manifest__.py b/sf_quality/__manifest__.py index c41e1a24..b1151b6d 100644 --- a/sf_quality/__manifest__.py +++ b/sf_quality/__manifest__.py @@ -13,10 +13,11 @@ 'author': 'jikimo', 'website': 'https://sf.cs.jikimo.com', # 此处依赖sf_manufacturing是因为我要重写其中的一个字段operation_id的string,故需要sf_manufacturing先安装 - 'depends': ['quality_control'], + 'depends': ['quality_control', 'web_widget_model_viewer', 'sf_manufacturing'], 'data': [ 'security/ir.model.access.csv', - 'views/view.xml' + 'views/view.xml', + 'views/quality_cnc_test_view.xml' ], 'assets': { diff --git a/sf_quality/models/__init__.py b/sf_quality/models/__init__.py index 71468786..248f7fb2 100644 --- a/sf_quality/models/__init__.py +++ b/sf_quality/models/__init__.py @@ -3,3 +3,4 @@ from . import custom_quality from . import quality +from . import quality_cnc_test diff --git a/sf_quality/models/quality_cnc_test.py b/sf_quality/models/quality_cnc_test.py new file mode 100644 index 00000000..f3fe5dbd --- /dev/null +++ b/sf_quality/models/quality_cnc_test.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +from odoo import models, fields, api, _ +from odoo.exceptions import UserError + + +class SfQualityCncTest(models.Model): + _name = 'quality.cnc.test' + _description = 'CNC加工质检' + + name = fields.Char('单号', default=lambda self: self.env['ir.sequence'].next_by_code('quality.cnc.test')) + workorder_id = fields.Many2one('mrp.workorder') + production_id = fields.Many2one(related='workorder_id.production_id', string='制造订单') + product_id = fields.Many2one(related='workorder_id.product_id', string='产品') + model_file = fields.Binary(related='workorder_id.glb_file', string='加工模型') + processing_panel = fields.Char(related='workorder_id.processing_panel', string='加工面') + equipment_id = fields.Many2one(related='workorder_id.equipment_id', string='加工设备') + production_line_id = fields.Many2one(related='workorder_id.production_line_id', + string='生产线') + part_number = fields.Char(related='workorder_id.part_number', string='成品零件图号') + detection_report = fields.Binary(related='workorder_id.detection_report', readonly=True, string='检测报告') + state = fields.Selection([ + ('waiting', '待判定'), + ('done', '已完成')], string='状态', default='waiting') + result = fields.Selection([ + ('pass', '合格'), + ('fail', '不合格')], string='判定结果') + number = fields.Integer('数量', default=1) + test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], string="检测结果") + reason = fields.Selection( + [("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"), ("operate computer", "操机"), + ("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因") + detailed_reason = fields.Text('详细原因') + + def submit_pass(self): + self.write({'result': 'pass', 'test_results': self.test_results, 'state': 'done'}) + self.workorder_id.write({'test_results': self.test_results}) + self.workorder_id.button_finish() + + def submit_fail(self): + if not self.reason and not self.detailed_reason and not self.test_results: + raise UserError(_('请填写【判定结果】里的信息')) + else: + self.write({'result': 'fail', 'test_results': self.test_results, 'state': 'done'}) + self.workorder_id.write( + {'test_results': self.test_results, 'reason': self.reason, 'detailed_reason': self.detailed_reason}) + self.workorder_id.button_finish() + + +class SfQualityWorkOrder(models.Model): + _inherit = 'mrp.workorder' + + def button_finish(self): + super(SfQualityWorkOrder, self).button_finish() + if self.routing_type == 'CNC加工': + quality_cnc_test = self.env['quality.cnc.test'].search([('workorder_id', '=', self.id)]) + if quality_cnc_test: + quality_cnc_test.write({'result': 'fail' if self.test_results in ['返工', '报废'] else 'pass', + 'test_results': self.test_results, 'state': 'done', + 'reason': self.reason, + 'detailed_reason': self.detailed_reason, + 'detection_report': self.detection_report}) + + def write(self, vals): + res = super(SfQualityWorkOrder, self).write(vals) + if self.state == 'to be detected': + quality_cnc_test = self.env['quality.cnc.test'].search([('workorder_id', '=', self.id)]) + if not quality_cnc_test: + self.env['quality.cnc.test'].sudo().create({'workorder_id': self.id}) diff --git a/sf_quality/security/ir.model.access.csv b/sf_quality/security/ir.model.access.csv index b147a1df..19818982 100644 --- a/sf_quality/security/ir.model.access.csv +++ b/sf_quality/security/ir.model.access.csv @@ -67,5 +67,11 @@ access_quality_alert_stage,quality.alert.stage,quality.model_quality_alert_stage access_stock_move_group_quality,stock_move_group_quality,stock.model_stock_move,sf_base.group_quality,1,1,0,0 access_stock_move_group_quality_director,stock_move_group_quality_director,stock.model_stock_move,sf_base.group_quality_director,1,1,0,0 +access_quality_cnc_test_group_quality,quality_cnc_test_group_quality,model_quality_cnc_test,sf_base.group_quality,1,1,0,0 +access_quality_cnc_test_group_quality_director,quality_cnc_test_group_quality_director,model_quality_cnc_test,sf_base.group_quality_director,1,1,0,0 + +access_quality_cnc_test_group_sf_equipment_user,quality_cnc_test_group_sf_equipment_user,model_quality_cnc_test,sf_base.group_sf_equipment_user,1,1,0,0 + + diff --git a/sf_quality/views/quality_cnc_test_view.xml b/sf_quality/views/quality_cnc_test_view.xml new file mode 100644 index 00000000..4a6008ae --- /dev/null +++ b/sf_quality/views/quality_cnc_test_view.xml @@ -0,0 +1,202 @@ + + + + + 加工质检单编码规则 + quality.cnc.test + QCT + 4 + + + + + quality.cnc.test.view.tree + quality.cnc.test + + + + + + + + + + + + + + + + + + search.quality.cnc.test + quality.cnc.test + + + + + + + + + + + + + + + + 加工质检 + quality.cnc.test + tree,form + { 'search_default_filter_waiting':1} + +

+ 请先创建一个加工质检单 +

+
+
+ + + quality.cnc.test.form. + quality.cnc.test + +
+
+
+ +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + quality.cnc.test.view.kanban + quality.cnc.test + + + + + +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ + + + + + + + + + +
+
+
+
+
+
+
+ + + + + + 驾驶舱 + ir.actions.act_window + quality.cnc.test + kanban,form + + + [] + +

+ 暂无加工质检单 +

+
+
+ + + +
diff --git a/sf_quality/views/view.xml b/sf_quality/views/view.xml index 1edbca05..1ed999d6 100644 --- a/sf_quality/views/view.xml +++ b/sf_quality/views/view.xml @@ -34,36 +34,36 @@
- - quality.point.form.inherit.sf - quality.point - - - - - - - custom_required - 1 - - - custom_required - 1 - - - + + quality.point.form.inherit.sf + quality.point + + + + + + + custom_required + 1 + + + custom_required + 1 + + + - - sf.quality.point.form.inherit.sf - quality.point - - - - custom_required - - - custom_required - - - + + sf.quality.point.form.inherit.sf + quality.point + + + + custom_required + + + custom_required + + + diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index d19a3b02..f28a76c4 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -55,6 +55,9 @@ class ReSaleOrder(models.Model): store=True, readonly=False, copy=False, precompute=True, states=READONLY_FIELD_STATES, default=fields.Datetime.now) + delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效') + + # 业务平台分配工厂后在智能工厂先创建销售订单 def sale_order_create(self, company_id, delivery_name, delivery_telephone, delivery_address, deadline_of_delivery, payments_way, pay_way): diff --git a/sf_sale/views/sale_order_view.xml b/sf_sale/views/sale_order_view.xml index a5c7a6fa..61b53b08 100644 --- a/sf_sale/views/sale_order_view.xml +++ b/sf_sale/views/sale_order_view.xml @@ -95,7 +95,7 @@ {'readonly': [('state', 'in', ['cancel','sale'])]} - + @@ -106,6 +106,7 @@
+ {'no_create': True} @@ -208,6 +209,20 @@ + + sale.order.message.search.view + sale.order + + primary + + + + + + + + + sale.order.tree sale.order @@ -217,18 +232,15 @@ create_date desc False + delivery_warning == 'warning' + delivery_warning == 'overdue' 订单号 - - - - - - - - + + + @@ -253,10 +265,18 @@ + {"search_default_categ_id":1, "search_default_filter_to_sell":1,"sale_multi_pricelist_product_template": 1} + + + + + { 'search_default_filter_order_warning':1,'search_default_filter_order_overdue':1} + + \ No newline at end of file