制造订单工序自动生成规则

This commit is contained in:
gqh
2022-11-16 17:35:42 +08:00
parent 4ce0a7670c
commit 4f0df9f2bd
4 changed files with 171 additions and 61 deletions

View File

@@ -2,14 +2,10 @@
import logging import logging
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from odoo.addons.stock.models.stock_rule import ProcurementException from odoo.addons.stock.models.stock_rule import ProcurementException
from re import findall as regex_findall
from dateutil.relativedelta import relativedelta from re import split as regex_split
from odoo import SUPERUSER_ID, _, api, fields, models, registry from odoo import SUPERUSER_ID, _, api, fields, models, registry
from odoo.exceptions import UserError
from odoo.osv import expression
from odoo.tools import float_compare, float_is_zero, html_escape from odoo.tools import float_compare, float_is_zero, html_escape
from odoo.tools.misc import split_every
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -29,6 +25,20 @@ class MrpProduction(models.Model):
_inherit = 'mrp.production' _inherit = 'mrp.production'
_description = "制造订单" _description = "制造订单"
def action_generate_serial(self):
self.ensure_one()
self.lot_producing_id = self.env['stock.production.lot'].create({
'product_id': self.product_id.id,
'company_id': self.company_id.id,
'name': self.env['stock.production.lot']._get_next_serial(self.company_id, self.product_id) or self.env[
'ir.sequence'].next_by_code('stock.lot.serial'),
})
if self.move_finished_ids.filtered(lambda m: m.product_id == self.product_id).move_line_ids:
self.move_finished_ids.filtered(
lambda m: m.product_id == self.product_id).move_line_ids.lot_id = self.lot_producing_id
if self.product_id.tracking == 'serial':
self._set_qty_producing()
# 重载根据工序生成工单的程序如果产品BOM中没有工序时 # 重载根据工序生成工单的程序如果产品BOM中没有工序时
# 根据产品对应的模板类型中工序,去生成工单; # 根据产品对应的模板类型中工序,去生成工单;
# CNC加工工序的选取规则 # CNC加工工序的选取规则
@@ -238,7 +248,6 @@ class StockRule(models.Model):
''' '''
创建制造订单时生成序列号 创建制造订单时生成序列号
''' '''
production.lot_producing_id._get_next_serial(production.company_id, production.product_id)
production.action_generate_serial() production.action_generate_serial()
origin_production = production.move_dest_ids and production.move_dest_ids[ origin_production = production.move_dest_ids and production.move_dest_ids[
0].raw_material_production_id or False 0].raw_material_production_id or False
@@ -259,3 +268,49 @@ class StockRule(models.Model):
values={'self': production, 'origin': origin_production}, values={'self': production, 'origin': origin_production},
subtype_id=self.env.ref('mail.mt_note').id) subtype_id=self.env.ref('mail.mt_note').id)
return True return True
class ProductionLot(models.Model):
_inherit = 'stock.production.lot'
@api.model
def generate_lot_names1(self, display_name, first_lot, count):
"""Generate `lot_names` from a string."""
if first_lot.__contains__(display_name):
first_lot = first_lot[(len(display_name)+1):]
# We look if the first lot contains at least one digit.
caught_initial_number = regex_findall(r"\d+", first_lot)
if not caught_initial_number:
return self.generate_lot_names1(display_name, first_lot + "0", count)
# We base the series on the last number found in the base lot.
initial_number = caught_initial_number[-1]
padding = len(initial_number)
# We split the lot name to get the prefix and suffix.
splitted = regex_split(initial_number, first_lot)
# initial_number could appear several times, e.g. BAV023B00001S00001
prefix = initial_number.join(splitted[:-1])
suffix = splitted[-1]
initial_number = int(initial_number)
lot_names = []
for i in range(0, count):
lot_names.append('%s-%s%s%s' % (
display_name,
prefix,
str(initial_number + i).zfill(padding),
suffix
))
return lot_names
@api.model
def _get_next_serial(self, company, product):
"""Return the next serial number to be attributed to the product."""
if product.tracking == "serial":
last_serial = self.env['stock.production.lot'].search(
[('company_id', '=', company.id), ('product_id', '=', product.id)],
limit=1, order='id DESC')
if last_serial:
return self.env['stock.production.lot'].generate_lot_names1(product.display_name, last_serial.name, 2)[
1]
return "%s-%03d" %(product.display_name,1)

View File

@@ -5,7 +5,7 @@ import logging
import math import math
from io import BytesIO from io import BytesIO
from odoo import api, fields, models, SUPERUSER_ID from odoo import api, fields, models, SUPERUSER_ID, _
from pystrich.code128 import Code128Encoder from pystrich.code128 import Code128Encoder
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
@@ -146,18 +146,18 @@ class MrpWorkOrder(models.Model):
(x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4)) (x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4))
y0 = ((y3 - y4) * (y2 * x1 - y1 * x2) - (y1 - y2) * (y4 * x3 - y3 * x4)) / ( y0 = ((y3 - y4) * (y2 * x1 - y1 * x2) - (y1 - y2) * (y4 * x3 - y3 * x4)) / (
(y3 - y4) * (x1 - x2) - (y1 - y2) * (x3 - x4)) (y3 - y4) * (x1 - x2) - (y1 - y2) * (x3 - x4))
x1 = ((x7 - x8) * (x6 * y5 - x5 * y7) - (x5 - x6) * (x8 * y7 - x7 * y8)) / ( x1 = ((x7 - x8) * (x6 * y5 - x5 * y6) - (x5 - x6) * (x8 * y7 - x7 * y8)) / (
(x7 - x8) * (y5 - y6) - (x5 - x6) * (y7 - y8)); (x7 - x8) * (y5 - y6) - (x5 - x6) * (y7 - y8));
y1 = ((y7 - y8) * (y6 * x5 - y5 * x7) - (y5 - y6) * (y8 * x7 - y7 * x8)) / ( y1 = ((y7 - y8) * (y6 * x5 - y5 * x6) - (y5 - y6) * (y8 * x7 - y7 * x8)) / (
(y7 - y8) * (x5 - x6) - (y5 - y6) * (x7 - x8)) (y7 - y8) * (x5 - x6) - (y5 - y6) * (x7 - x8))
x = (x0 + x1) / 2 x = (x0 + x1) / 2
y = (y0 + y1) / 2 y = (y0 + y1) / 2
z = z1 / 2 z = z1 / 2
jd = math.atan2((x7 - x8), (y7 - y8)) jd = math.atan2((x5 - x6), (y5 - y6))
jdz = jd * 180 / math.pi jdz = jd * 180 / math.pi
print("(%s,%s)" % (x, y)) print("(%.2f,%.2f)" % (x, y))
self.material_center_point = ("(%s,%s,%s)" % (x, y, z)) self.material_center_point = ("(%.2f,%.2f,%.2f)" % (x, y, z))
self.X_deviation_angle = jdz self.X_deviation_angle = jdz
X_deviation_angle = fields.Integer(string="X轴偏差度", default=0) X_deviation_angle = fields.Integer(string="X轴偏差度", default=0)
@@ -185,8 +185,8 @@ class MrpWorkOrder(models.Model):
}) })
else: else:
raise ValidationError('该托盘编码已失效') raise ValidationError('该托盘编码已失效')
else:return "" else:
return ""
# 解除托盘绑定 # 解除托盘绑定
def unbindtray(self): def unbindtray(self):

View File

@@ -1,6 +1,6 @@
<odoo> <odoo>
<data> <data>
<!-- 打印尺寸--> <!-- 托盘码打印尺寸-->
<record id="sf_tray1" model="report.paperformat"> <record id="sf_tray1" model="report.paperformat">
<field name="name">Dymo Label Sheet</field> <field name="name">Dymo Label Sheet</field>
<field name="default" eval="True"/> <field name="default" eval="True"/>
@@ -16,7 +16,7 @@
<field name="dpi">96</field> <field name="dpi">96</field>
</record> </record>
<!-- 打印动作--> <!-- 托盘码打印动作-->
<record id="label_sf_tray_code" model="ir.actions.report"> <record id="label_sf_tray_code" model="ir.actions.report">
<field name="name">打印条形码</field> <field name="name">打印条形码</field>
<field name="model">sf.tray</field> <field name="model">sf.tray</field>
@@ -28,7 +28,7 @@
<field name="paperformat_id" ref="sf_route_workcenter.sf_tray1"/> <field name="paperformat_id" ref="sf_route_workcenter.sf_tray1"/>
</record> </record>
<!-- 打印模板--> <!-- 托盘码打印模板-->
<template id="sf_tray_template"> <template id="sf_tray_template">
<t t-call="web.html_container"> <t t-call="web.html_container">
<t t-call="web.external_layout"> <t t-call="web.external_layout">
@@ -46,6 +46,40 @@
</template> </template>
<!-- 产品信息打印动作-->
<record id="label_sf_tray_code1" model="ir.actions.report">
<field name="name">打印产品信息</field>
<field name="model">mrp.workorder</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">sf_route_workcenter.sf_tray_template1</field>
<field name="report_file">sf_route_workcenter.sf_tray_template1</field>
<field name="binding_model_id" ref="model_mrp_workorder"/>
<field name="binding_type">report</field>
<field name="paperformat_id" ref="sf_route_workcenter.sf_tray1"/>
</record>
<!-- 产品信息打印模板-->
<template id="sf_tray_template1">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<t t-foreach="docs" t-as="o">
<div class="page">
<div t-field="o.production_id" style="text-align: center"/>
<div t-field="o.name" style="text-align: center"/>
</div>
</t>
</t>
</t>
</template>
</data> </data>
</odoo> </odoo>

View File

@@ -72,93 +72,113 @@
<group> <group>
<div>左面:</div> <div>左面:</div>
<div></div> <div></div>
<div class="o_address_city"> <div class="o_address_format">
<label for="X1_axis" string="x1"/> <label for="X1_axis" string="x1"/>
<field name='X1_axis' class="o_address_city"/> <field name='X1_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Y1_axis" string="y1"/> <label for="Y1_axis" string="y1"/>
<field name='Y1_axis' class="o_address_city"/> <field name='Y1_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Z1_axis" string="z1"/> <label for="Z1_axis" string="z1"/>
<field name='Z1_axis' class="o_address_city"/> <field name='Z1_axis' class="o_address_zip"/>
</div> </div>
<div class="o_address_city"> <div class="o_address_format">
<label for="X2_axis" string="x2"/> <label for="X2_axis" string="x2"/>
<field name='X2_axis' class="o_address_city"/> <field name='X2_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Y2_axis" string="y2"/> <label for="Y2_axis" string="y2"/>
<field name='Y2_axis' class="o_address_city"/> <field name='Y2_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Z2_axis" string="z2"/> <label for="Z2_axis" string="z2"/>
<field name='Z2_axis' class="o_address_city"/> <field name='Z2_axis' class="o_address_zip"/>
</div> </div>
<div>前面:</div> <div>前面:</div>
<div></div> <div></div>
<div class="o_address_city"> <div class="o_address_format">
<label for="X3_axis" string="x1"/> <label for="X3_axis" string="x1"/>
<field name='X3_axis' class="o_address_city"/> <field name='X3_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Y3_axis" string="y1"/> <label for="Y3_axis" string="y1"/>
<field name='Y3_axis' class="o_address_city"/> <field name='Y3_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Z3_axis" string="z1"/> <label for="Z3_axis" string="z1"/>
<field name='Z3_axis' class="o_address_city"/> <field name='Z3_axis' class="o_address_zip"/>
</div> </div>
<div class="o_address_city"> <div class="o_address_format">
<label for="X4_axis" string="x2"/> <label for="X4_axis" string="x2"/>
<field name='X4_axis' class="o_address_city"/> <field name='X4_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Y4_axis" string="y2"/> <label for="Y4_axis" string="y2"/>
<field name='Y4_axis' class="o_address_city"/> <field name='Y4_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Z4_axis" string="z2"/> <label for="Z4_axis" string="z2"/>
<field name='Z4_axis' class="o_address_city"/> <field name='Z4_axis' class="o_address_zip"/>
</div> </div>
<div>右面:</div> <div>右面:</div>
<div></div> <div></div>
<div class="o_address_city"> <div class="o_address_format">
<label for="X5_axis" string="x1"/> <label for="X5_axis" string="x1"/>
<field name='X5_axis' class="o_address_city"/> <field name='X5_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Y5_axis" string="y1"/> <label for="Y5_axis" string="y1"/>
<field name='Y5_axis' class="o_address_city"/> <field name='Y5_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Z5_axis" string="z1"/> <label for="Z5_axis" string="z1"/>
<field name='Z5_axis' class="o_address_city"/> <field name='Z5_axis' class="o_address_zip"/>
</div> </div>
<div class="o_address_city"> <div class="o_address_format">
<label for="X6_axis" string="x2"/> <label for="X6_axis" string="x2"/>
<field name='X6_axis' class="o_address_city"/> <field name='X6_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Y6_axis" string="y2"/> <label for="Y6_axis" string="y2"/>
<field name='Y6_axis' class="o_address_city"/> <field name='Y6_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Z6_axis" string="z2"/> <label for="Z6_axis" string="z2"/>
<field name='Z6_axis' class="o_address_city"/> <field name='Z6_axis' class="o_address_zip"/>
</div> </div>
<div>面:</div> <div>面:</div>
<div></div> <div></div>
<div class="o_address_city"> <div class="o_address_format">
<label for="X7_axis" string="x1"/> <label for="X7_axis" string="x1"/>
<field name='X7_axis' class="o_address_city"/> <field name='X7_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Y7_axis" string="y1"/> <label for="Y7_axis" string="y1"/>
<field name='Y7_axis' class="o_address_city"/> <field name='Y7_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Z7_axis" string="z1"/> <label for="Z7_axis" string="z1"/>
<field name='Z7_axis' class="o_address_city"/> <field name='Z7_axis' class="o_address_zip"/>
</div> </div>
<div class="o_address_city"> <div class="o_address_format">
<label for="X8_axis" string="x2"/> <label for="X8_axis" string="x2"/>
<field name='X8_axis' class="o_address_city"/> <field name='X8_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Y8_axis" string="y2"/> <label for="Y8_axis" string="y2"/>
<field name='Y8_axis' class="o_address_city"/> <field name='Y8_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Z8_axis" string="z2"/> <label for="Z8_axis" string="z2"/>
<field name='Z8_axis' class="o_address_city"/> <field name='Z8_axis' class="o_address_zip"/>
</div> </div>
<div>上面:</div> <div>上面:</div>
<div></div> <div></div>
<div class="o_address_city"> <div class="o_address_format">
<label for="X9_axis" string="x1"/> <label for="X9_axis" string="x1"/>
<field name='X9_axis' class="o_address_city"/> <field name='X9_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Y9_axis" string="y1"/> <label for="Y9_axis" string="y1"/>
<field name='Y9_axis' class="o_address_city"/> <field name='Y9_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Z9_axis" string="z1"/> <label for="Z9_axis" string="z1"/>
<field name='Z9_axis' class="o_address_city"/> <field name='Z9_axis' class="o_address_zip"/>
</div> </div>
<div class="o_address_city"> <div class="o_address_format">
<label for="X10_axis" string="x2"/> <label for="X10_axis" string="x2"/>
<field name='X10_axis' class="o_address_city"/> <field name='X10_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Y10_axis" string="y2"/> <label for="Y10_axis" string="y2"/>
<field name='Y10_axis' class="o_address_city"/> <field name='Y10_axis' class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="Z10_axis" string="z2"/> <label for="Z10_axis" string="z2"/>
<field name='Z10_axis' class="o_address_city"/> <field name='Z10_axis' class="o_address_zip"/>
</div> </div>
@@ -232,6 +252,7 @@
/> />
</div> </div>
</page> </page>
</xpath> </xpath>