Compare commits
46 Commits
master_sf_
...
feature/sy
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61bcd72a41 | ||
|
|
ee87e1dacf | ||
|
|
d0d4db1555 | ||
|
|
62cbb4b796 | ||
|
|
f040406002 | ||
|
|
bfff4ac440 | ||
|
|
a97386c37c | ||
|
|
18ae46207a | ||
|
|
bacddd2ad8 | ||
|
|
dd5794899d | ||
|
|
e5b730b2ef | ||
|
|
aea158de41 | ||
|
|
a933a0ffea | ||
|
|
7575424760 | ||
|
|
6c2eb40e6a | ||
|
|
f10f595fa4 | ||
|
|
6d1de42d76 | ||
|
|
5dc16c039c | ||
|
|
c416cdbeed | ||
|
|
18c7b22319 | ||
|
|
e0ba222382 | ||
|
|
58b00e6442 | ||
|
|
9182dbfb5d | ||
|
|
27516844af | ||
|
|
99237445ac | ||
|
|
9349ca91d3 | ||
|
|
c55f3d77bf | ||
|
|
95716c2e3e | ||
|
|
5f72519dc2 | ||
|
|
c24bba3137 | ||
|
|
01bb6fd0aa | ||
|
|
bf4add6b78 | ||
|
|
7d986fe139 | ||
|
|
fffbfc21c2 | ||
|
|
6451bfbc42 | ||
|
|
5aa848de53 | ||
|
|
4f181e5eba | ||
|
|
2bf43ae9a1 | ||
|
|
d98d04d4ed | ||
|
|
602d6678bc | ||
|
|
8fd0c4e1f1 | ||
|
|
514fd79c3e | ||
|
|
21d052e222 | ||
|
|
95e2c2db0d | ||
|
|
17a29b7b29 | ||
|
|
dd745423a1 |
@@ -17,6 +17,11 @@ class JikimoPrinting(models.AbstractModel):
|
|||||||
"""
|
"""
|
||||||
打印二维码
|
打印二维码
|
||||||
"""
|
"""
|
||||||
|
printer = self.env['printing.printer'].get_default()
|
||||||
|
if not printer:
|
||||||
|
_logger.error("未找到默认打印机")
|
||||||
|
return False
|
||||||
|
|
||||||
# 生成二维码
|
# 生成二维码
|
||||||
qr = qrcode.QRCode(version=1, box_size=10, border=5)
|
qr = qrcode.QRCode(version=1, box_size=10, border=5)
|
||||||
qr.add_data(data)
|
qr.add_data(data)
|
||||||
@@ -45,19 +50,23 @@ class JikimoPrinting(models.AbstractModel):
|
|||||||
|
|
||||||
# 获取PDF内容并打印
|
# 获取PDF内容并打印
|
||||||
pdf_content = pdf_buffer.getvalue()
|
pdf_content = pdf_buffer.getvalue()
|
||||||
printer = self.env['printing.printer'].get_default()
|
# _logger.info(f"打印内容: {pdf_content}")
|
||||||
_logger.info(f"打印内容: {pdf_content}")
|
|
||||||
printer.print_document(report=None, content=pdf_content, doc_format='pdf')
|
printer.print_document(report=None, content=pdf_content, doc_format='pdf')
|
||||||
|
|
||||||
# 清理资源
|
# 清理资源
|
||||||
pdf_buffer.close()
|
pdf_buffer.close()
|
||||||
temp_image.close()
|
temp_image.close()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def print_pdf(self, pdf_data):
|
def print_pdf(self, pdf_data):
|
||||||
"""
|
"""
|
||||||
打印PDF
|
打印PDF
|
||||||
"""
|
"""
|
||||||
_logger.info("PDF打印开始")
|
printer = self.env['printing.printer'].get_default()
|
||||||
|
if not printer:
|
||||||
|
_logger.error("未找到默认打印机")
|
||||||
|
return False
|
||||||
|
|
||||||
pdf_data_str = pdf_data.decode('ascii', errors='ignore')
|
pdf_data_str = pdf_data.decode('ascii', errors='ignore')
|
||||||
decoded_data = base64.b64decode(pdf_data_str)
|
decoded_data = base64.b64decode(pdf_data_str)
|
||||||
@@ -69,15 +78,10 @@ class JikimoPrinting(models.AbstractModel):
|
|||||||
|
|
||||||
# 获取PDF内容
|
# 获取PDF内容
|
||||||
pdf_content = pdf_buffer.getvalue()
|
pdf_content = pdf_buffer.getvalue()
|
||||||
_logger.info(f"处理后的内容前20字节: {pdf_content[:20]}")
|
|
||||||
|
|
||||||
# 获取默认打印机
|
|
||||||
printer = self.env['printing.printer'].get_default()
|
|
||||||
if not printer:
|
|
||||||
_logger.error("未找到默认打印机")
|
|
||||||
return
|
|
||||||
|
|
||||||
printer.print_document(report=None, content=pdf_content, doc_format='pdf')
|
printer.print_document(report=None, content=pdf_content, doc_format='pdf')
|
||||||
# 清理资源
|
# 清理资源
|
||||||
pdf_buffer.close()
|
pdf_buffer.close()
|
||||||
_logger.info("PDF打印结束")
|
|
||||||
|
_logger.info("成功打印PDF")
|
||||||
|
return True
|
||||||
@@ -21,8 +21,6 @@ class MrpWorkorder(models.Model):
|
|||||||
# 执行打印
|
# 执行打印
|
||||||
self.env['jikimo.printing'].print_pdf(pdf_data)
|
self.env['jikimo.printing'].print_pdf(pdf_data)
|
||||||
wo.production_id.product_id.is_print_program = True
|
wo.production_id.product_id.is_print_program = True
|
||||||
_logger.info(f"工单 {wo.name} 的PDF已成功打印")
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
_logger.error(f"工单 {wo.name} 的PDF打印失败: {str(e)}")
|
_logger.error(f"工单 {wo.name} 的PDF打印失败: {str(e)}")
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,14 @@
|
|||||||
'views/mrp_production.xml',
|
'views/mrp_production.xml',
|
||||||
'views/purchase_request_view.xml',
|
'views/purchase_request_view.xml',
|
||||||
'wizard/purchase_request_line_make_purchase_order_view.xml',
|
'wizard/purchase_request_line_make_purchase_order_view.xml',
|
||||||
|
'views/purchase_request_line_view.xml',
|
||||||
|
'views/stock_picking_views.xml',
|
||||||
],
|
],
|
||||||
# 'assets': {
|
'assets': {
|
||||||
# 'web.assets_backend': [
|
'web.assets_backend': [
|
||||||
# 'jikimo_purchase_request/static/src/**/*'
|
'jikimo_purchase_request/static/src/**/*'
|
||||||
# ],
|
],
|
||||||
# },
|
},
|
||||||
'application': True,
|
'application': True,
|
||||||
'installable': True,
|
'installable': True,
|
||||||
'auto_install': False,
|
'auto_install': False,
|
||||||
|
|||||||
@@ -1043,7 +1043,7 @@ msgstr "询价单"
|
|||||||
#. module: purchase_request
|
#. module: purchase_request
|
||||||
#: model:ir.model.fields,field_description:purchase_request.field_purchase_request_line__purchased_qty
|
#: model:ir.model.fields,field_description:purchase_request.field_purchase_request_line__purchased_qty
|
||||||
msgid "RFQ/PO Qty"
|
msgid "RFQ/PO Qty"
|
||||||
msgstr ""
|
msgstr "已订购数"
|
||||||
|
|
||||||
#. module: purchase_request
|
#. module: purchase_request
|
||||||
#. odoo-python
|
#. odoo-python
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ from . import sale_order
|
|||||||
from . import mrp_production
|
from . import mrp_production
|
||||||
from . import purchase_order
|
from . import purchase_order
|
||||||
from . import stock_rule
|
from . import stock_rule
|
||||||
|
from . import stock_picking
|
||||||
|
|||||||
@@ -9,12 +9,20 @@ class MrpProduction(models.Model):
|
|||||||
@api.depends('state')
|
@api.depends('state')
|
||||||
def _compute_pr_mp_count(self):
|
def _compute_pr_mp_count(self):
|
||||||
for item in self:
|
for item in self:
|
||||||
pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', item.name)])
|
# if item.product_id.product_tmpl_id.single_manufacturing == True and not item.is_remanufacture:
|
||||||
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', item.name), ('is_subcontract', '!=', 'True')])
|
# first_order = self.env['mrp.production'].search(
|
||||||
if pr_ids:
|
# [('origin', '=', item.origin), ('product_id', '=', item.product_id.id)], limit=1, order='id asc')
|
||||||
|
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', first_order.name)])
|
||||||
|
# item.pr_mp_count = len(pr_ids)
|
||||||
|
# else:
|
||||||
|
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', item.name)])
|
||||||
|
# item.pr_mp_count = len(pr_ids)
|
||||||
|
# 由于采购申请合并了所有销售订单行的采购,所以不区分产品
|
||||||
|
first_mp = self.env['mrp.production'].search(
|
||||||
|
[('origin', '=', item.origin)], limit=1, order='id asc')
|
||||||
|
pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', first_mp.name)])
|
||||||
item.pr_mp_count = len(pr_ids)
|
item.pr_mp_count = len(pr_ids)
|
||||||
else:
|
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', item.name), ('is_subcontract', '!=', 'True')])
|
||||||
item.pr_mp_count = 0
|
|
||||||
|
|
||||||
def action_view_pr_mp(self):
|
def action_view_pr_mp(self):
|
||||||
"""
|
"""
|
||||||
@@ -22,7 +30,18 @@ class MrpProduction(models.Model):
|
|||||||
"""
|
"""
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', self.name),('is_subcontract', '!=', True)])
|
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', self.name),('is_subcontract', '!=', True)])
|
||||||
pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', self.name)])
|
# if self.product_id.product_tmpl_id.single_manufacturing == True and not self.is_remanufacture:
|
||||||
|
# first_order = self.env['mrp.production'].search(
|
||||||
|
# [('origin', '=', self.origin), ('product_id', '=', self.product_id.id)], limit=1, order='id asc')
|
||||||
|
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', first_order.name)])
|
||||||
|
# else:
|
||||||
|
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', self.name)])
|
||||||
|
# 由于采购申请合并了所有销售订单行的采购,所以不区分产品
|
||||||
|
first_mp = self.env['mrp.production'].search(
|
||||||
|
[('origin', '=', self.origin)], limit=1, order='id asc')
|
||||||
|
pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', first_mp.name)])
|
||||||
|
|
||||||
|
|
||||||
action = {
|
action = {
|
||||||
'res_model': 'purchase.request',
|
'res_model': 'purchase.request',
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
|
|||||||
@@ -47,6 +47,19 @@ class PurchaseRequestLine(models.Model):
|
|||||||
('outsourcing', "委外加工"),
|
('outsourcing', "委外加工"),
|
||||||
], string='供货方式', compute='_compute_supply_method', store=True)
|
], string='供货方式', compute='_compute_supply_method', store=True)
|
||||||
|
|
||||||
|
purchase_request_count = fields.Integer(string='采购申请数量', compute='_compute_purchase_request_count', readonly=True)
|
||||||
|
purchase_count = fields.Integer(string="采购订单数量", compute="_compute_purchase_count", readonly=True)
|
||||||
|
|
||||||
|
@api.depends("purchase_lines")
|
||||||
|
def _compute_purchase_count(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.purchase_count = len(rec.mapped("purchase_lines.order_id"))
|
||||||
|
|
||||||
|
@api.depends('request_id')
|
||||||
|
def _compute_purchase_request_count(self):
|
||||||
|
for order in self:
|
||||||
|
order.purchase_request_count = len(order.request_id)
|
||||||
|
|
||||||
@api.depends('origin')
|
@api.depends('origin')
|
||||||
def _compute_supply_method(self):
|
def _compute_supply_method(self):
|
||||||
for prl in self:
|
for prl in self:
|
||||||
@@ -98,3 +111,33 @@ class PurchaseRequestLine(models.Model):
|
|||||||
else:
|
else:
|
||||||
record.part_number = record.product_id.part_number
|
record.part_number = record.product_id.part_number
|
||||||
record.part_name = record.product_id.part_name
|
record.part_name = record.product_id.part_name
|
||||||
|
|
||||||
|
def _compute_qty_to_buy(self):
|
||||||
|
for pr in self:
|
||||||
|
qty_to_buy = sum(pr.mapped("product_qty")) - sum(pr.mapped("qty_done")) - sum(pr.mapped("qty_in_progress"))
|
||||||
|
pr.qty_to_buy = qty_to_buy > 0.0
|
||||||
|
pr.pending_qty_to_receive = qty_to_buy
|
||||||
|
|
||||||
|
def action_view_purchase_request(self):
|
||||||
|
action = self.env["ir.actions.actions"]._for_xml_id("purchase_request.purchase_request_form_action")
|
||||||
|
action.update({
|
||||||
|
'res_id': self.request_id.id,
|
||||||
|
'views': [[False, 'form']],
|
||||||
|
})
|
||||||
|
return action
|
||||||
|
|
||||||
|
def action_view_purchase_order(self):
|
||||||
|
action = self.env["ir.actions.actions"]._for_xml_id("purchase.purchase_rfq")
|
||||||
|
lines = self.mapped("purchase_lines.order_id")
|
||||||
|
if len(lines) > 1:
|
||||||
|
action["domain"] = [("id", "in", lines.ids)]
|
||||||
|
elif lines:
|
||||||
|
action["views"] = [
|
||||||
|
(self.env.ref("purchase.purchase_order_form").id, "form")
|
||||||
|
]
|
||||||
|
action["res_id"] = lines.id
|
||||||
|
origin_context = ast.literal_eval(action['context'])
|
||||||
|
if 'search_default_draft' in origin_context:
|
||||||
|
origin_context.pop('search_default_draft')
|
||||||
|
action['context'] = origin_context
|
||||||
|
return action
|
||||||
|
|||||||
35
jikimo_purchase_request/models/stock_picking.py
Normal file
35
jikimo_purchase_request/models/stock_picking.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
from odoo import fields, api, models, _
|
||||||
|
|
||||||
|
|
||||||
|
class StockPicking(models.Model):
|
||||||
|
_inherit = "stock.picking"
|
||||||
|
|
||||||
|
purchase_request_count = fields.Integer('采购订单数量', compute='_compute_purchase_request')
|
||||||
|
|
||||||
|
@api.depends('name')
|
||||||
|
def _compute_purchase_request(self):
|
||||||
|
for record in self:
|
||||||
|
purchase_request_ids = self.env['purchase.request'].search([('origin', '=', record.name)])
|
||||||
|
record.purchase_request_count = len(purchase_request_ids)
|
||||||
|
|
||||||
|
def action_view_purchase_request(self):
|
||||||
|
self.ensure_one()
|
||||||
|
|
||||||
|
purchase_request_ids = self.env['purchase.request'].search([('origin', '=', self.name)])
|
||||||
|
|
||||||
|
action = {
|
||||||
|
'res_model': 'purchase.request',
|
||||||
|
'type': 'ir.actions.act_window',
|
||||||
|
}
|
||||||
|
if len(purchase_request_ids) == 1:
|
||||||
|
action.update({
|
||||||
|
'view_mode': 'form',
|
||||||
|
'res_id': purchase_request_ids[0].id,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
action.update({
|
||||||
|
'name': _("从 %s生成采购请求单", self.name),
|
||||||
|
'domain': [('id', 'in', purchase_request_ids.ids)],
|
||||||
|
'view_mode': 'tree,form',
|
||||||
|
})
|
||||||
|
return action
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
from odoo import api, fields, models
|
from odoo import api, fields, models
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
|
||||||
class StockRule(models.Model):
|
class StockRule(models.Model):
|
||||||
@@ -44,7 +45,40 @@ class StockRule(models.Model):
|
|||||||
purchase_request_line_model.create(request_line_data)
|
purchase_request_line_model.create(request_line_data)
|
||||||
|
|
||||||
def _run_buy(self, procurements):
|
def _run_buy(self, procurements):
|
||||||
res = super(StockRule, self)._run_buy(procurements)
|
# 如果补货组相同,并且产品相同,则合并
|
||||||
|
procurements_dict = defaultdict()
|
||||||
|
for procurement, rule in procurements:
|
||||||
|
if (procurement.product_id.id, procurement.values['group_id'], rule.id) not in procurements_dict:
|
||||||
|
procurements_dict[(procurement.product_id.id, procurement.values['group_id'], rule.id)] = {
|
||||||
|
'product_id': procurement.product_id,
|
||||||
|
'product_qty': procurement.product_qty,
|
||||||
|
'product_uom': procurement.product_uom,
|
||||||
|
'location_id': procurement.location_id,
|
||||||
|
'name': procurement.name,
|
||||||
|
'origin': procurement.origin,
|
||||||
|
'company_id': procurement.company_id,
|
||||||
|
'values': procurement.values,
|
||||||
|
'rule': rule
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
procurements_dict[(procurement.product_id.id, procurement.values['group_id'], rule.id)]['product_qty'] += procurement.product_qty
|
||||||
|
procurements_dict[(procurement.product_id.id, procurement.values['group_id'], rule.id)]['values']['move_dest_ids'] |= procurement.values['move_dest_ids']
|
||||||
|
new_procurements = []
|
||||||
|
for k, p in procurements_dict.items():
|
||||||
|
new_procurements.append((
|
||||||
|
self.env['procurement.group'].Procurement(
|
||||||
|
product_id=p['product_id'],
|
||||||
|
product_qty=p['product_qty'],
|
||||||
|
product_uom=p['product_uom'],
|
||||||
|
location_id=p['location_id'],
|
||||||
|
name=p['name'],
|
||||||
|
origin=p['origin'],
|
||||||
|
company_id=p['company_id'],
|
||||||
|
values=p['values']
|
||||||
|
), p['rule'])
|
||||||
|
)
|
||||||
|
|
||||||
|
res = super(StockRule, self)._run_buy(new_procurements)
|
||||||
# 判断是否根据规则生成新的采购申请单据,如果生成则修改状态为 approved
|
# 判断是否根据规则生成新的采购申请单据,如果生成则修改状态为 approved
|
||||||
origins = list(set([procurement[0].origin for procurement in procurements]))
|
origins = list(set([procurement[0].origin for procurement in procurements]))
|
||||||
for origin in origins:
|
for origin in origins:
|
||||||
|
|||||||
3
jikimo_purchase_request/static/src/change.scss
Normal file
3
jikimo_purchase_request/static/src/change.scss
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
th[data-name=keep_description] {
|
||||||
|
min-width: 220px;
|
||||||
|
}
|
||||||
22
jikimo_purchase_request/views/purchase_request_line_view.xml
Normal file
22
jikimo_purchase_request/views/purchase_request_line_view.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<odoo>
|
||||||
|
<record id="purchase_request_line_form_sf" model="ir.ui.view">
|
||||||
|
<field name="name">purchase.request.line.sf.form</field>
|
||||||
|
<field name="model">purchase.request.line</field>
|
||||||
|
<field name="inherit_id" ref="purchase_request.purchase_request_line_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//h1" position="before">
|
||||||
|
<div class="oe_button_box" name="button_box">
|
||||||
|
<button type="object" name="action_view_purchase_request" class="oe_stat_button"
|
||||||
|
icon="fa-file">
|
||||||
|
<field name="purchase_request_count" widget="statinfo" string="采购申请"/>
|
||||||
|
</button>
|
||||||
|
<button type="object" name="action_view_purchase_order" class="oe_stat_button"
|
||||||
|
attrs="{'invisible': [('purchase_count', '=', 0)]}" icon="fa-shopping-cart">
|
||||||
|
<field name="purchase_count" widget="statinfo" string="采购订单"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</xpath>
|
||||||
|
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
21
jikimo_purchase_request/views/stock_picking_views.xml
Normal file
21
jikimo_purchase_request/views/stock_picking_views.xml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<record id="stock_pikcing_inherited_form_jikimo_purchase_request" model="ir.ui.view">
|
||||||
|
<field name="name">stock.pikcing.inherited.form.jikimo.purchase.request</field>
|
||||||
|
<field name="model">stock.picking</field>
|
||||||
|
<field name="inherit_id" ref="stock.view_picking_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//div[@name='button_box']/button" position="before">
|
||||||
|
<button class="oe_stat_button" name="action_view_purchase_request" type="object" icon="fa-credit-card"
|
||||||
|
attrs="{'invisible': [('purchase_request_count', '=', 0)]}">
|
||||||
|
<div class="o_field_widget o_stat_info">
|
||||||
|
<span class="o_stat_value">
|
||||||
|
<field name="purchase_request_count"/>
|
||||||
|
</span>
|
||||||
|
<span class="o_stat_text">采购申请</span>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
@@ -104,9 +104,26 @@ class PurchaseRequestLineMakePurchaseOrder(models.TransientModel):
|
|||||||
# 去掉合并必须同一采购组的限制
|
# 去掉合并必须同一采购组的限制
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_items(self, request_line_ids):
|
||||||
|
request_line_obj = self.env["purchase.request.line"]
|
||||||
|
items = []
|
||||||
|
request_lines = request_line_obj.browse(request_line_ids).filtered(lambda line: line.pending_qty_to_receive > 0)
|
||||||
|
self._check_valid_request_line(request_line_ids)
|
||||||
|
self.check_group(request_lines)
|
||||||
|
for line in request_lines:
|
||||||
|
items.append([0, 0, self._prepare_item(line)])
|
||||||
|
return items
|
||||||
|
|
||||||
|
|
||||||
class PurchaseRequestLineMakePurchaseOrderItem(models.TransientModel):
|
class PurchaseRequestLineMakePurchaseOrderItem(models.TransientModel):
|
||||||
_inherit = "purchase.request.line.make.purchase.order.item"
|
_inherit = "purchase.request.line.make.purchase.order.item"
|
||||||
|
|
||||||
supply_method = fields.Selection(related='line_id.supply_method', string='供货方式')
|
supply_method = fields.Selection(related='line_id.supply_method', string='供货方式')
|
||||||
|
|
||||||
|
wiz_id = fields.Many2one(
|
||||||
|
comodel_name="purchase.request.line.make.purchase.order",
|
||||||
|
string="Wizard",
|
||||||
|
required=False,
|
||||||
|
ondelete="cascade",
|
||||||
|
readonly=True,
|
||||||
|
)
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ class QualityCheck(models.Model):
|
|||||||
# # 出厂检验报告编号
|
# # 出厂检验报告编号
|
||||||
# report_number = fields.Char('出厂检验报告编号', compute='_compute_report_number', readonly=True)
|
# report_number = fields.Char('出厂检验报告编号', compute='_compute_report_number', readonly=True)
|
||||||
# 总数量,值为调拨单_产品明细_数量
|
# 总数量,值为调拨单_产品明细_数量
|
||||||
total_qty = fields.Char('总数量', compute='_compute_total_qty')
|
total_qty = fields.Char('总数量', compute='_compute_total_qty', store=True)
|
||||||
|
|
||||||
column_nums = fields.Integer('测量值列数', default=1)
|
column_nums = fields.Integer('测量值列数', default=1)
|
||||||
|
|
||||||
@@ -153,9 +153,9 @@ class QualityCheck(models.Model):
|
|||||||
for move in record.picking_id.move_ids_without_package:
|
for move in record.picking_id.move_ids_without_package:
|
||||||
if move.product_id == record.product_id:
|
if move.product_id == record.product_id:
|
||||||
total_qty = int(move.product_uom_qty)
|
total_qty = int(move.product_uom_qty)
|
||||||
record.total_qty = total_qty if total_qty > 0 else ''
|
record.total_qty = total_qty if total_qty > 0 else 0
|
||||||
else:
|
else:
|
||||||
record.total_qty = ''
|
record.total_qty = 0
|
||||||
|
|
||||||
# 检验数
|
# 检验数
|
||||||
check_qty = fields.Integer('检验数', default=lambda self: self._get_default_check_qty())
|
check_qty = fields.Integer('检验数', default=lambda self: self._get_default_check_qty())
|
||||||
@@ -735,8 +735,9 @@ class QualityCheck(models.Model):
|
|||||||
def _compute_qty_to_test(self):
|
def _compute_qty_to_test(self):
|
||||||
for qc in self:
|
for qc in self:
|
||||||
if qc.is_lot_tested_fractionally:
|
if qc.is_lot_tested_fractionally:
|
||||||
|
rounding = qc.product_id.uom_id.rounding if qc.product_id.uom_id else 0.01
|
||||||
qc.qty_to_test = float_round(qc.qty_line * qc.testing_percentage_within_lot / 100,
|
qc.qty_to_test = float_round(qc.qty_line * qc.testing_percentage_within_lot / 100,
|
||||||
precision_rounding=self.product_id.uom_id.rounding, rounding_method="UP")
|
precision_rounding=rounding, rounding_method="UP")
|
||||||
else:
|
else:
|
||||||
qc.qty_to_test = qc.qty_line
|
qc.qty_to_test = qc.qty_line
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ class QualityCheckWizard(models.TransientModel):
|
|||||||
lot_name = fields.Char(related='current_check_id.lot_name')
|
lot_name = fields.Char(related='current_check_id.lot_name')
|
||||||
lot_line_id = fields.Many2one(related='current_check_id.lot_line_id')
|
lot_line_id = fields.Many2one(related='current_check_id.lot_line_id')
|
||||||
qty_line = fields.Float(related='current_check_id.qty_line')
|
qty_line = fields.Float(related='current_check_id.qty_line')
|
||||||
qty_to_test = fields.Float(related='current_check_id.qty_to_test')
|
qty_to_test = fields.Float(related='current_check_id.qty_to_test', string='待检')
|
||||||
qty_tested = fields.Float(related='current_check_id.qty_tested', readonly=False)
|
qty_tested = fields.Float(related='current_check_id.qty_tested', string='已检', readonly=False)
|
||||||
measure = fields.Float(related='current_check_id.measure', readonly=False)
|
measure = fields.Float(related='current_check_id.measure', readonly=False)
|
||||||
measure_on = fields.Selection(related='current_check_id.measure_on')
|
measure_on = fields.Selection(related='current_check_id.measure_on')
|
||||||
quality_state = fields.Selection(related='current_check_id.quality_state')
|
quality_state = fields.Selection(related='current_check_id.quality_state')
|
||||||
|
|||||||
@@ -1357,8 +1357,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
# 判断是否有坯料的序列号信息
|
# 判断是否有坯料的序列号信息
|
||||||
boolean = False
|
boolean = False
|
||||||
if self.production_id.move_raw_ids:
|
if self.production_id.move_raw_ids:
|
||||||
if self.production_id.move_raw_ids[0].product_id.categ_type == '坯料':
|
if self.production_id.move_raw_ids[0].product_id.categ_type == '坯料' and self.production_id.move_raw_ids[0].product_id.tracking == 'serial':
|
||||||
if self.production_id.move_raw_ids[0].move_line_ids:
|
|
||||||
if self.production_id.move_raw_ids[0].move_line_ids:
|
if self.production_id.move_raw_ids[0].move_line_ids:
|
||||||
if self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name:
|
if self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name:
|
||||||
boolean = True
|
boolean = True
|
||||||
|
|||||||
@@ -1030,6 +1030,7 @@ class ResProductMo(models.Model):
|
|||||||
'single_manufacturing': product_id.single_manufacturing,
|
'single_manufacturing': product_id.single_manufacturing,
|
||||||
'is_bfm': True,
|
'is_bfm': True,
|
||||||
'active': True,
|
'active': True,
|
||||||
|
'tracking': finish_product.tracking, # 坯料的跟踪方式跟随成品
|
||||||
}
|
}
|
||||||
# 外协和采购生成的坯料需要根据材料型号绑定供应商
|
# 外协和采购生成的坯料需要根据材料型号绑定供应商
|
||||||
if route_type == 'subcontract' or route_type == 'purchase':
|
if route_type == 'subcontract' or route_type == 'purchase':
|
||||||
|
|||||||
@@ -96,8 +96,12 @@ class PurchaseOrder(models.Model):
|
|||||||
# 'origin': record.name + ',' + replenish.origin,
|
# 'origin': record.name + ',' + replenish.origin,
|
||||||
# })
|
# })
|
||||||
# replenish.action_replenish()
|
# replenish.action_replenish()
|
||||||
|
res = super(PurchaseOrder, self).button_confirm()
|
||||||
return super(PurchaseOrder, self).button_confirm()
|
for line in self.order_line:
|
||||||
|
# 将产品不追踪序列号的行项目设置qty_done
|
||||||
|
if line.move_ids and line.move_ids[0].product_id.tracking == 'none':
|
||||||
|
line.move_ids[0].quantity_done = line.move_ids[0].product_qty
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
origin_sale_id = fields.Many2one('sale.order', string='销售订单号', store=True, compute='_compute_origin_sale_id')
|
origin_sale_id = fields.Many2one('sale.order', string='销售订单号', store=True, compute='_compute_origin_sale_id')
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ class SaleOrder(models.Model):
|
|||||||
line.product_id.product_tmpl_id.copy_template(product_template_id)
|
line.product_id.product_tmpl_id.copy_template(product_template_id)
|
||||||
# 将模板上的single_manufacturing属性复制到成品上
|
# 将模板上的single_manufacturing属性复制到成品上
|
||||||
line.product_id.single_manufacturing = product_template_id.single_manufacturing
|
line.product_id.single_manufacturing = product_template_id.single_manufacturing
|
||||||
|
line.product_id.tracking = product_template_id.tracking
|
||||||
|
|
||||||
order_id = self
|
order_id = self
|
||||||
product = line.product_id
|
product = line.product_id
|
||||||
|
|||||||
@@ -675,6 +675,7 @@ class StockPicking(models.Model):
|
|||||||
|
|
||||||
# 创建 外协出库入单
|
# 创建 外协出库入单
|
||||||
def create_outcontract_picking(self, workorders, item, sorted_workorders):
|
def create_outcontract_picking(self, workorders, item, sorted_workorders):
|
||||||
|
production = workorders[0].production_id
|
||||||
for workorder in workorders:
|
for workorder in workorders:
|
||||||
if workorder.move_subcontract_workorder_ids:
|
if workorder.move_subcontract_workorder_ids:
|
||||||
workorder.move_subcontract_workorder_ids.write({'state': 'cancel'})
|
workorder.move_subcontract_workorder_ids.write({'state': 'cancel'})
|
||||||
@@ -706,7 +707,7 @@ class StockPicking(models.Model):
|
|||||||
})
|
})
|
||||||
moves_in = self.env['stock.move'].sudo().with_context(context).create(
|
moves_in = self.env['stock.move'].sudo().with_context(context).create(
|
||||||
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_in,
|
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_in,
|
||||||
procurement_group_id.id, move_dest_id))
|
procurement_group_id.id, move_dest_id, production.product_uom_qty))
|
||||||
picking_in = self.create(
|
picking_in = self.create(
|
||||||
moves_in._get_new_picking_values_Res(item, workorder, 'WH/OCIN/'))
|
moves_in._get_new_picking_values_Res(item, workorder, 'WH/OCIN/'))
|
||||||
# pick_ids.append(picking_in.id)
|
# pick_ids.append(picking_in.id)
|
||||||
@@ -716,7 +717,7 @@ class StockPicking(models.Model):
|
|||||||
# self.env.context.get('default_production_id')
|
# self.env.context.get('default_production_id')
|
||||||
moves_out = self.env['stock.move'].sudo().with_context(context).create(
|
moves_out = self.env['stock.move'].sudo().with_context(context).create(
|
||||||
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_out,
|
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_out,
|
||||||
procurement_group_id.id, moves_in.id))
|
procurement_group_id.id, moves_in.id, production.product_uom_qty))
|
||||||
workorder.write({'move_subcontract_workorder_ids': [(6, 0, [moves_in.id, moves_out.id])]})
|
workorder.write({'move_subcontract_workorder_ids': [(6, 0, [moves_in.id, moves_out.id])]})
|
||||||
picking_out = self.create(
|
picking_out = self.create(
|
||||||
moves_out._get_new_picking_values_Res(item, workorder, 'WH/OCOUT/'))
|
moves_out._get_new_picking_values_Res(item, workorder, 'WH/OCOUT/'))
|
||||||
@@ -848,7 +849,7 @@ class ReStockMove(models.Model):
|
|||||||
traceback_error = traceback.format_exc()
|
traceback_error = traceback.format_exc()
|
||||||
logging.error("零件图号 零件名称获取失败:%s" % traceback_error)
|
logging.error("零件图号 零件名称获取失败:%s" % traceback_error)
|
||||||
|
|
||||||
def _get_stock_move_values_Res(self, item, picking_type_id, group_id, move_dest_ids=False):
|
def _get_stock_move_values_Res(self, item, picking_type_id, group_id, move_dest_ids=False, product_uom_qty=1.0):
|
||||||
route_id = self.env.ref('sf_manufacturing.route_surface_technology_outsourcing').id
|
route_id = self.env.ref('sf_manufacturing.route_surface_technology_outsourcing').id
|
||||||
stock_rule = self.env['stock.rule'].sudo().search(
|
stock_rule = self.env['stock.rule'].sudo().search(
|
||||||
[('route_id', '=', route_id), ('picking_type_id', '=', picking_type_id)])
|
[('route_id', '=', route_id), ('picking_type_id', '=', picking_type_id)])
|
||||||
@@ -857,7 +858,7 @@ class ReStockMove(models.Model):
|
|||||||
'company_id': item.company_id.id,
|
'company_id': item.company_id.id,
|
||||||
'product_id': item.bom_id.bom_line_ids.product_id.id,
|
'product_id': item.bom_id.bom_line_ids.product_id.id,
|
||||||
'product_uom': item.bom_id.bom_line_ids.product_uom_id.id,
|
'product_uom': item.bom_id.bom_line_ids.product_uom_id.id,
|
||||||
'product_uom_qty': 1.0,
|
'product_uom_qty': product_uom_qty,
|
||||||
'location_id': stock_rule.location_src_id.id,
|
'location_id': stock_rule.location_src_id.id,
|
||||||
'location_dest_id': stock_rule.location_dest_id.id,
|
'location_dest_id': stock_rule.location_dest_id.id,
|
||||||
'origin': item.name,
|
'origin': item.name,
|
||||||
@@ -902,7 +903,7 @@ class ReStockMove(models.Model):
|
|||||||
'location_id': self.picking_id.location_id.id,
|
'location_id': self.picking_id.location_id.id,
|
||||||
'location_dest_id': self.picking_id.location_dest_id.id,
|
'location_dest_id': self.picking_id.location_dest_id.id,
|
||||||
'picking_id': self.picking_id.id,
|
'picking_id': self.picking_id.id,
|
||||||
'reserved_uom_qty': 1.0,
|
'reserved_uom_qty': self.product_uom_qty,
|
||||||
'lot_id': production_id.move_line_raw_ids.lot_id.id,
|
'lot_id': production_id.move_line_raw_ids.lot_id.id,
|
||||||
'company_id': self.env.company.id,
|
'company_id': self.env.company.id,
|
||||||
# 'workorder_id': '' if not sorted_workorders else sorted_workorders.id,
|
# 'workorder_id': '' if not sorted_workorders else sorted_workorders.id,
|
||||||
|
|||||||
@@ -4,30 +4,32 @@
|
|||||||
name="Manufacturing"
|
name="Manufacturing"
|
||||||
groups="mrp.group_mrp_user,mrp.group_mrp_manager,sf_base.group_sf_mrp_user,sf_base.group_sf_mrp_manager"
|
groups="mrp.group_mrp_user,mrp.group_mrp_manager,sf_base.group_sf_mrp_user,sf_base.group_sf_mrp_manager"
|
||||||
web_icon="mrp,static/description/icon.svg"
|
web_icon="mrp,static/description/icon.svg"
|
||||||
sequence="145">
|
sequence="145"/>
|
||||||
|
|
||||||
<menuitem id="mrp.menu_mrp_manufacturing"
|
<menuitem id="mrp.menu_mrp_manufacturing"
|
||||||
name="Operations"
|
name="Operations"
|
||||||
|
parent="mrp.menu_mrp_root"
|
||||||
sequence="10"/>
|
sequence="10"/>
|
||||||
|
|
||||||
<menuitem id="mrp.mrp_planning_menu_root"
|
<menuitem id="mrp.mrp_planning_menu_root"
|
||||||
name="Planning"
|
name="Planning"
|
||||||
|
parent="mrp.menu_mrp_root"
|
||||||
sequence="15"/>
|
sequence="15"/>
|
||||||
|
|
||||||
<menuitem id="mrp.enu_mrp_bom"
|
<menuitem id="mrp.menu_mrp_bom"
|
||||||
name="Products"
|
name="Products"
|
||||||
|
parent="mrp.menu_mrp_root"
|
||||||
sequence="20"/>
|
sequence="20"/>
|
||||||
|
|
||||||
<menuitem id="mrp.menu_mrp_reporting"
|
<menuitem id="mrp.menu_mrp_reporting"
|
||||||
name="Reporting"
|
name="Reporting"
|
||||||
|
parent="mrp.menu_mrp_root"
|
||||||
sequence="25"/>
|
sequence="25"/>
|
||||||
|
|
||||||
<menuitem id="mrp.menu_mrp_configuration"
|
<menuitem id="mrp.menu_mrp_configuration"
|
||||||
name="Configuration"
|
name="Configuration"
|
||||||
|
parent="mrp.menu_mrp_root"
|
||||||
groups="mrp.group_mrp_manager,sf_base.group_sf_mrp_manager"
|
groups="mrp.group_mrp_manager,sf_base.group_sf_mrp_manager"
|
||||||
sequence="100"/>
|
sequence="100"/>
|
||||||
|
|
||||||
</menuitem>
|
|
||||||
|
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -268,6 +268,8 @@ class ReworkWizard(models.TransientModel):
|
|||||||
'cmm_ids': new_cnc_workorder.cmm_ids.sudo()._json_cmm_program(
|
'cmm_ids': new_cnc_workorder.cmm_ids.sudo()._json_cmm_program(
|
||||||
cnc_work.processing_panel, ret),
|
cnc_work.processing_panel, ret),
|
||||||
'cnc_worksheet': old_cnc_rework.cnc_worksheet})
|
'cnc_worksheet': old_cnc_rework.cnc_worksheet})
|
||||||
|
# 复制装夹图纸
|
||||||
|
new_cnc_workorder.processing_drawing = old_cnc_rework.processing_drawing
|
||||||
# ========== 处理装夹预调 【装夹图纸】 数据 ================
|
# ========== 处理装夹预调 【装夹图纸】 数据 ================
|
||||||
for new_pre_work in new_pre_workorder_ids:
|
for new_pre_work in new_pre_workorder_ids:
|
||||||
pre_rework = max(self.production_id.workorder_ids.filtered(
|
pre_rework = max(self.production_id.workorder_ids.filtered(
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from odoo import fields, models, api
|
|||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from odoo.addons.sf_base.commons.common import Common
|
from odoo.addons.sf_base.commons.common import Common
|
||||||
|
from odoo.tools import float_round
|
||||||
|
|
||||||
|
|
||||||
class QualityCheck(models.Model):
|
class QualityCheck(models.Model):
|
||||||
@@ -132,3 +133,71 @@ class QualityCheck(models.Model):
|
|||||||
return "零件特采发送成功"
|
return "零件特采发送成功"
|
||||||
else:
|
else:
|
||||||
raise ValidationError("零件特采发送失败")
|
raise ValidationError("零件特采发送失败")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@api.model_create_multi
|
||||||
|
def create(self, vals_list):
|
||||||
|
for val in vals_list:
|
||||||
|
if 'point_id' in val and 'measure_on' not in val:
|
||||||
|
# 如果没有控制方式字段,则从检查点读取质量方式
|
||||||
|
point_id = self.env['quality.point'].browse(val['point_id'])
|
||||||
|
val.update({'measure_on': point_id.measure_on})
|
||||||
|
return super(QualityCheck, self).create(vals_list)
|
||||||
|
|
||||||
|
|
||||||
|
@api.depends('total_qty','testing_percentage_within_lot', 'is_lot_tested_fractionally')
|
||||||
|
def _compute_workorder_qty_to_test(self):
|
||||||
|
for qc in self:
|
||||||
|
if qc.is_lot_tested_fractionally:
|
||||||
|
rounding = qc.product_id.uom_id.rounding if qc.product_id.uom_id else 0.01
|
||||||
|
qc.workorder_qty_to_test = float_round(float(qc.total_qty) * qc.testing_percentage_within_lot / 100,
|
||||||
|
precision_rounding=rounding, rounding_method="UP")
|
||||||
|
else:
|
||||||
|
qc.workorder_qty_to_test = qc.total_qty
|
||||||
|
|
||||||
|
@api.depends('picking_id', 'workorder_id')
|
||||||
|
def _compute_total_qty(self):
|
||||||
|
super(QualityCheck, self)._compute_total_qty()
|
||||||
|
for qc in self:
|
||||||
|
if not qc.picking_id and qc.workorder_id:
|
||||||
|
qc.total_qty = qc.workorder_id.production_id.product_qty
|
||||||
|
|
||||||
|
@api.depends('workorder_qty_to_test')
|
||||||
|
def _compute_workorder_qty_tested(self):
|
||||||
|
for qc in self:
|
||||||
|
qc.workorder_qty_tested = qc.workorder_qty_to_test
|
||||||
|
|
||||||
|
|
||||||
|
workorder_qty_to_test = fields.Float('应检', compute='_compute_workorder_qty_to_test', store=True)
|
||||||
|
workorder_qty_tested = fields.Float('已检', compute='_compute_workorder_qty_tested', store=True)
|
||||||
|
workorder_qty_test_failed = fields.Float('不合格数')
|
||||||
|
|
||||||
|
|
||||||
|
@api.onchange('total_qty', 'workorder_qty_test_failed', 'workorder_qty_to_test', 'workorder_qty_tested')
|
||||||
|
def _onchage_qty(self):
|
||||||
|
for record in self:
|
||||||
|
if record.total_qty and record.workorder_qty_to_test and record.workorder_qty_to_test > float(record.total_qty):
|
||||||
|
record.workorder_qty_to_test = float(record.total_qty)
|
||||||
|
return {
|
||||||
|
'warning': {
|
||||||
|
'title': '警告',
|
||||||
|
'message': '待检数量不能超过总数量'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if record.workorder_qty_to_test and record.workorder_qty_tested and record.workorder_qty_tested > record.workorder_qty_to_test:
|
||||||
|
record.workorder_qty_tested = record.workorder_qty_to_test
|
||||||
|
return {
|
||||||
|
'warning': {
|
||||||
|
'title': '警告',
|
||||||
|
'message': '已检数量不能超过待检数量'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if record.workorder_qty_tested and record.workorder_qty_test_failed and record.workorder_qty_test_failed > record.workorder_qty_tested:
|
||||||
|
record.workorder_qty_test_failed = record.workorder_qty_tested
|
||||||
|
return {
|
||||||
|
'warning': {
|
||||||
|
'title': '警告',
|
||||||
|
'message': '不合格数量不能超过已检数量'
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -88,6 +88,42 @@
|
|||||||
<button name="do_cancel_publish" string="取消发布" type="object" class="btn-primary" confirm="确定取消发布吗?" attrs="{'invisible': ['|',('is_out_check', '=', False), ('publish_status', '!=', 'published')]}"/>
|
<button name="do_cancel_publish" string="取消发布" type="object" class="btn-primary" confirm="确定取消发布吗?" attrs="{'invisible': ['|',('is_out_check', '=', False), ('publish_status', '!=', 'published')]}"/>
|
||||||
<button name="do_re_publish" string="重新发布" type="object" class="btn-primary" attrs="{'invisible': ['|', ('is_out_check', '=', False), ('publish_status', '!=', 'canceled')]}"/>
|
<button name="do_re_publish" string="重新发布" type="object" class="btn-primary" attrs="{'invisible': ['|', ('is_out_check', '=', False), ('publish_status', '!=', 'canceled')]}"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='total_qty']" position="attributes">
|
||||||
|
<attribute name="attrs">{
|
||||||
|
'invisible': ['&', '|', ('measure_on', '!=', 'product'), ('is_out_check', '=', False), '|', ('measure_on', '!=', 'move_line'), ('workorder_id', '=', False)],
|
||||||
|
'readonly': ['|', ('measure_on', '!=', 'move_line'), ('workorder_id', '=', False)],
|
||||||
|
'on_change': ['|', ('measure_on', '!=', 'move_line'), ('workorder_id', '=', False)]
|
||||||
|
}</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='total_qty']" position="after">
|
||||||
|
<label for="workorder_qty_to_test"
|
||||||
|
attrs="{'invisible': ['|', '&', ('measure_on', '!=', 'move_line'), ('workorder_id', '=', False), ('is_lot_tested_fractionally', '=', False)]}"/>
|
||||||
|
<div class="o_row"
|
||||||
|
attrs="{'invisible': ['|', '&', ('measure_on', '!=', 'move_line'), ('workorder_id', '=', False), ('is_lot_tested_fractionally', '=', False)]}">
|
||||||
|
<field name="workorder_qty_to_test" attrs="{'readonly': 0, 'on_chnage': 1}"/>
|
||||||
|
<field name="uom_id"/>
|
||||||
|
</div>
|
||||||
|
<label for="workorder_qty_tested"
|
||||||
|
attrs="{'invisible': ['|', '&', ('measure_on', '!=', 'move_line'), ('workorder_id', '=', False), ('is_lot_tested_fractionally', '=', False)]}"/>
|
||||||
|
<div class="o_row"
|
||||||
|
attrs="{'invisible': ['|', '&', ('measure_on', '!=', 'move_line'), ('workorder_id', '=', False), ('is_lot_tested_fractionally', '=', False)]}">
|
||||||
|
<field name="workorder_qty_tested" attrs="{'readonly': [('quality_state', '!=', 'none')], 'on_chnage': 1}"/>
|
||||||
|
<field name="uom_id"/>
|
||||||
|
</div>
|
||||||
|
<label for="workorder_qty_test_failed"
|
||||||
|
attrs="{'invisible': ['|', '&', ('measure_on', '!=', 'move_line'), ('workorder_id', '=', False), ('is_lot_tested_fractionally', '=', False)]}"/>
|
||||||
|
<div class="o_row"
|
||||||
|
attrs="{'invisible': ['|', '&', ('measure_on', '!=', 'move_line'), ('workorder_id', '=', False), ('is_lot_tested_fractionally', '=', False)]}">
|
||||||
|
<field name="workorder_qty_test_failed" attrs="{'readonly': [('quality_state', '!=', 'none')], 'on_chnage': 1}"/>
|
||||||
|
<field name="uom_id"/>
|
||||||
|
</div>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//label[@for='qty_tested']" position="attributes">
|
||||||
|
<attribute name="attrs">{'invisible': ['|', '|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '=', False), '&', ('measure_on', '=', 'move_line'), ('workorder_id', '!=', False)]}</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//div[@class='o_row'][.//field[@name='qty_tested']]" position="attributes">
|
||||||
|
<attribute name="attrs">{'invisible': ['|', '|', ('measure_on', '!=', 'move_line'), ('is_lot_tested_fractionally', '=', False), '&', ('measure_on', '=', 'move_line'), ('workorder_id', '!=', False)]}</attribute>
|
||||||
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ class RePurchaseOrder(models.Model):
|
|||||||
('detailed_type', '=', 'service')])
|
('detailed_type', '=', 'service')])
|
||||||
server_product_process.append((0, 0, {
|
server_product_process.append((0, 0, {
|
||||||
'product_id': server_template.product_variant_id.id,
|
'product_id': server_template.product_variant_id.id,
|
||||||
'product_qty': 1,
|
'product_qty': production.product_uom_qty,
|
||||||
'product_uom': server_template.uom_id.id,
|
'product_uom': server_template.uom_id.id,
|
||||||
'related_product': production.product_id.id,
|
'related_product': production.product_id.id,
|
||||||
'manual_part_number': pp.part_number,
|
'manual_part_number': pp.part_number,
|
||||||
|
|||||||
@@ -812,40 +812,49 @@ class SfStockMoveLine(models.Model):
|
|||||||
# # 从目标stock.move对象获取目标stock.picking对象
|
# # 从目标stock.move对象获取目标stock.picking对象
|
||||||
# dest_picking = dest_move.picking_id if dest_move else False
|
# dest_picking = dest_move.picking_id if dest_move else False
|
||||||
# # 现在,dest_picking就是current_picking的下一步
|
# # 现在,dest_picking就是current_picking的下一步
|
||||||
|
# 添加所有需要的依赖字段
|
||||||
@api.depends('location_id')
|
@api.depends('location_id')
|
||||||
def _compute_current_location_id(self):
|
def _compute_current_location_id(self):
|
||||||
|
# 批量获取所有相关记录的picking
|
||||||
|
pickings = self.mapped('picking_id')
|
||||||
|
|
||||||
|
# 构建源picking的移库行与目标位置的映射
|
||||||
|
origin_location_map = {}
|
||||||
|
for picking in pickings:
|
||||||
|
# 获取源picking
|
||||||
|
origin_move = picking.move_ids[:1].move_orig_ids[:1]
|
||||||
|
if not origin_move:
|
||||||
|
continue
|
||||||
|
|
||||||
|
origin_picking = origin_move.picking_id
|
||||||
|
if not origin_picking:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 为每个picking构建lot_id到location的映射
|
||||||
|
origin_location_map[picking.id] = {
|
||||||
|
move_line.lot_id.id: move_line.destination_location_id
|
||||||
|
for move_line in origin_picking.move_line_ids.filtered(
|
||||||
|
lambda ml: ml.destination_location_id and ml.lot_id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# 批量更新current_location_id
|
||||||
for record in self:
|
for record in self:
|
||||||
# 使用record代替self来引用当前遍历到的记录
|
current_picking = record.picking_id
|
||||||
logging.info('record.picking_id.name: %s' % record.picking_id.name)
|
if not current_picking:
|
||||||
logging.info('record.env: %s' % record.env['stock.picking'].search([('name', '=', record.picking_id.name)]))
|
record.current_location_id = False
|
||||||
|
continue
|
||||||
|
|
||||||
# 获取当前的stock.picking对象
|
# 获取当前picking对应的lot_location映射
|
||||||
current_picking = record.env['stock.picking'].search([('name', '=', record.picking_id.name)], limit=1)
|
lot_dest_map = origin_location_map.get(current_picking.id, {})
|
||||||
|
|
||||||
# 获取当前picking的第一个stock.move对象
|
# 查找匹配的lot_id
|
||||||
current_move = current_picking.move_ids[0] if current_picking.move_ids else False
|
for move_line in current_picking.move_line_ids:
|
||||||
|
if move_line.lot_id and move_line.lot_id.id in lot_dest_map:
|
||||||
# 如果存在相关的stock.move对象
|
record.current_location_id = lot_dest_map[move_line.lot_id.id]
|
||||||
if current_move:
|
break
|
||||||
# 获取源stock.move对象
|
else:
|
||||||
origin_move = current_move.move_orig_ids[0] if current_move.move_orig_ids else False
|
record.current_location_id = False
|
||||||
|
|
||||||
# 从源stock.move对象获取源stock.picking对象
|
|
||||||
origin_picking = origin_move.picking_id if origin_move else False
|
|
||||||
|
|
||||||
# 如果前一个调拨单有目标货位
|
|
||||||
if origin_picking:
|
|
||||||
for i in current_picking.move_line_ids:
|
|
||||||
for j in origin_picking.move_line_ids:
|
|
||||||
if j.destination_location_id and i.lot_id == j.lot_id:
|
|
||||||
# 更新当前记录的current_location_id字段
|
|
||||||
record.current_location_id = j.destination_location_id
|
|
||||||
# # 获取目标stock.move对象
|
|
||||||
# dest_move = current_move.move_dest_ids[0] if current_move.move_dest_ids else False
|
|
||||||
#
|
|
||||||
# # 从目标stock.move对象获取目标stock.picking对象
|
|
||||||
# dest_picking = dest_move.picking_id if dest_move else False
|
|
||||||
# # 现在,dest_picking就是current_picking的下一步
|
|
||||||
|
|
||||||
# 是一张单据一张单据往下走的,所以这里的目标货位是上一张单据的当前货位,且这样去计算是可以的。
|
# 是一张单据一张单据往下走的,所以这里的目标货位是上一张单据的当前货位,且这样去计算是可以的。
|
||||||
@api.depends('location_dest_id')
|
@api.depends('location_dest_id')
|
||||||
|
|||||||
Reference in New Issue
Block a user