Merge branch 'feature/commercially_launched' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/commercially_launched
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import re
|
||||
import ast
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
@@ -20,6 +21,13 @@ class PurchaseRequest(models.Model):
|
||||
if pr.state != 'draft' and pr.rule_new_add:
|
||||
pr.rule_new_add = False
|
||||
|
||||
def action_view_purchase_order(self):
|
||||
action = super(PurchaseRequest, self).action_view_purchase_order()
|
||||
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
|
||||
|
||||
class PurchaseRequestLine(models.Model):
|
||||
_inherit = 'purchase.request.line'
|
||||
|
||||
3
jikimo_purchase_request_tier_validation/__init__.py
Normal file
3
jikimo_purchase_request_tier_validation/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import models
|
||||
28
jikimo_purchase_request_tier_validation/__manifest__.py
Normal file
28
jikimo_purchase_request_tier_validation/__manifest__.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': "机企猫 采购审批流程",
|
||||
|
||||
'summary': """
|
||||
Short (1 phrase/line) summary of the module's purpose, used as
|
||||
subtitle on modules listing or apps.openerp.com""",
|
||||
|
||||
'description': """
|
||||
Long description of module's purpose
|
||||
""",
|
||||
|
||||
'author': "My Company",
|
||||
'website': "https://www.yourcompany.com",
|
||||
|
||||
# Categories can be used to filter modules in modules listing
|
||||
# Check https://github.com/odoo/odoo/blob/16.0/odoo/addons/base/data/ir_module_category_data.xml
|
||||
# for the full list
|
||||
'category': 'Uncategorized',
|
||||
'version': '0.1',
|
||||
|
||||
# any module necessary for this one to work correctly
|
||||
'depends': ['purchase_request_tier_validation'],
|
||||
|
||||
# always loaded
|
||||
'data': [
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import models
|
||||
24
jikimo_purchase_request_tier_validation/models/models.py
Normal file
24
jikimo_purchase_request_tier_validation/models/models.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PurchaseRequest(models.Model):
|
||||
_inherit = 'purchase.request'
|
||||
|
||||
|
||||
def _validate_tier(self, tiers=False):
|
||||
res = super(PurchaseRequest, self)._validate_tier(tiers)
|
||||
|
||||
# 检查是否所有审批都已通过
|
||||
all_approved = all(
|
||||
tier_review.status == 'approved'
|
||||
for tier_review in self.review_ids
|
||||
)
|
||||
|
||||
if self.review_ids and all_approved: # 确保有审批记录
|
||||
self.state = 'approved'
|
||||
|
||||
return res
|
||||
@@ -1,14 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': "机企猫 采购审批流程",
|
||||
'name': "机企猫 采购申请审批流程",
|
||||
|
||||
'summary': """
|
||||
Short (1 phrase/line) summary of the module's purpose, used as
|
||||
subtitle on modules listing or apps.openerp.com""",
|
||||
采购申请审批流程""",
|
||||
|
||||
'description': """
|
||||
Long description of module's purpose
|
||||
""",
|
||||
采购申请审批流程""",
|
||||
|
||||
'author': "My Company",
|
||||
'website': "https://www.yourcompany.com",
|
||||
|
||||
@@ -421,3 +421,4 @@ class EmbryoRedundancy(models.Model):
|
||||
width = fields.Float('宽度(mm)', required=True)
|
||||
height = fields.Float('高度(mm)', required=True)
|
||||
active = fields.Boolean('有效', default=True)
|
||||
remark = fields.Char('描述')
|
||||
|
||||
@@ -645,6 +645,7 @@
|
||||
<field name="long"/>
|
||||
<field name="width"/>
|
||||
<field name="height"/>
|
||||
<field name="remark"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -5,6 +5,8 @@ import logging
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import traceback
|
||||
|
||||
import requests
|
||||
from itertools import groupby
|
||||
from collections import defaultdict, namedtuple
|
||||
@@ -257,14 +259,46 @@ class MrpProduction(models.Model):
|
||||
], string='工序状态', default='待装夹')
|
||||
|
||||
# 零件图号
|
||||
part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True)
|
||||
part_number = fields.Char('零件图号', compute='_compute_part_info', store=True)
|
||||
|
||||
# 上传零件图纸
|
||||
part_drawing = fields.Binary('零件图纸', related='product_id.machining_drawings', readonly=True)
|
||||
|
||||
quality_standard = fields.Binary('质检标准', related='product_id.quality_standard', readonly=True)
|
||||
|
||||
part_name = fields.Char(string='零件名称', related='product_id.part_name', readonly=True)
|
||||
part_name = fields.Char(string='零件名称', compute='_compute_part_info', store=True)
|
||||
@api.depends('product_id')
|
||||
def _compute_part_info(self):
|
||||
try:
|
||||
for production_id in self:
|
||||
if production_id.product_id.categ_id.type == '成品':
|
||||
production_id.part_number = production_id.product_id.part_number
|
||||
production_id.part_name = production_id.product_id.part_name
|
||||
elif production_id.product_id.categ_id.type == '坯料':
|
||||
product_name = ''
|
||||
match = re.search(r'(S\d{5}-\d)', production_id.product_id.name)
|
||||
# 如果匹配成功,提取结果
|
||||
if match:
|
||||
product_name = match.group(0)
|
||||
if production_id.sale_order_id:
|
||||
sale_order = production_id.sale_order_id
|
||||
else:
|
||||
sale_order_name = ''
|
||||
match = re.search(r'(S\d+)', production_id.product_id.name)
|
||||
if match:
|
||||
sale_order_name = match.group(0)
|
||||
sale_order = self.env['sale.order'].sudo().search(
|
||||
[('name', '=', sale_order_name)])
|
||||
logging.info("product_name is :%s" % product_name)
|
||||
filtered_order_line = sale_order.order_line.filtered(
|
||||
lambda production: re.search(f'{product_name}$', production.product_id.name)
|
||||
)
|
||||
if filtered_order_line:
|
||||
production_id.part_number = filtered_order_line.part_number
|
||||
production_id.part_name = filtered_order_line.part_name
|
||||
except Exception as e:
|
||||
traceback_error = traceback.format_exc()
|
||||
logging.error("制造订单零件图号 零件名称获取失败:%s" % traceback_error)
|
||||
|
||||
# 判断制造的产品类型
|
||||
production_product_type = fields.Selection([
|
||||
|
||||
@@ -1533,7 +1533,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
# workorder.rfid_code_old = rfid_code
|
||||
# workorder.rfid_code = False
|
||||
logging.info('workorder.rfid_code:%s' % workorder.rfid_code)
|
||||
# if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺', '切割']:
|
||||
|
||||
if is_production_id is True:
|
||||
logging.info('product_qty:%s' % record.production_id.product_qty)
|
||||
for move_raw_id in record.production_id.move_raw_ids:
|
||||
@@ -1548,6 +1548,17 @@ class ResMrpWorkOrder(models.Model):
|
||||
# if raw_move:
|
||||
# raw_move.write({'state': 'done'})
|
||||
if record.production_id.state != 'rework':
|
||||
# 如果工单包含了外协工序,需要预留数量
|
||||
if self.move_raw_ids.move_orig_ids.subcontract_workorder_id:
|
||||
location_id = self.move_raw_ids.location_id
|
||||
quant = self.move_raw_ids.lot_ids.quant_ids.filtered(lambda q: q.location_id.id == location_id.id)
|
||||
if quant.reserved_quantity == 0:
|
||||
self.env['stock.quant']._update_reserved_quantity(
|
||||
self.move_raw_ids.product_id,
|
||||
location_id,
|
||||
quant.quantity,
|
||||
lot_id=quant.lot_id,
|
||||
)
|
||||
record.production_id.button_mark_done1()
|
||||
# record.production_id.state = 'done'
|
||||
|
||||
|
||||
@@ -173,7 +173,6 @@ class ResProductMo(models.Model):
|
||||
'压紧方式', domain=[('type', '=', '压紧方式')])
|
||||
|
||||
name = fields.Char('产品名称', compute='_compute_tool_name', store=True, required=False)
|
||||
|
||||
|
||||
@api.constrains('seller_ids')
|
||||
def _check_seller_ids(self):
|
||||
@@ -896,8 +895,9 @@ class ResProductMo(models.Model):
|
||||
'model_long': self.format_float(item['model_long'] + embryo_redundancy_id.long),
|
||||
'model_width': self.format_float(item['model_width'] + embryo_redundancy_id.width),
|
||||
'model_height': self.format_float(item['model_height'] + embryo_redundancy_id.height),
|
||||
'model_volume': self.format_float(item['blank_volume']),
|
||||
'model_area': self.format_float(item['blank_area']),
|
||||
'model_volume': self.format_float((item['model_long'] + embryo_redundancy_id.long) * (
|
||||
item['model_width'] + embryo_redundancy_id.width) * (
|
||||
item['model_height'] + embryo_redundancy_id.height)),
|
||||
'product_model_type_id': model_type.id,
|
||||
'model_processing_panel': item['processing_panel_detail'],
|
||||
'model_machining_precision': item['model_machining_precision'],
|
||||
@@ -1114,9 +1114,9 @@ class ResProductMo(models.Model):
|
||||
image_data = fileObj.read()
|
||||
base64_data = base64.b64encode(image_data)
|
||||
return base64_data
|
||||
|
||||
|
||||
# 增加产品表面积
|
||||
|
||||
|
||||
|
||||
|
||||
class ResProductFixture(models.Model):
|
||||
|
||||
@@ -59,18 +59,15 @@ class PurchaseOrder(models.Model):
|
||||
production_id = self.env['mrp.production'].search([('origin', 'in', origins)])
|
||||
purchase.production_count = len(production_id)
|
||||
|
||||
# def button_confirm(self):
|
||||
# super().button_confirm()
|
||||
# workorders = self.env['mrp.workorder'].search([('purchase_id', '=', self.id), ('state', '!=', 'cancel')])
|
||||
# for workorder in workorders:
|
||||
# if workorder.routing_type == '表面工艺' and workorder.is_subcontract is True:
|
||||
# move_out = workorder.move_subcontract_workorder_ids[1]
|
||||
# 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
|
||||
def button_confirm(self):
|
||||
for record in self:
|
||||
for line in record.order_line:
|
||||
if line.product_qty <= 0:
|
||||
raise UserError('请对【产品】中的【数量】进行输入')
|
||||
if line.price_unit <= 0:
|
||||
raise UserError('请对【产品】中的【单价】进行输入')
|
||||
return super(PurchaseOrder, self).button_confirm()
|
||||
|
||||
|
||||
origin_sale_id = fields.Many2one('sale.order', string='销售订单号', store=True, compute='_compute_origin_sale_id')
|
||||
origin_sale_ids = fields.Many2many('sale.order', string='销售订单号(多个)', store=True,
|
||||
|
||||
@@ -564,6 +564,18 @@ class StockPicking(models.Model):
|
||||
sale_order_id = fields.Many2one('sale.order', '销售单号', compute='_compute_move_ids', store=True)
|
||||
picking_type_sequence_code = fields.Char(related='picking_type_id.sequence_code')
|
||||
|
||||
part_numbers = fields.Char(string="零件图号", compute='_compute_part_info', store=True, index=True)
|
||||
part_names = fields.Char(string="零件名称", compute='_compute_part_info', store=True, index=True)
|
||||
|
||||
@api.depends('move_ids_without_package.part_number', 'move_ids_without_package.part_name')
|
||||
def _compute_part_info(self):
|
||||
for picking in self:
|
||||
# 聚合所有关联行的 part_number 和 part_name
|
||||
part_numbers = picking.move_ids_without_package.mapped('part_number')
|
||||
part_names = picking.move_ids_without_package.mapped('part_name')
|
||||
picking.part_numbers = ','.join(filter(None, part_numbers))
|
||||
picking.part_names = ','.join(filter(None, part_names))
|
||||
|
||||
@api.depends('move_ids', 'move_ids.product_id')
|
||||
def _compute_move_ids(self):
|
||||
for item in self:
|
||||
@@ -678,7 +690,8 @@ class StockPicking(models.Model):
|
||||
# 如果当前工单是是制造订单的最后一个工艺外协工单
|
||||
if workorder == next((workorder for workorder in reversed(sorted_workorders) if workorder.is_subcontract),
|
||||
None):
|
||||
move_dest_id = item.move_raw_ids[0].id
|
||||
if item.move_raw_ids:
|
||||
move_dest_id = item.move_raw_ids[0].id
|
||||
else:
|
||||
# 从sorted_workorders中找到上一工单的move
|
||||
if len(sorted_workorders) > 1:
|
||||
@@ -714,6 +727,7 @@ class StockPicking(models.Model):
|
||||
moves_out._action_confirm()
|
||||
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()
|
||||
@@ -837,6 +851,7 @@ class ReStockMove(models.Model):
|
||||
# 'route_ids': False if not route else [(4, route.id)],
|
||||
'date_deadline': datetime.now(),
|
||||
'picking_type_id': picking_type_id,
|
||||
# 'is_subcontract': True,
|
||||
}
|
||||
return move_values
|
||||
|
||||
@@ -1106,6 +1121,13 @@ class ReStockMove(models.Model):
|
||||
if self.state != 'assigned':
|
||||
self.state = 'assigned'
|
||||
return self.action_show_details()
|
||||
|
||||
def _prepare_move_line_vals(self, quantity=None, reserved_quant=None):
|
||||
res = super(ReStockMove, self)._prepare_move_line_vals(quantity, reserved_quant)
|
||||
if self.subcontract_workorder_id:
|
||||
if self.subcontract_workorder_id.production_id.move_raw_ids.move_line_ids:
|
||||
res['lot_id'] = self.subcontract_workorder_id.production_id.move_raw_ids.move_line_ids[0].lot_id.id
|
||||
return res
|
||||
|
||||
|
||||
class ReStockQuant(models.Model):
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<xpath expr="//page/field[@name='order_line']/tree/field[@name='remark']" position="before">
|
||||
<field name="supply_method" attrs="{'invisible': [('state', '=', 'draft')], 'required': [('state', '=', 'supply method')]}" />
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='order_line']/tree/field[@name='glb_url']" position="before">
|
||||
<xpath expr="//field[@name='order_line']/tree/field[@name='product_template_id']" position="after">
|
||||
<field name="part_number" optional="show" class="section_and_note_text"/>
|
||||
</xpath>
|
||||
<!-- <xpath expr="//field[@name='order_line']/tree/field[@name='remark']" position="before"> -->
|
||||
|
||||
@@ -68,14 +68,8 @@
|
||||
context="{'group_by': 'retrospect_ref'}"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='picking_type_id']" position="after">
|
||||
<field name="product_id"
|
||||
string="零件图号"
|
||||
filter_domain="[('product_id.part_number', 'ilike', self)]"
|
||||
/>
|
||||
<field name="product_id"
|
||||
string="零件名称"
|
||||
filter_domain="[('product_id.part_name', 'ilike', self)]"
|
||||
/>
|
||||
<field name="part_numbers" string="零件图号" filter_domain="[('part_numbers', 'ilike', self)]"/>
|
||||
<field name="part_names" string="零件名称" filter_domain="[('part_names', 'ilike', self)]"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
@@ -97,7 +91,8 @@
|
||||
<attribute name="invisible">True</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//form//button[@name='action_assign_serial_show_details']" position="after">
|
||||
<button name="button_update_the_sequence_number" type="object" class="btn-link" data-hotkey="k" title="Assign Serial Numbers">
|
||||
<button name="button_update_the_sequence_number" type="object" class="btn-link" data-hotkey="k"
|
||||
title="Assign Serial Numbers">
|
||||
<span>更新序列号</span>
|
||||
</button>
|
||||
</xpath>
|
||||
|
||||
@@ -191,7 +191,8 @@ class SFMessageWork(models.Model):
|
||||
|
||||
def write(self, vals):
|
||||
res = super(SFMessageWork, self).write(vals)
|
||||
if ('leave_id' in vals and vals['leave_id'] is False or 'date_planned_start' in vals and vals['date_planned_start'] is False) \
|
||||
and self.schedule_state != '未排':
|
||||
self.add_queue('计划数据异常跟踪')
|
||||
for record in self:
|
||||
if ('leave_id' in vals and vals['leave_id'] is False or 'date_planned_start' in vals and vals['date_planned_start'] is False) \
|
||||
and record.schedule_state != '未排':
|
||||
record.add_queue('计划数据异常跟踪')
|
||||
return res
|
||||
|
||||
@@ -3214,6 +3214,7 @@ class EmbryoRedundancySync(models.Model):
|
||||
embryo_redundancy.width = item['width']
|
||||
embryo_redundancy.height = item['height']
|
||||
embryo_redundancy.active = item['active']
|
||||
embryo_redundancy.remark = item['remark']
|
||||
else:
|
||||
self.env['sf.embryo.redundancy'].sudo().create({
|
||||
"name": item['name'],
|
||||
@@ -3222,4 +3223,5 @@ class EmbryoRedundancySync(models.Model):
|
||||
"width": item['width'],
|
||||
"height": item['height'],
|
||||
"active": item['active'],
|
||||
"remark": item['remark'],
|
||||
})
|
||||
Reference in New Issue
Block a user