Compare commits

..

14 Commits

Author SHA1 Message Date
liaodanlong
9f67dbe9aa 工序外协工单没有自动触发工单开始、结束的优化需求处理 2024-12-12 16:06:55 +08:00
liaodanlong
ab32f881c2 制造订单退回调整删除表面工艺再次确认后-没被删除的表面工艺的外协出入库单变成了草稿状态问题处理 2024-12-11 17:09:51 +08:00
liaodanlong
f32ca13dff 修改日志的使用库 2024-12-11 11:05:25 +08:00
liaodanlong
d1ba2cc3d4 Merge branch 'refs/heads/develop' into feature/delivery_status
# Conflicts:
#	sf_manufacturing/models/mrp_production.py
2024-12-11 10:07:34 +08:00
liaodanlong
4738b03a45 销售订单与制造订单关联 2024-12-11 10:03:20 +08:00
禹翔辉
e14e750bd9 Accept Merge Request #1610: (feature/返工入口 -> develop)
Merge Request: 开放返工入口

Created By: @禹翔辉
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @禹翔辉
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1610?initial=true
2024-12-09 16:08:52 +08:00
yuxianghui
1c4a6ca85e 开放返工入口 2024-12-09 16:07:34 +08:00
管欢
c922ae1571 Accept Merge Request #1609: (feature/manufactur_order -> develop)
Merge Request: 手动创建的采购单生成的内部调拨单没有源单据

Created By: @管欢
Reviewed By: @胡尧
Approved By: @胡尧 
Accepted By: @管欢
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1609
2024-12-09 09:48:12 +08:00
guanhuan
ed6189a963 Merge remote-tracking branch 'origin/feature/manufactur_order' into feature/manufactur_order 2024-12-09 09:36:08 +08:00
guanhuan
a6979b213b 手动创建的采购单生成的内部调拨单没有源单据 2024-12-09 09:35:41 +08:00
马广威
f873ebe079 Accept Merge Request #1608: (release/release_2.6 -> develop)
Merge Request: Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1608
2024-12-05 18:26:29 +08:00
马广威
e50b601ccf Accept Merge Request #1607: (feature/制造功能优化 -> develop)
Merge Request: 对合并后的采购单修改匹配逻辑

Created By: @马广威
Accepted By: @马广威
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1607?initial=true
2024-12-05 18:15:09 +08:00
mgw
37c47b0a54 对合并后的采购单修改匹配逻辑 2024-12-05 18:14:19 +08:00
liaodanlong
73ab43f16a 人工线下加工 2024-11-28 10:05:17 +08:00
8 changed files with 114 additions and 19 deletions

View File

@@ -15,3 +15,4 @@ from . import sf_technology_design
from . import sf_production_common
from . import sale_order
from . import quick_easy_order
from . import purchase_order

View File

@@ -8,6 +8,7 @@ import re
import requests
from itertools import groupby
from collections import defaultdict, namedtuple
from odoo import api, fields, models, SUPERUSER_ID, _
from odoo.exceptions import UserError, ValidationError
from odoo.addons.sf_base.commons.common import Common
@@ -18,6 +19,7 @@ class MrpProduction(models.Model):
_inherit = 'mrp.production'
_description = "制造订单"
_order = 'create_date desc'
sale_order_id = fields.Many2one('sale.order', string='销售订单', compute='_compute_sale_order_id', store=True)
deadline_of_delivery = fields.Date('订单交期', tracking=True, compute='_compute_deadline_of_delivery')
# tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘")
maintenance_count = fields.Integer(compute='_compute_maintenance_count', string="Number of maintenance requests")
@@ -34,6 +36,29 @@ class MrpProduction(models.Model):
tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True)
tool_state_remark2 = fields.Text(string='功能刀具状态备注(无效刀)', readonly=True)
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
def _compute_sale_order_id(self):
for production in self:
# 初始化 sale_order_id 为 False
sale_order_id = False
# 使用正则表达式查找产品名称中的 'S' 开头的字母数字字符串
match = re.search(r'S\d+', production.product_id.with_context(lang='zh_CN').name) # 从字符串开始匹配
if match:
result = match.group(0)
try:
# 查找与匹配的字符串相符的销售订单
sale_order = self.env['sale.order'].search(
[('name', '=', result)], limit=1, order='id asc'
)
if sale_order:
production.sale_order_id = sale_order.id
else:
logging.warning("No sale order found for production {} with product {} (name match: {})".format(
production.id, production.product_id.name, result))
except Exception as e:
logging.error("Error while fetching sale order for production {}: {}".format(production.id, str(e)))
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
def _compute_deadline_of_delivery(self):
for production in self:
@@ -762,7 +787,7 @@ class MrpProduction(models.Model):
# 立即创建外协出入库单和采购订单
# self.env['stock.picking'].create_outcontract_picking(workorder, production)
# self.env['purchase.order'].get_purchase_order(workorder, production,
# product_id_to_production_names)
# product_id_to_production_names)
consecutive_workorders = []
# 处理最后一个组,即使它可能只有一个工作订单
@@ -774,6 +799,7 @@ class MrpProduction(models.Model):
for workorders in reversed(proc_workorders):
self.env['stock.picking'].create_outcontract_picking(workorders, production, sorted_workorders)
self.env['purchase.order'].get_purchase_order(workorders, production, product_id_to_production_names)
# 工单排序
def _reset_work_order_sequence1(self, k):
for rec in self:
@@ -1435,6 +1461,26 @@ class MrpProduction(models.Model):
for production in self:
production.production_type = '自动化产线加工' if not production.product_id.is_manual_processing else '人工线下加工'
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
def _compute_sale_order_count(self):
for production in self:
if production.sale_order_id:
production.sale_order_count = 1
else:
production.sale_order_count = 0
def action_view_sale_orders(self):
if self.sale_order_id:
action = {
'res_model': 'sale.order',
'type': 'ir.actions.act_window',
}
action.update({
'view_mode': 'form',
'res_id': self.sale_order_id.id,
})
return action
@api.model_create_multi
def create(self, vals_list):
"""

View File

@@ -129,7 +129,7 @@ class ResMrpWorkOrder(models.Model):
Y10_axis = fields.Float(default=0)
Z10_axis = fields.Float(default=0)
X_deviation_angle = fields.Integer(string="X轴偏差度", default=0)
test_results = fields.Selection([("合格", "合格")], default='合格',
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], default='合格',
string="检测结果", tracking=True)
cnc_ids = fields.One2many("sf.cnc.processing", 'workorder_id', string="CNC加工程序")
cmm_ids = fields.One2many("sf.cmm.program", 'workorder_id', string="CMM程序")

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from collections import defaultdict
from odoo import api, fields, models, _
from odoo.tools import OrderedSet
# _get_surface_technics_purchase_ids
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
def button_confirm(self):
super().button_confirm()
workorders = self.env['mrp.workorder'].search([('purchase_id', '=', self.id)])
for workorder in workorders:
if workorder.routing_type == '表面工艺' and workorder.is_subcontract is True:
move_out = workorder.move_subcontract_workorder_ids[1]
# move_out = self.env['stock.move'].search(
# [('location_id', '=', self.env['stock.location'].search(
# [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
# ('location_dest_id', '=', self.env['stock.location'].search(
# [('barcode', 'ilike', 'VL-SPOC')]).id),
# ('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])])
for mo in move_out:
if mo.state != 'done':
mo.write({'state': 'assigned', 'production_id': False})
if not mo.move_line_ids:
self.env['stock.move.line'].create(mo.get_move_line(workorder.production_id, workorder))
return True

View File

@@ -644,20 +644,27 @@ class StockPicking(models.Model):
workorder = move_in.subcontract_workorder_id
workorders = workorder.production_id.workorder_ids
subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True).sorted('sequence')
if workorder == subcontract_workorders[-1]:
if workorder == subcontract_workorders[-1]:
self.env['stock.quant']._update_reserved_quantity(
move_in.product_id, move_in.location_dest_id, move_in.product_uom_qty, lot_id=move_in.move_line_ids.lot_id,
move_in.product_id, move_in.location_dest_id, move_in.product_uom_qty,
lot_id=move_in.move_line_ids.lot_id,
package_id=False, owner_id=False, strict=False
)
workorder.button_finish()
picking_type_out = self.env.ref('sf_manufacturing.outcontract_picking_out').id
if res and self.picking_type_id.id == picking_type_out:
move_out = self.move_ids
if move_out:
workorder = move_out.subcontract_workorder_id
workorder.button_start()
return res
# 创建 外协出库入单
def create_outcontract_picking(self, workorders, item, sorted_workorders):
for workorder in workorders:
if workorder.move_subcontract_workorder_ids:
workorder.move_subcontract_workorder_ids.write({'state': 'draft'})
workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'draft'})
workorder.move_subcontract_workorder_ids.write({'state': 'waiting'})
workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'waiting'})
else:
# 创建一个新的补货组
procurement_group_id = self.env['procurement.group'].create({
@@ -671,14 +678,16 @@ class StockPicking(models.Model):
else:
# 从sorted_workorders中找到上一工单的move
if sorted_workorders.index(workorder) > 0:
move_dest_id = sorted_workorders[sorted_workorders.index(workorder) - 1].move_subcontract_workorder_ids[1].id
move_dest_id = \
sorted_workorders[sorted_workorders.index(workorder) - 1].move_subcontract_workorder_ids[1].id
new_picking = True
outcontract_picking_type_in = self.env.ref(
'sf_manufacturing.outcontract_picking_in').id,
outcontract_picking_type_out = self.env.ref(
'sf_manufacturing.outcontract_picking_out').id,
moves_in = self.env['stock.move'].sudo().create(
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_in, procurement_group_id.id, move_dest_id))
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_in,
procurement_group_id.id, move_dest_id))
picking_in = self.create(
moves_in._get_new_picking_values_Res(item, workorder, 'WH/OCIN/'))
# pick_ids.append(picking_in.id)
@@ -686,7 +695,8 @@ class StockPicking(models.Model):
{'picking_id': picking_in.id, 'state': 'waiting'})
moves_in._assign_picking_post_process(new=new_picking)
moves_out = self.env['stock.move'].sudo().create(
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_out, procurement_group_id.id, moves_in.id))
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_out,
procurement_group_id.id, moves_in.id))
workorder.write({'move_subcontract_workorder_ids': [(6, 0, [moves_in.id, moves_out.id])]})
picking_out = self.create(
moves_out._get_new_picking_values_Res(item, workorder, 'WH/OCOUT/'))
@@ -694,8 +704,7 @@ class StockPicking(models.Model):
moves_out.write(
{'picking_id': picking_out.id, 'state': 'waiting'})
moves_out._assign_picking_post_process(new=new_picking)
@api.depends('move_type', 'immediate_transfer', 'move_ids.state', 'move_ids.picking_id')
def _compute_state(self):
super(StockPicking, self)._compute_state()
@@ -706,7 +715,9 @@ class StockPicking(models.Model):
if picking.move_ids:
workorder = picking.move_ids[0].subcontract_workorder_id
if picking.state == 'assigned':
if workorder.state in ['pending', 'waiting'] or workorder._get_surface_technics_purchase_ids().state in ['draft', 'sent']:
if workorder.state in ['pending',
'waiting'] or workorder._get_surface_technics_purchase_ids().state in [
'draft', 'sent']:
picking.state = 'waiting'
@@ -719,7 +730,8 @@ class ReStockMove(models.Model):
def _get_stock_move_values_Res(self, item, picking_type_id, group_id, move_dest_ids=False):
route_id = self.env.ref('sf_manufacturing.route_surface_technology_outsourcing').id
stock_rule = self.env['stock.rule'].sudo().search([('route_id', '=', route_id), ('picking_type_id', '=', picking_type_id)])
stock_rule = self.env['stock.rule'].sudo().search(
[('route_id', '=', route_id), ('picking_type_id', '=', picking_type_id)])
move_values = {
'name': '',
'company_id': item.company_id.id,
@@ -993,11 +1005,13 @@ class ReStockMove(models.Model):
production = self.env['mrp.production'].search([('name', '=', self[0].origin)], limit=1, order='id asc')
productions = self.env['mrp.production'].search(
[('origin', '=', production.origin), ('product_id', '=', production.product_id.id)])
res['origin'] = ','.join(productions.mapped('name'))
if productions.mapped('name'):
res['origin'] = ','.join(productions.mapped('name'))
res['retrospect_ref'] = production.product_id.name
return res
subcontract_workorder_id = fields.Many2one('mrp.workorder', '外协工单组件', check_company=True, index='btree_not_null')
subcontract_workorder_id = fields.Many2one('mrp.workorder', '外协工单组件', check_company=True,
index='btree_not_null')
class ReStockQuant(models.Model):

View File

@@ -43,6 +43,7 @@
<field name="activity_ids" string="下一个活动" widget="list_activity" optional="hide"/>
</xpath>
<xpath expr="//field[@name='origin']" position="replace">
<field name="sale_order_id" optional="show"/>
<field name="origin" optional="hide"/>
</xpath>
<xpath expr="//field[@name='components_availability']" position="replace">
@@ -123,6 +124,7 @@
<field name="tool_state"
attrs="{'invisible': [('production_type', 'not in', ['自动化产线加工'])]}"/>
<field name="tool_state_remark" string="备注" attrs="{'invisible': [('tool_state', '!=', '1')]}"/>
<field name="sale_order_id" readonly="1"/>
<field name="deadline_of_delivery" readonly="1"/>
<field name="tool_state_remark2" invisible="1"/>
</xpath>
@@ -584,6 +586,7 @@
<searchpanel>
<field name="state" icon="fa-filter" enable_counters="1"/>
<field name="delivery_status" icon="fa-filter" enable_counters="1"/>
<field name="production_type" icon="fa-filter" enable_counters="1"/>
</searchpanel>
</xpath>
<filter name='todo' position="replace"/>

View File

@@ -200,7 +200,7 @@
<!-- attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked'),('state','=','done')]}"/> -->
<!-- <button name="button_workpiece_delivery" type="object" string="工件配送" class="btn-primary"-->
<!-- attrs="{'invisible': ['|','|','|','|',('routing_type','!=','装夹预调'),('is_delivery','=',True),('state','!=','done'),('is_rework','=',True),'&amp;',('rfid_code','in',['',False]),('state','=','done')]}"/>-->
<button name="button_rework_pre" type="object" string="异常反馈" invisible="1"
<button name="button_rework_pre" type="object" string="异常反馈"
class="btn-primary"
attrs="{'invisible': ['|','|',('routing_type','!=','装夹预调'),('state','!=','progress'),('is_rework','=',True)]}"/>
<button name="unbind_tray" type="object" string="解绑托盘"

View File

@@ -25,7 +25,7 @@ class SfQualityCncTest(models.Model):
('pass', '合格'),
('fail', '不合格')], string='判定结果')
number = fields.Integer('数量', default=1)
test_results = fields.Selection([("合格", "合格")], string="检测结果")
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], string="检测结果")
reason = fields.Selection(
[("programming", "编程"), ("cutter", "刀具"), ("clamping", "装夹"), ("operate computer", "操机"),
("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因")