Compare commits

..

9 Commits

Author SHA1 Message Date
陈赓
2347ed9cb3 材料型号增加是否磁吸 2025-07-17 14:12:35 +08:00
胡尧
e4c3435840 Accept Merge Request #2292: (feature/增加模块完整性验证 -> develop)
Merge Request: 去掉多余的js

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2292?initial=true
2025-07-16 15:04:01 +08:00
胡尧
2a7048dafd 去掉多余的js 2025-07-16 15:03:23 +08:00
胡尧
2bb215f9df Accept Merge Request #2291: (feature/增加模块完整性验证 -> develop)
Merge Request: 去掉多余的js文件

Created By: @胡尧
Accepted By: @胡尧
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2291?initial=true
2025-07-16 14:33:35 +08:00
胡尧
a2be3a0dbf 去掉多余的js文件 2025-07-16 14:32:37 +08:00
李晓斌
1f4ceab377 Accept Merge Request #2290: (feature/7253 -> develop)
Merge Request: Bug_7262_lxb_commit

Created By: @李晓斌
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @李晓斌
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2290?initial=true
2025-07-16 14:10:37 +08:00
lixiaobin@jikimo.com
94d727e8e0 Bug_7262_lxb_commit 2025-07-16 14:06:58 +08:00
李晓斌
42d9f894dd Accept Merge Request #2289: (feature/7253 -> develop)
Merge Request: BUG_7276_lxb_commit

Created By: @李晓斌
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @李晓斌
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/2289
2025-07-16 11:23:08 +08:00
lixiaobin@jikimo.com
9416d1c1a0 BUG_7276_lxb_commit 2025-07-16 11:20:26 +08:00
11 changed files with 158 additions and 285 deletions

View File

@@ -35,7 +35,6 @@
], ],
'web.assets_backend': [ 'web.assets_backend': [
'sf_base/static/src/scss/*.scss', 'sf_base/static/src/scss/*.scss',
'sf_base/static/src/js/*.js',
], ],
}, },

View File

@@ -42,6 +42,7 @@ class MrsMaterialModel(models.Model):
materials_num = fields.Char("编码号") materials_num = fields.Char("编码号")
name = fields.Char('型号名') name = fields.Char('型号名')
need_h = fields.Boolean("热处理", default="false") need_h = fields.Boolean("热处理", default="false")
need_m = fields.Boolean("是否磁吸", default="false")
mf_materia_post = fields.Char("热处理后密度") mf_materia_post = fields.Char("热处理后密度")
density = fields.Float("密度(kg/m³)") density = fields.Float("密度(kg/m³)")
materials_id = fields.Many2one('sf.production.materials', "材料名") materials_id = fields.Many2one('sf.production.materials', "材料名")

View File

@@ -1,62 +0,0 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { barcodeGenericHandlers } from '@barcodes/barcode_handlers';
import { patch } from "@web/core/utils/patch";
// 定义新的 clickOnButton 函数
function customClickOnButton(selector) {
console.log("This is the custom clickOnButton function!");
const buttons = document.body.querySelectorAll(selector);
let length = buttons.length;
if (length > 0) {
buttons[length - 1].click();
} else {
console.warn(`Button with selector ${selector} not found`);
}
}
patch(barcodeGenericHandlers, "start", {
start(env, { ui, barcode, notification }) {
// 使用新定义的 clickOnButton 函数
const COMMANDS = {
"O-CMD.EDIT": () => customClickOnButton(".o_form_button_edit"),
"O-CMD.DISCARD": () => customClickOnButton(".o_form_button_cancel"),
"O-CMD.SAVE": () => customClickOnButton(".o_form_button_save"),
"O-CMD.PREV": () => customClickOnButton(".o_pager_previous"),
"O-CMD.NEXT": () => customClickOnButton(".o_pager_next"),
"O-CMD.PAGER-FIRST": () => updatePager("first"),
"O-CMD.PAGER-LAST": () => updatePager("last"),
"O-CMD.CONFIRM": () => customClickOnButton(".jikimo_button_confirm"),
"O-CMD.FLUSHED": () => customClickOnButton(".jikimo_button_flushed"),
};
barcode.bus.addEventListener("barcode_scanned", (ev) => {
const barcode = ev.detail.barcode;
if (barcode.startsWith("O-BTN.")) {
let targets = [];
try {
targets = getVisibleElements(ui.activeElement, `[barcode_trigger=${barcode.slice(6)}]`);
} catch (_e) {
console.warn(`Barcode '${barcode}' is not valid`);
}
for (let elem of targets) {
elem.click();
}
}
if (barcode.startsWith("O-CMD.")) {
const fn = COMMANDS[barcode];
if (fn) {
fn();
} else {
notification.add(env._t("Barcode: ") + `'${barcode}'`, {
title: env._t("Unknown barcode command"),
type: "danger"
});
}
}
});
}
})

View File

@@ -1,42 +0,0 @@
/** @odoo-module **/
import { registry } from '@web/core/registry';
import { formView } from '@web/views/form/form_view';
import { FormController } from '@web/views/form/form_controller';
import { listView } from '@web/views/list/list_view';
import { ListController } from '@web/views/list/list_controller'
import { onRendered, onMounted } from "@odoo/owl";
export class RemoveFocusFormController extends FormController {
setup() {
super.setup();
onMounted(() => {
this.__owl__.bdom.el.querySelectorAll(':focus').forEach(element => element.blur());
})
}
}
registry.category('views').add('remove_focus_form_view', {
...formView,
Controller: RemoveFocusFormController,
});
export class RemoveFocusListController extends ListController {
setup() {
super.setup();
onMounted(() => {
this.__owl__.bdom.el.querySelectorAll(':focus').forEach(element => element.blur());
})
}
}
registry.category('views').add('remove_focus_list_view', {
...listView,
Controller: RemoveFocusListController,
});

View File

@@ -263,6 +263,7 @@
<field name="materials_no" readonly="1" force_save="1"/> <field name="materials_no" readonly="1" force_save="1"/>
<field name="gain_way" required="0"/> <field name="gain_way" required="0"/>
<field name="density" readonly="1" required="1" class="custom_required"/> <field name="density" readonly="1" required="1" class="custom_required"/>
<field name="need_m" default="false" readonly="1"/>
</group> </group>
<group> <group>
<field name="rough_machining" required="1"/> <field name="rough_machining" required="1"/>
@@ -306,6 +307,7 @@
<field name="tensile_strength"/> <field name="tensile_strength"/>
<field name="hardness" optional="show"/> <field name="hardness" optional="show"/>
<field name="need_h"/> <field name="need_h"/>
<field name="need_m"/>
<field name="apply" widget="many2many_tags" optional="show"/> <field name="apply" widget="many2many_tags" optional="show"/>
<field name="density" optional="show"/> <field name="density" optional="show"/>
<field name="rough_machining" optional="hide"/> <field name="rough_machining" optional="hide"/>
@@ -352,6 +354,7 @@
<field name="materials_no"/> <field name="materials_no"/>
<field name="name"/> <field name="name"/>
<field name="need_h"/> <field name="need_h"/>
<field name="need_m"/>
<field name="mf_materia_post"/> <field name="mf_materia_post"/>
<field name="density"/> <field name="density"/>
<field name='materials_id' default="default" invisible="1"/> <field name='materials_id' default="default" invisible="1"/>

View File

@@ -222,9 +222,14 @@ class SfDemandPlan(models.Model):
line_ids = self.line_ids.filtered(lambda p: p.status == '30') line_ids = self.line_ids.filtered(lambda p: p.status == '30')
sum_product_uom_qty = sum(line_ids.mapped('plan_uom_qty')) sum_product_uom_qty = sum(line_ids.mapped('plan_uom_qty'))
customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers') customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers')
if not self.overdelivery_allowed and line_ids.filtered(lambda p: p.location_id.id == customer_location_id): check_overdelivery_allowed = False
for line in line_ids:
if line.location_id.id == customer_location_id:
if not self.overdelivery_allowed:
if float_compare(sum_product_uom_qty, self.product_uom_qty, if float_compare(sum_product_uom_qty, self.product_uom_qty,
precision_rounding=self.product_id.uom_id.rounding) == 1: precision_rounding=line.product_id.uom_id.rounding) == 1:
check_overdelivery_allowed = True
if check_overdelivery_allowed:
raise ValidationError(f"已禁止向合作伙伴/客户超量发货,请更换“补货原因”或将“可超量发货”设置为“是”。") raise ValidationError(f"已禁止向合作伙伴/客户超量发货,请更换“补货原因”或将“可超量发货”设置为“是”。")
elif float_compare(sum_product_uom_qty, self.product_uom_qty, elif float_compare(sum_product_uom_qty, self.product_uom_qty,
precision_rounding=self.product_id.uom_id.rounding) == 1: precision_rounding=self.product_id.uom_id.rounding) == 1:

View File

@@ -7,39 +7,17 @@ from odoo.tools import float_compare
from datetime import datetime, timedelta from datetime import datetime, timedelta
from odoo.exceptions import UserError from odoo.exceptions import UserError
import re import re
#本地环境问题 不加报错
class ProductCategory(models.Model):
_inherit = 'product.category'
negative_inventory_allowed = fields.Boolean(string="允许负库存", default=False)
class StockPicking(models.Model):
_inherit = 'stock.picking'
whether_show_quality_check = fields.Boolean(string="是否显示质检")
class ProductTemplate(models.Model):
_inherit = 'product.template'
blank_type = fields.Selection([
('圆料', '圆料'),
('方料', '方料'),
], string='坯料分类')
blank_precision = fields.Selection([
('精坯', '精坯'),
('粗坯', '粗坯'),
], string='坯料类型')
class SfProductionDemandPlan(models.Model): class SfProductionDemandPlan(models.Model):
_name = 'sf.production.demand.plan' _name = 'sf.production.demand.plan'
_description = 'sf_production_demand_plan' _description = 'sf_production_demand_plan'
def get_location_id(self): def get_location_id(self):
stock_location = self.env['stock.location'].sudo().search([('name', '=', '客户')], limit=1) customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers')
return stock_location.id return customer_location_id
priority = fields.Selection(related='demand_plan_id.priority', string='优先级') priority = fields.Selection(related='demand_plan_id.priority', string='优先级', store=True)
status = fields.Selection([ status = fields.Selection([
('10', '草稿'), ('10', '草稿'),
('20', '待确认'), ('20', '待确认'),
@@ -56,7 +34,7 @@ class SfProductionDemandPlan(models.Model):
company_id = fields.Many2one( company_id = fields.Many2one(
related='sale_order_id.company_id', related='sale_order_id.company_id',
store=True, index=True, precompute=True) store=True, index=True, precompute=True)
customer_name = fields.Char('客户', related='sale_order_id.customer_name') customer_name = fields.Char('客户', related='sale_order_id.customer_name', store=True)
order_remark = fields.Text(related='sale_order_id.remark', order_remark = fields.Text(related='sale_order_id.remark',
string="订单备注", store=True) string="订单备注", store=True)
glb_url = fields.Char(related='sale_order_line_id.glb_url', string='glb文件地址') glb_url = fields.Char(related='sale_order_line_id.glb_url', string='glb文件地址')
@@ -105,7 +83,7 @@ class SfProductionDemandPlan(models.Model):
related='product_id.blank_precision') related='product_id.blank_precision')
unit_number = fields.Float('单件用量', digits=(16, 3), related='product_id.unit_number') unit_number = fields.Float('单件用量', digits=(16, 3), related='product_id.unit_number')
embryo_long = fields.Char('坯料尺寸(mm)', related='demand_plan_id.embryo_long') embryo_long = fields.Char('坯料尺寸(mm)', related='demand_plan_id.embryo_long')
materials_id = fields.Char('材料', related='demand_plan_id.materials_id') materials_id = fields.Char('材料', related='demand_plan_id.materials_id', store=True)
model_machining_precision = fields.Selection(related='product_id.model_machining_precision', string='精度') model_machining_precision = fields.Selection(related='product_id.model_machining_precision', string='精度')
model_process_parameters_ids = fields.Many2many(related='demand_plan_id.model_process_parameters_ids', model_process_parameters_ids = fields.Many2many(related='demand_plan_id.model_process_parameters_ids',
string='表面工艺', ) string='表面工艺', )
@@ -149,6 +127,12 @@ class SfProductionDemandPlan(models.Model):
string='字段自制类型只读' string='字段自制类型只读'
) )
is_processing = fields.Boolean(
string='正在处理中',
default=False,
help='用于防止重复点击按钮'
)
# hide_action_open_mrp_production = fields.Boolean( # hide_action_open_mrp_production = fields.Boolean(
# string='显示待工艺确认按钮', # string='显示待工艺确认按钮',
# compute='_compute_hid_button', # compute='_compute_hid_button',
@@ -629,11 +613,6 @@ class SfProductionDemandPlan(models.Model):
filtered_plan = self.filtered(lambda mo: mo.status == '30') filtered_plan = self.filtered(lambda mo: mo.status == '30')
if not filtered_plan: if not filtered_plan:
raise UserError(_("没有需要下达的计划!")) raise UserError(_("没有需要下达的计划!"))
check_overdelivery_allowed = False
if not self.demand_plan_id.overdelivery_allowed:
customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers')
if self.location_id.id == customer_location_id:
check_overdelivery_allowed = True
# 按产品分组并计算总数 # 按产品分组并计算总数
product_data = {} product_data = {}
for plan in filtered_plan: for plan in filtered_plan:
@@ -681,9 +660,15 @@ class SfProductionDemandPlan(models.Model):
'default_demand_plan_line_id': self.ids, 'default_demand_plan_line_id': self.ids,
'default_release_message': warning_message, 'default_release_message': warning_message,
}} }}
else:
for demand_plan_line_id in filtered_plan:
demand_plan_line_id.action_confirm()
def button_release_plan(self): def button_release_plan(self):
self.ensure_one() self.ensure_one()
if self.is_processing:
return
self.is_processing = True
check_overdelivery_allowed = False check_overdelivery_allowed = False
if not self.demand_plan_id.overdelivery_allowed: if not self.demand_plan_id.overdelivery_allowed:
customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers') customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers')
@@ -710,49 +695,38 @@ class SfProductionDemandPlan(models.Model):
self.action_confirm() self.action_confirm()
def action_confirm(self): def action_confirm(self):
""" self = self.with_context(
确认需求计划行,创建 BOM、触发库存规则并更新状态。 demand_plan_line_id=self.id
""" )
# 将当前需求计划行 ID 写入上下文,便于后续方法使用
self = self.with_context(demand_plan_line_id=self.id)
# 创建物料清单BOM根据供货方式进行不同的处理
self.mrp_bom_create() self.mrp_bom_create()
# 启动库存规则(创建采购、生产等)
self._action_launch_stock_rule() self._action_launch_stock_rule()
# 根据供货方式设置状态字段
if self.supply_method in ('automation', 'manual'): if self.supply_method in ('automation', 'manual'):
self.write({'status': '50'}) # 自动/手工 供货:待排产 self.write({'status': '50'})
self.update_sale_order_state() self.update_sale_order_state()
else: else:
self.write({'status': '60'}) # 外购/外协/客户自供:无需排产 self.write({'status': '60'})
self.update_sale_order_state() self.update_sale_order_state()
def _get_embryo_template_by_supply_method(self):
"""
根据供货方式返回对应的胚料模板 product.template 记录。
"""
supply_map = {
'automation': self.env.ref('sf_dlm.product_embryo_sf_self_machining').sudo(),
'outsourcing': self.env.ref('sf_dlm.product_embryo_sf_outsource').sudo(),
'purchase': self.env.ref('sf_dlm.product_embryo_sf_purchase').sudo(),
'manual': self.env.ref('jikimo_sale_multiple_supply_methods.product_template_manual_processing').sudo(),
'material_customer_provided': self.env.ref('jikimo_sale_multiple_supply_methods.product_template_embryo_customer_provided').sudo(),
}
template = supply_map.get(self.supply_method)
if not template:
raise UserError(f"未配置供货方式 {self.supply_method} 对应的胚料模板")
return template
def mrp_bom_create(self): def mrp_bom_create(self):
""" bom_type = ''
创建 BOM包含胚料与成品 BOM用于后续生产或采购流程。 # 根据供货方式修改成品模板
""" if self.supply_method == 'automation':
# 如果同一计划中已有对应的 BOM 可复用,则直接使用 bom_type = 'normal'
product_template_id = self.env.ref('sf_dlm.product_template_sf').sudo().product_tmpl_id
elif self.supply_method == 'outsourcing':
bom_type = 'subcontract'
product_template_id = self.env.ref(
'jikimo_sale_multiple_supply_methods.product_template_outsourcing').sudo()
elif self.supply_method == 'purchase':
product_template_id = self.env.ref(
'jikimo_sale_multiple_supply_methods.product_template_purchase').sudo()
elif self.supply_method == 'manual':
bom_type = 'normal'
product_template_id = self.env.ref(
'jikimo_sale_multiple_supply_methods.product_template_manual_processing').sudo()
# 复制成品模板上的属性
self.product_id.product_tmpl_id.copy_template(product_template_id)
if self.supply_method in ('automation', 'manual'): if self.supply_method in ('automation', 'manual'):
line_ids = self.demand_plan_id.line_ids.filtered( line_ids = self.demand_plan_id.line_ids.filtered(
lambda p: p.supply_method in ('automation', 'manual') and p.status in ('50', '60')) lambda p: p.supply_method in ('automation', 'manual') and p.status in ('50', '60'))
@@ -765,32 +739,13 @@ class SfProductionDemandPlan(models.Model):
if line_ids: if line_ids:
self.bom_id = line_ids[0].bom_id.id self.bom_id = line_ids[0].bom_id.id
return return
# 根据供货方式选择模板和 BOM 类型
bom_type = ''
if self.supply_method == 'automation':
bom_type = 'normal'
product_template_id = self.env.ref('sf_dlm.product_template_sf').sudo().product_tmpl_id
elif self.supply_method == 'outsourcing':
bom_type = 'subcontract'
product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_outsourcing').sudo()
elif self.supply_method == 'purchase':
product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_purchase').sudo()
elif self.supply_method == 'manual':
bom_type = 'normal'
product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_manual_processing').sudo()
# 使用模板复制内容到当前产品
self.product_id.product_tmpl_id.copy_template(product_template_id)
# 构造 BOM 编码(包含时间戳)
future_time = datetime.now() + timedelta(hours=8) future_time = datetime.now() + timedelta(hours=8)
# 生成BOM单据编码
code = f"{self.product_id.default_code}-{bom_type}-{future_time.strftime('%Y%m%d%H%M%S')}" code = f"{self.product_id.default_code}-{bom_type}-{future_time.strftime('%Y%m%d%H%M%S')}"
order_id = self.sale_order_id order_id = self.sale_order_id
product = self.product_id product = self.product_id
# 拼接方法需要的item结构成品的模型数据信息就是坯料的数据信息
# 构造胚料产品的参数
item = { item = {
'texture_code': product.materials_id.materials_no, 'texture_code': product.materials_id.materials_no,
'texture_type_code': product.materials_type_id.materials_no, 'texture_type_code': product.materials_type_id.materials_no,
@@ -803,84 +758,110 @@ class SfProductionDemandPlan(models.Model):
'embryo_redundancy_id': self.sale_order_line_id.embryo_redundancy_id, 'embryo_redundancy_id': self.sale_order_line_id.embryo_redundancy_id,
'model_id': self.model_id 'model_id': self.model_id
} }
# 从产品名中提取编号(如 S12345-3
product_name = '' product_name = ''
match = re.search(r'(S\d{5}-\d+)', product.name) match = re.search(r'(S\d{5}-\d+)', product.name)
product_seria = 0 product_seria = 0
# 如果匹配成功,提取结果
if match: if match:
product_name = match.group(0) product_name = match.group(0)
# 获取成品名结尾-n的n
product_seria = int(product_name.split('-')[-1]) product_seria = int(product_name.split('-')[-1])
# 如果供货方式不是采购,则需要先创建胚料产品 # 成品供货方式为采购则不生成bom
if self.supply_method != 'purchase': if self.supply_method != 'purchase':
# 判断是否为客户自供 # 当成品上带有客供料选项时,生成坯料时选择“客供料”路线
if self.sale_order_line_id.embryo_redundancy_id: if self.sale_order_line_id.embryo_redundancy_id:
embryo_template = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_embryo_customer_provided').sudo() # 将成品模板的内容复制到成品上
embryo_key = 'material_customer_provided' customer_provided_embryo = self.env.ref(
else: 'jikimo_sale_multiple_supply_methods.product_template_embryo_customer_provided').sudo()
embryo_template = self._get_embryo_template_by_supply_method() # 创建坯料客供料的批量不需要创建bom
embryo_key = self.supply_method material_customer_provided_embryo = self.env['product.template'].sudo().no_bom_product_create(
customer_provided_embryo.with_context(active_test=False).product_variant_id,
# 获取批次追踪方式 依据模版 item,
tracking_method = embryo_template.tracking order_id, 'material_customer_provided', product_seria, product)
# 成品配置bom
# 创建胚料产品(无 BOM 产品) product_bom_material_customer_provided = self.env['mrp.bom'].with_user(
embryo_product = self.env['product.template'].sudo().no_bom_product_create( self.env.ref("base.user_admin")).bom_create(
embryo_template.with_context(active_test=False).product_variant_id, product, bom_type, 'product', code)
product_bom_material_customer_provided.with_user(
self.env.ref("base.user_admin")).bom_create_line_has(
material_customer_provided_embryo)
self.bom_id = product_bom_material_customer_provided.id
elif self.product_id.materials_type_id.gain_way == '自加工':
self_machining_id = self.env.ref('sf_dlm.product_embryo_sf_self_machining').sudo()
# 创建坯料
self_machining_embryo = self.env['product.template'].sudo().no_bom_product_create(
self_machining_id,
item,
order_id, 'self_machining', product_seria, product)
# 创建坯料的bom
self_machining_bom = self.env['mrp.bom'].with_user(
self.env.ref("base.user_admin")).bom_create(
self_machining_embryo, 'normal', False)
# 创建坯料里bom的组件
self_machining_bom_line = self_machining_bom.with_user(
self.env.ref("base.user_admin")).bom_create_line(
self_machining_embryo)
if not self_machining_bom_line:
raise UserError('该订单模型的材料型号暂未有原材料,请先配置再进行分配')
# 产品配置bom
product_bom_self_machining = self.env['mrp.bom'].with_user(
self.env.ref("base.user_admin")).bom_create(
product, bom_type, 'product', code)
product_bom_self_machining.with_user(self.env.ref("base.user_admin")).bom_create_line_has(
self_machining_embryo)
self.bom_id = product_bom_self_machining.id
elif self.product_id.materials_type_id.gain_way == '外协':
outsource_id = self.env.ref('sf_dlm.product_embryo_sf_outsource').sudo()
# 创建坯料
outsource_embryo = self.env['product.template'].sudo().no_bom_product_create(outsource_id,
item, item,
order_id, order_id,
embryo_key, 'subcontract',
product_seria, product_seria,
product product)
) if outsource_embryo == -3:
if isinstance(embryo_product, models.Model): # 确保返回的是记录而非错误码
embryo_product.write({'tracking': tracking_method})
if embryo_product == -3:
raise UserError('该订单模型的材料型号暂未设置获取方式和供应商,请先配置再进行分配') raise UserError('该订单模型的材料型号暂未设置获取方式和供应商,请先配置再进行分配')
# 创建坯料的bom
# 设置胚料 BOM 类型 outsource_bom = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).bom_create(
if embryo_key in ('automation', 'manual', 'material_customer_provided'): outsource_embryo,
embryo_bom_type = 'normal' 'subcontract', True)
elif embryo_key == 'outsourcing': # 创建坯料的bom的组件
embryo_bom_type = 'subcontract' outsource_bom_line = outsource_bom.with_user(
elif embryo_key == 'purchase': self.env.ref("base.user_admin")).bom_create_line(outsource_embryo)
embryo_bom_type = 'purchase' if not outsource_bom_line:
else:
embryo_bom_type = 'normal'
# 创建胚料 BOM 及 BOM 行
embryo_bom = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).bom_create(
embryo_product, embryo_bom_type, True, tracking=tracking_method)
embryo_bom_line = embryo_bom.with_user(self.env.ref("base.user_admin")).bom_create_line(embryo_product)
if not embryo_bom_line:
raise UserError('该订单模型的材料型号暂未有原材料,请先配置再进行分配') raise UserError('该订单模型的材料型号暂未有原材料,请先配置再进行分配')
# 产品配置bom
# 创建成品 BOM包含胚料 product_bom_outsource = self.env['mrp.bom'].with_user(
product_bom = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).bom_create( self.env.ref("base.user_admin")).bom_create(product, bom_type, 'product', code)
product, bom_type, 'product', code, tracking=tracking_method) product_bom_outsource.with_user(self.env.ref("base.user_admin")).bom_create_line_has(
product_bom.with_user(self.env.ref("base.user_admin")).bom_create_line_has(embryo_product) outsource_embryo)
self.bom_id = product_bom_outsource.id
# 赋值 BOM ID elif self.product_id.materials_type_id.gain_way == '采购':
self.bom_id = product_bom.id purchase_id = self.env.ref('sf_dlm.product_embryo_sf_purchase').sudo()
purchase_embryo = self.env['product.template'].sudo().no_bom_product_create(purchase_id,
item,
order_id,
'purchase',
product_seria,
product)
if purchase_embryo and purchase_embryo == -3:
raise UserError('该订单模型的材料型号暂未设置获取方式和供应商,请先配置再进行分配')
else:
# 产品配置bom
product_bom_purchase = self.env['mrp.bom'].with_user(
self.env.ref("base.user_admin")).bom_create(product, bom_type, 'product', code)
product_bom_purchase.with_user(self.env.ref("base.user_admin")).bom_create_line_has(
purchase_embryo)
self.bom_id = product_bom_purchase.id
def _action_launch_stock_rule(self): def _action_launch_stock_rule(self):
"""
触发库存规则(如采购、生产),并确认相关拣货单。
"""
procurements = [] procurements = []
group_id = self.sale_order_id.procurement_group_id group_id = self.sale_order_id.procurement_group_id
if not group_id: if not group_id:
# 没有分组则创建
group_id = self.env['procurement.group'].create(self._prepare_procurement_group_vals()) group_id = self.env['procurement.group'].create(self._prepare_procurement_group_vals())
self.sale_order_id.procurement_group_id = group_id self.sale_order_id.procurement_group_id = group_id
else: else:
# 若已有分组但字段有变动则更新
updated_vals = {} updated_vals = {}
if group_id.partner_id != self.sale_order_id.partner_shipping_id: if group_id.partner_id != self.sale_order_id.partner_shipping_id:
updated_vals.update({'partner_id': self.sale_order_id.partner_shipping_id.id}) updated_vals.update({'partner_id': self.sale_order_id.partner_shipping_id.id})
@@ -888,42 +869,27 @@ class SfProductionDemandPlan(models.Model):
updated_vals.update({'move_type': self.sale_order_id.picking_policy}) updated_vals.update({'move_type': self.sale_order_id.picking_policy})
if updated_vals: if updated_vals:
group_id.write(updated_vals) group_id.write(updated_vals)
# 构造 procurement 所需的字段
values = self._prepare_procurement_values(group_id=group_id) values = self._prepare_procurement_values(group_id=group_id)
# 单位换算
line_uom = self.sale_order_line_id.product_uom line_uom = self.sale_order_line_id.product_uom
quant_uom = self.product_id.uom_id quant_uom = self.product_id.uom_id
plan_uom_qty, procurement_uom = line_uom._adjust_uom_quantities(self.plan_uom_qty, quant_uom) plan_uom_qty, procurement_uom = line_uom._adjust_uom_quantities(self.plan_uom_qty, quant_uom)
# 创建 procurement 请求
procurements.append(self.env['procurement.group'].Procurement( procurements.append(self.env['procurement.group'].Procurement(
self.product_id, plan_uom_qty, procurement_uom, self.product_id, plan_uom_qty, procurement_uom,
self.sale_order_id.partner_shipping_id.property_stock_customer, self.sale_order_id.partner_shipping_id.property_stock_customer,
self.product_id.display_name, self.sale_order_id.name, self.sale_order_id.company_id, values)) self.product_id.display_name, self.sale_order_id.name, self.sale_order_id.company_id, values))
# 执行调度
if procurements: if procurements:
procurement_group = self.env['procurement.group'] procurement_group = self.env['procurement.group']
if self.env.context.get('import_file'): if self.env.context.get('import_file'):
procurement_group = procurement_group.with_context(import_file=False) procurement_group = procurement_group.with_context(import_file=False)
procurement_group.run(procurements) procurement_group.run(procurements)
# 确认相关的拣货单
orders = self.mapped('sale_order_id') orders = self.mapped('sale_order_id')
for order in orders: for order in orders:
pickings_to_confirm = order.picking_ids.filtered(lambda p: p.state not in ['cancel', 'done']) pickings_to_confirm = order.picking_ids.filtered(lambda p: p.state not in ['cancel', 'done'])
if pickings_to_confirm: if pickings_to_confirm:
pickings_to_confirm.action_confirm() pickings_to_confirm.action_confirm()
return True return True
def _prepare_procurement_group_vals(self): def _prepare_procurement_group_vals(self):
"""
构造创建 procurement group 所需的字段。
"""
return { return {
'name': self.sale_order_id.name, 'name': self.sale_order_id.name,
'move_type': self.sale_order_id.picking_policy, 'move_type': self.sale_order_id.picking_policy,
@@ -931,18 +897,11 @@ class SfProductionDemandPlan(models.Model):
'partner_id': self.sale_order_id.partner_shipping_id.id, 'partner_id': self.sale_order_id.partner_shipping_id.id,
} }
def _prepare_procurement_values(self, group_id=False): def _prepare_procurement_values(self, group_id=False):
"""
构造单个 procurement 请求所需的字段字典。
"""
self.ensure_one() self.ensure_one()
# 交货日期与计划日期
date_deadline = self.sale_order_id.commitment_date or ( date_deadline = self.sale_order_id.commitment_date or (
self.sale_order_id.date_order + timedelta(days=self.sale_order_line_id.customer_lead or 0.0)) self.sale_order_id.date_order + timedelta(days=self.sale_order_line_id.customer_lead or 0.0))
date_planned = date_deadline - timedelta(days=self.sale_order_id.company_id.security_lead) date_planned = date_deadline - timedelta(days=self.sale_order_id.company_id.security_lead)
values = { values = {
'group_id': group_id, 'group_id': group_id,
'sale_line_id': self.sale_order_line_id.id, 'sale_line_id': self.sale_order_line_id.id,
@@ -958,6 +917,7 @@ class SfProductionDemandPlan(models.Model):
'sequence': self.sale_order_line_id.sequence, 'sequence': self.sale_order_line_id.sequence,
'demand_plan_line_id': self.id 'demand_plan_line_id': self.id
} }
return values return values
def button_plan_detail(self):
pass

View File

@@ -11,7 +11,7 @@
'category': 'sf', 'category': 'sf',
'website': 'https://www.sf.jikimo.com', 'website': 'https://www.sf.jikimo.com',
'depends': ['sf_base', 'sf_maintenance', 'web_widget_model_viewer', 'sf_warehouse', 'jikimo_attachment_viewer', 'depends': ['sf_base', 'sf_maintenance', 'web_widget_model_viewer', 'sf_warehouse', 'jikimo_attachment_viewer',
'jikimo_sale_multiple_supply_methods', 'product'], 'jikimo_sale_multiple_supply_methods', 'product', 'jikimo_tree_header_buttons_always_visible'],
'data': [ 'data': [
'data/cron_data.xml', 'data/cron_data.xml',
'data/stock_data.xml', 'data/stock_data.xml',

View File

@@ -178,6 +178,7 @@ class sfMaterialModel(models.Model):
materials_model.mf_materia_post = item['mf_materia_post'] materials_model.mf_materia_post = item['mf_materia_post']
materials_model.materials_id = materials.id materials_model.materials_id = materials.id
materials_model.need_h = item['need_h'] materials_model.need_h = item['need_h']
materials_model.need_m = item['need_m']
materials_model.density = item['density'] materials_model.density = item['density']
materials_model.active = item['active'] materials_model.active = item['active']
else: else:
@@ -192,6 +193,7 @@ class sfMaterialModel(models.Model):
"active": item['active'], "active": item['active'],
"materials_id": materials.id, "materials_id": materials.id,
"need_h": item['need_h'], "need_h": item['need_h'],
"need_m": item['need_m'],
"mf_materia_post": item['mf_materia_post'], "mf_materia_post": item['mf_materia_post'],
"density": item['density'], "density": item['density'],
}) })
@@ -228,6 +230,7 @@ class sfMaterialModel(models.Model):
"standards_id": self.env['sf.international.standards'].search( "standards_id": self.env['sf.international.standards'].search(
[("name", '=', item['standards_id'])]).id, [("name", '=', item['standards_id'])]).id,
"need_h": item['need_h'], "need_h": item['need_h'],
"need_m": item['need_m'],
"alloy_code": item['alloy_code'], "alloy_code": item['alloy_code'],
"mf_materia_post": item['mf_materia_post'], "mf_materia_post": item['mf_materia_post'],
"density": item['density'], "density": item['density'],
@@ -248,6 +251,7 @@ class sfMaterialModel(models.Model):
materials_model.mf_materia_post = item['mf_materia_post'] materials_model.mf_materia_post = item['mf_materia_post']
materials_model.materials_id = materials.id materials_model.materials_id = materials.id
materials_model.need_h = item['need_h'] materials_model.need_h = item['need_h']
materials_model.need_m = item['need_m']
materials_model.density = item['density'] materials_model.density = item['density']
materials_model.active = item['active'] materials_model.active = item['active']
materials_model.materials_code= item['materials_code'] materials_model.materials_code= item['materials_code']

View File

@@ -45759,6 +45759,11 @@ msgstr ""
msgid "热处理" msgid "热处理"
msgstr "" msgstr ""
#. module: sf_base
#: model:ir.model.fields,field_description:sf_base.field_sf_materials_model__need_m
msgid "是否磁吸"
msgstr ""
#. module: sf_base #. module: sf_base
#: model:ir.model.fields,field_description:sf_base.field_sf_materials_model__mf_materia_post #: model:ir.model.fields,field_description:sf_base.field_sf_materials_model__mf_materia_post
msgid "热处理后密度" msgid "热处理后密度"

View File

@@ -155,7 +155,7 @@ class ReSaleOrder(models.Model):
'glb_url': item['glb_url'], 'glb_url': item['glb_url'],
'remark': item.get('remark'), 'remark': item.get('remark'),
'embryo_redundancy_id': item.get('embryo_redundancy_id'), 'embryo_redundancy_id': item.get('embryo_redundancy_id'),
'is_incoming_material': True if item.get('embryo_redundancy_id') else False, 'is_incoming_material': True if item.get('incoming_size') else False,
'manual_quotation': item.get('manual_quotation'), 'manual_quotation': item.get('manual_quotation'),
'model_id': item['model_id'], 'model_id': item['model_id'],
'delivery_end_date': item['delivery_end_date'] 'delivery_end_date': item['delivery_end_date']
@@ -287,7 +287,7 @@ class ResaleOrderLine(models.Model):
check_status = fields.Selection(related='order_id.check_status') check_status = fields.Selection(related='order_id.check_status')
remark = fields.Char('备注') remark = fields.Char('备注')
is_incoming_material = fields.Boolean('客供料', compute='_compute_is_incoming_material', store=True) is_incoming_material = fields.Boolean('客供料', store=True)
embryo_redundancy_id = fields.Many2one('sf.embryo.redundancy', '坯料冗余') embryo_redundancy_id = fields.Many2one('sf.embryo.redundancy', '坯料冗余')
manual_quotation = fields.Boolean('人工编程', default=False) manual_quotation = fields.Boolean('人工编程', default=False)
model_url = fields.Char('模型文件地址') model_url = fields.Char('模型文件地址')