Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

# Conflicts:
#	sf_message/__manifest__.py
This commit is contained in:
mgw
2024-09-30 10:51:54 +08:00
10 changed files with 285 additions and 30 deletions

View File

@@ -1,4 +1,5 @@
import datetime import datetime
import logging
from datetime import timedelta, time from datetime import timedelta, time
from collections import defaultdict from collections import defaultdict
from odoo import fields, models, api from odoo import fields, models, api
@@ -6,6 +7,8 @@ from odoo.addons.resource.models.resource import Intervals
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
import math import math
_logger = logging.getLogger(__name__)
class ResWorkcenter(models.Model): class ResWorkcenter(models.Model):
_name = "mrp.workcenter" _name = "mrp.workcenter"
@@ -225,7 +228,11 @@ class ResWorkcenter(models.Model):
if plan_ids: if plan_ids:
sum_qty = sum([p.product_qty for p in plan_ids]) sum_qty = sum([p.product_qty for p in plan_ids])
date_planned_working_hours = self._compute_effective_working_hours_day1(date_planned) date_planned_working_hours = self._compute_effective_working_hours_day1(date_planned)
if sum_qty >= date_planned_working_hours: default_capacity = round(
self.production_line_hour_capacity * date_planned_working_hours, 2)
_logger.info('排程日期:%s,计划数量:%s,日产能:%s,日工时:%s' % (
date_planned, sum_qty, default_capacity, date_planned_working_hours))
if sum_qty >= default_capacity:
return False return False
return True return True

View File

@@ -11,10 +11,12 @@
""", """,
'category': 'sf', 'category': 'sf',
'website': 'https://www.sf.jikimo.com', 'website': 'https://www.sf.jikimo.com',
'depends': ['sale', 'purchase', 'sf_plan', 'jikimo_message_notify', 'stock', 'sf_tool_management', 'sf_manufacturing', 'sf_hr'], 'depends': ['sale', 'purchase', 'sf_plan', 'jikimo_message_notify', 'stock'],
'data': [ 'data': [
'data/bussiness_node.xml', 'data/bussiness_node.xml',
# 'data/cron_data.xml',
'data/template_data.xml', 'data/template_data.xml',
], ],
'test': [ 'test': [
], ],

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<odoo> <odoo>
<data noupdate="1"> <data noupdate="1">
<!--销售订单-->
<record id="bussiness_pending_order" model="jikimo.message.bussiness.node"> <record id="bussiness_pending_order" model="jikimo.message.bussiness.node">
<field name="name">待接单</field> <field name="name">待接单</field>
<field name="model">sale.order</field> <field name="model">sale.order</field>
@@ -10,6 +11,17 @@
<field name="name">确认接单</field> <field name="name">确认接单</field>
<field name="model">sale.order</field> <field name="model">sale.order</field>
</record> </record>
<!-- <record id="bussiness_sale_order_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">销售订单逾期预警</field>-->
<!-- <field name="model">sale.order</field>-->
<!-- </record>-->
<!-- <record id="bussiness_sale_order_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">销售订单已逾期</field>-->
<!-- <field name="model">sale.order</field>-->
<!-- </record>-->
<record id="transfer_inventory" model="jikimo.message.bussiness.node"> <record id="transfer_inventory" model="jikimo.message.bussiness.node">
<field name="name">调拨入库</field> <field name="name">调拨入库</field>
<field name="model">stock.picking</field> <field name="model">stock.picking</field>
@@ -30,9 +42,48 @@
<field name="name">坯料发料提醒</field> <field name="name">坯料发料提醒</field>
<field name="model">stock.picking</field> <field name="model">stock.picking</field>
</record> </record>
<!--工单-->
<record id="bussiness_mrp_workorder_remind" model="jikimo.message.bussiness.node"> <record id="bussiness_mrp_workorder_remind" model="jikimo.message.bussiness.node">
<field name="name">工单已下发通知</field> <field name="name">工单已下发通知</field>
<field name="model">mrp.workorder</field> <field name="model">mrp.workorder</field>
</record> </record>
<!-- <record id="bussiness_mrp_workorder_pre_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">装夹预调工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_pre_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">装夹预调工单已逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_cnc_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">CNC工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_cnc_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">CNC工单已逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_unclamp_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">解除装夹工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_unclamp_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">解除装夹工单已逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_surface_overdue_warning" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">表面工艺工单逾期预警</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
<!-- <record id="bussiness_mrp_workorder_surface_overdue" model="jikimo.message.bussiness.node">-->
<!-- <field name="name">表面工艺工单已逾期</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- </record>-->
</data> </data>
</odoo> </odoo>

View File

@@ -0,0 +1,160 @@
<odoo>
<data noupdate="1">
<record model="ir.cron" id="ir_cron_sale_order_overdue_warning">
<field name="name">销售订单逾期预警</field>
<field name="model_id" ref="model_sale_order"/>
<field name="state">code</field>
<field name="code">model._overdue_warning_func()</field>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="user_id" ref="base.user_root"/>
<field name="active" eval="True"/>
</record>
<record model="ir.cron" id="ir_cron_sale_order_overdue">
<field name="name">销售订单已逾期</field>
<field name="model_id" ref="model_sale_order"/>
<field name="state">code</field>
<field name="code">model._overdue_func()</field>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="user_id" ref="base.user_root"/>
<field name="active" eval="True"/>
</record>
<record model="ir.cron" id="ir_cron_mrp_workorder_overdue_warning">
<field name="name">装夹预调工单逾期预警</field>
<field name="model_id" ref="model_mrp_workorder"/>
<field name="state">code</field>
<field name="code">model._overdue_warning_func()</field>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="user_id" ref="base.user_root"/>
<field name="active" eval="True"/>
</record>
<record model="ir.cron" id="ir_cron_mrp_workorder_overdue">
<field name="name">工单已逾期</field>
<field name="model_id" ref="model_mrp_workorder"/>
<field name="state">code</field>
<field name="code">model._overdue_func()</field>
<field name="interval_number">1</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="user_id" ref="base.user_root"/>
<field name="active" eval="True"/>
</record>
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- -->
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- -->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue_warning">-->
<!-- <field name="name">工单逾期预警</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_warning_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <record model="ir.cron" id="ir_cron_mrp_workorder_pre_overdue">-->
<!-- <field name="name">工单已逾期</field>-->
<!-- <field name="model_id" ref="model_mrp_workorder"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">model._overdue_func()</field>-->
<!-- <field name="interval_number">1</field>-->
<!-- <field name="interval_type">minutes</field>-->
<!-- <field name="numbercall">-1</field>-->
<!-- <field name="doall" eval="False"/>-->
<!-- <field name="user_id" ref="base.user_root"/>-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
</data>
</odoo>

View File

@@ -1,6 +1,32 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<odoo> <odoo>
<data noupdate="1"> <data noupdate="1">
<record id="template_pending_order" model="jikimo.message.template">
<field name="name">待接单</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="model">sale.order</field>
<field name="bussiness_node_id" ref="bussiness_pending_order"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 待接单提醒:
单号:销售订单[{{name}}]({{url}})
事项:请确认是否接单。
</field>
</record>
<record id="template_to_be_confirm" model="jikimo.message.template">
<field name="name">确认接单</field>
<field name="model_id" ref="sale.model_sale_order"/>
<field name="model">sale.order</field>
<field name="bussiness_node_id" ref="bussiness_to_be_confirm"/>
<field name="msgtype">markdown</field>
<field name="urgency">normal</field>
<field name="content">### 待排程提醒:
单号:产品[{{product_id}}]({{url}})
事项:{{mrp_production_count}}个制造订单待计划排程
</field>
</record>
<record id="template_material_purchase_remind" model="jikimo.message.template"> <record id="template_material_purchase_remind" model="jikimo.message.template">
<field name="name">坯料采购提醒</field> <field name="name">坯料采购提醒</field>
<field name="model_id" ref="purchase.model_purchase_order"/> <field name="model_id" ref="purchase.model_purchase_order"/>

View File

@@ -19,9 +19,7 @@ class SFMessagePurchase(models.Model):
return contents return contents
def request_url(self, id): def request_url(self, id):
we_config_info = self.env['we.config'].sudo().search([], limit=1) url = self.env['ir.config_parameter'].get_param('web.base.url')
redirect_domain = self.env['we.app'].sudo().search([('id', '=', we_config_info.odoo_app_id.id)]).redirect_domain
full_url = 'https://%s/' % redirect_domain
action_id = self.env.ref('purchase.purchase_form_action').id action_id = self.env.ref('purchase.purchase_form_action').id
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_website_payment')]).id menu_id = self.env['ir.model.data'].search([('name', '=', 'module_website_payment')]).id
# 查询参数 # 查询参数
@@ -31,5 +29,5 @@ class SFMessagePurchase(models.Model):
# 拼接查询参数 # 拼接查询参数
query_string = urlencode(params) query_string = urlencode(params)
# 拼接URL # 拼接URL
full_url = full_url + "web#" + query_string full_url = url + "/web#" + query_string
return full_url return full_url

View File

@@ -40,21 +40,34 @@ class SFMessageSale(models.Model):
# 继承并重写jikimo.message.dispatch的_get_message() # 继承并重写jikimo.message.dispatch的_get_message()
def _get_message(self, message_queue_ids): def _get_message(self, message_queue_ids):
res = super(SFMessageSale, self)._get_message(message_queue_ids) contents = []
new_res = [] url = self.env['ir.config_parameter'].get_param('web.base.url')
processed_messages = set() # 用于跟踪已经处理过的消息
for item in message_queue_ids: for item in message_queue_ids:
if item.message_template_id.bussiness_node_id.name == '确认接单': # 待接单的处理
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)
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))]) sale_order_line = self.env['sale.order.line'].search([('order_id', '=', int(item.res_id))])
if len(sale_order_line) == 1: product = sale_order_line[0].product_id.name if len(sale_order_line) == 1 else '%s...' % \
product = sale_order_line[0].product_id.name sale_order_line[
elif len(sale_order_line) > 1: 0].product_id.name
product = '%s...' % sale_order_line[0].product_id.name action_id = self.env.ref('sf_plan.sf_production_plan_action1').id
for message in res: url = f"{url}/web#view_type=list&action={action_id}"
message_text = message.replace('{{product_id}}', product) content = content[0].replace('{{product_id}}', product).replace('{{url}}', url)
if message_text not in processed_messages: contents.append(content)
new_res.append(message_text) return contents
processed_messages.add(message_text)
if new_res: # # 销售订单逾期预警
res = new_res # def _overdue_warning_func(self):
return res # sale_order_
# return 1
#
# # 销售订单已逾期
# def _overdue_func(self):
# return 1

View File

@@ -52,9 +52,7 @@ class SFMessageStockPicking(models.Model):
return res return res
def request_url(self): def request_url(self):
we_config_info = self.env['we.config'].sudo().search([], limit=1) url = self.env['ir.config_parameter'].get_param('web.base.url')
redirect_domain = self.env['we.app'].sudo().search([('id', '=', we_config_info.odoo_app_id.id)]).redirect_domain
full_url = 'https://%s/' % redirect_domain
action_id = self.env.ref('stock.stock_picking_type_action').id action_id = self.env.ref('stock.stock_picking_type_action').id
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_theme_treehouse')]).id menu_id = self.env['ir.model.data'].search([('name', '=', 'module_theme_treehouse')]).id
# 查询参数 # 查询参数
@@ -63,5 +61,5 @@ class SFMessageStockPicking(models.Model):
# 拼接查询参数 # 拼接查询参数
query_string = urlencode(params) query_string = urlencode(params)
# 拼接URL # 拼接URL
full_url = full_url + "web#" + query_string full_url = url + "/web#" + query_string
return full_url return full_url

View File

@@ -40,9 +40,7 @@ class SFMessageWork(models.Model):
return contents return contents
def request_url(self): def request_url(self):
we_config_info = self.env['we.config'].sudo().search([], limit=1) url = self.env['ir.config_parameter'].get_param('web.base.url')
redirect_domain = self.env['we.app'].sudo().search([('id', '=', we_config_info.odoo_app_id.id)]).redirect_domain
full_url = 'https://%s/' % redirect_domain
action_id = self.env.ref('sf_manufacturing.mrp_workorder_action_tablet').id action_id = self.env.ref('sf_manufacturing.mrp_workorder_action_tablet').id
menu_id = self.env['ir.model.data'].search([('name', '=', 'module_stock_dropshipping')]).id menu_id = self.env['ir.model.data'].search([('name', '=', 'module_stock_dropshipping')]).id
# 查询参数 # 查询参数
@@ -51,5 +49,6 @@ class SFMessageWork(models.Model):
# 拼接查询参数 # 拼接查询参数
query_string = urlencode(params) query_string = urlencode(params)
# 拼接URL # 拼接URL
full_url = full_url + "web#" + query_string full_url = url + "/web#" + query_string
return full_url return full_url

View File

@@ -18,6 +18,7 @@ class OrderPrice(models.Model):
return True return True
except ValueError: except ValueError:
return False return False
@api.depends('sale_order_id.order_line.remark')
def _compute_bfm_amount_total(self): def _compute_bfm_amount_total(self):
for record in self: for record in self:
amount_total = 0 amount_total = 0