Compare commits
2 Commits
feature/cu
...
feature/pl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5dfb50da5 | ||
|
|
1f938292f5 |
@@ -536,7 +536,3 @@ div:has(.o_required_modifier) > label::before {
|
|||||||
position: unset;
|
position: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修复搜索面板checkbox样式
|
|
||||||
.o_search_panel .form-check .form-check-label span {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
@@ -190,7 +190,7 @@ def _create(self, data_list):
|
|||||||
# 如果该用户组被限制创建或更新操作
|
# 如果该用户组被限制创建或更新操作
|
||||||
if rec['is_create_or_update']:
|
if rec['is_create_or_update']:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_("您没有执行此操作的权限。请联系管理员"))
|
_("You are restricted from performing this operation. Please contact the administrator."))
|
||||||
else:
|
else:
|
||||||
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
|
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
|
||||||
# 例如,记录日志、发送通知或者简单地跳过这部分逻辑
|
# 例如,记录日志、发送通知或者简单地跳过这部分逻辑
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from . import controllers
|
|
||||||
from . import models
|
|
||||||
from . import wizards
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# -*- 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', 'base_tier_validation', 'documents'],
|
|
||||||
|
|
||||||
# always loaded
|
|
||||||
'data': [
|
|
||||||
'security/ir.model.access.csv',
|
|
||||||
'data/documents_data.xml',
|
|
||||||
'wizards/upload_file_wizard_view.xml',
|
|
||||||
'views/views.xml',
|
|
||||||
],
|
|
||||||
# only loaded in demonstration mode
|
|
||||||
'demo': [
|
|
||||||
'demo/demo.xml',
|
|
||||||
],
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from . import controllers
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# from odoo import http
|
|
||||||
|
|
||||||
|
|
||||||
# class JikimoPurchaseTierValidation(http.Controller):
|
|
||||||
# @http.route('/jikimo_purchase_tier_validation/jikimo_purchase_tier_validation', auth='public')
|
|
||||||
# def index(self, **kw):
|
|
||||||
# return "Hello, world"
|
|
||||||
|
|
||||||
# @http.route('/jikimo_purchase_tier_validation/jikimo_purchase_tier_validation/objects', auth='public')
|
|
||||||
# def list(self, **kw):
|
|
||||||
# return http.request.render('jikimo_purchase_tier_validation.listing', {
|
|
||||||
# 'root': '/jikimo_purchase_tier_validation/jikimo_purchase_tier_validation',
|
|
||||||
# 'objects': http.request.env['jikimo_purchase_tier_validation.jikimo_purchase_tier_validation'].search([]),
|
|
||||||
# })
|
|
||||||
|
|
||||||
# @http.route('/jikimo_purchase_tier_validation/jikimo_purchase_tier_validation/objects/<model("jikimo_purchase_tier_validation.jikimo_purchase_tier_validation"):obj>', auth='public')
|
|
||||||
# def object(self, obj, **kw):
|
|
||||||
# return http.request.render('jikimo_purchase_tier_validation.object', {
|
|
||||||
# 'object': obj
|
|
||||||
# })
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<odoo>
|
|
||||||
<data noupdate="1">
|
|
||||||
<!-- 创建采购合同文件夹 -->
|
|
||||||
<record id="documents_purchase_contracts_folder" model="documents.folder">
|
|
||||||
<field name="name">采购合同</field>
|
|
||||||
<field name="description">存放采购合同相关文件</field>
|
|
||||||
<field name="sequence">10</field>
|
|
||||||
</record>
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
<odoo>
|
|
||||||
<data>
|
|
||||||
<!--
|
|
||||||
<record id="object0" model="jikimo_purchase_tier_validation.jikimo_purchase_tier_validation">
|
|
||||||
<field name="name">Object 0</field>
|
|
||||||
<field name="value">0</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="object1" model="jikimo_purchase_tier_validation.jikimo_purchase_tier_validation">
|
|
||||||
<field name="name">Object 1</field>
|
|
||||||
<field name="value">10</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="object2" model="jikimo_purchase_tier_validation.jikimo_purchase_tier_validation">
|
|
||||||
<field name="name">Object 2</field>
|
|
||||||
<field name="value">20</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="object3" model="jikimo_purchase_tier_validation.jikimo_purchase_tier_validation">
|
|
||||||
<field name="name">Object 3</field>
|
|
||||||
<field name="value">30</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="object4" model="jikimo_purchase_tier_validation.jikimo_purchase_tier_validation">
|
|
||||||
<field name="name">Object 4</field>
|
|
||||||
<field name="value">40</field>
|
|
||||||
</record>
|
|
||||||
-->
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from . import models
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
from odoo import models, fields, api, _
|
|
||||||
from odoo.exceptions import ValidationError
|
|
||||||
import logging
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class jikimo_purchase_tier_validation(models.Model):
|
|
||||||
_name = 'purchase.order'
|
|
||||||
_inherit = ['purchase.order', 'tier.validation']
|
|
||||||
|
|
||||||
_tier_validation_buttons_xpath = "/form/header/button[@id='draft_confirm'][1]"
|
|
||||||
|
|
||||||
contract_document_id = fields.Many2one('documents.document', string='合同文件')
|
|
||||||
contract_file = fields.Binary(related='contract_document_id.datas', string='合同文件内容')
|
|
||||||
contract_file_name = fields.Char(related='contract_document_id.attachment_id.name', string='文件名')
|
|
||||||
|
|
||||||
# 是否已上传合同文件
|
|
||||||
is_upload_contract_file = fields.Boolean(string='是否已上传合同文件', default=False)
|
|
||||||
|
|
||||||
def button_confirm(self):
|
|
||||||
for record in self:
|
|
||||||
if record.need_validation and record.validation_status != 'validated':
|
|
||||||
raise ValidationError(_('请先完成审批!'))
|
|
||||||
return super().button_confirm()
|
|
||||||
|
|
||||||
# def button_confirm(self):
|
|
||||||
# self = self.with_context(skip_validation=True)
|
|
||||||
# return super().button_confirm()
|
|
||||||
#
|
|
||||||
# def _check_state_conditions(self, vals):
|
|
||||||
# self.ensure_one()
|
|
||||||
# if self._context.get('skip_validation'):
|
|
||||||
# return False
|
|
||||||
# return (
|
|
||||||
# self._check_state_from_condition()
|
|
||||||
# and vals.get(self._state_field) in self._state_to
|
|
||||||
# )
|
|
||||||
|
|
||||||
def request_validation(self):
|
|
||||||
for record in self:
|
|
||||||
error_messages = []
|
|
||||||
|
|
||||||
# 检查必填字段
|
|
||||||
required_fields = {
|
|
||||||
'partner_ref': '合同名称',
|
|
||||||
'contract_number': '合同编号'
|
|
||||||
}
|
|
||||||
|
|
||||||
missing_fields = [
|
|
||||||
name for field, name in required_fields.items()
|
|
||||||
if not record[field]
|
|
||||||
]
|
|
||||||
|
|
||||||
if missing_fields:
|
|
||||||
error_messages.append('* 如下字段要求必须填写:%s' % '、'.join(missing_fields))
|
|
||||||
|
|
||||||
# 检查合同文件
|
|
||||||
if not record.contract_document_id:
|
|
||||||
error_messages.append('* 必须点击上传合同文件')
|
|
||||||
|
|
||||||
# 如果有任何错误,一次性显示所有错误信息
|
|
||||||
if error_messages:
|
|
||||||
raise ValidationError('\n'.join(error_messages))
|
|
||||||
|
|
||||||
return super(jikimo_purchase_tier_validation, self).request_validation()
|
|
||||||
|
|
||||||
# 上传合同文件
|
|
||||||
def upload_contract_file(self):
|
|
||||||
print('upload_contract_file===========================')
|
|
||||||
# self.ensure_one()
|
|
||||||
# return {
|
|
||||||
# 'name': _('上传合同文件'),
|
|
||||||
# 'type': 'ir.actions.act_window',
|
|
||||||
# 'res_model': 'ir.attachment',
|
|
||||||
# 'view_mode': 'form',
|
|
||||||
# 'view_type': 'form',
|
|
||||||
# 'target': 'new',
|
|
||||||
# 'context': {
|
|
||||||
# 'default_res_model': self._name,
|
|
||||||
# 'default_res_id': self.id,
|
|
||||||
# 'default_type': 'binary',
|
|
||||||
# 'default_mimetype': 'application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,image/jpeg,image/png',
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
|
|
||||||
self.ensure_one()
|
|
||||||
action = {
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'name': _('上传合同文件'),
|
|
||||||
'res_model': 'ir.attachment.wizard', # 我们需要创建一个新的向导模型
|
|
||||||
'view_mode': 'form',
|
|
||||||
'target': 'new',
|
|
||||||
'context': {
|
|
||||||
'default_res_model': self._name,
|
|
||||||
'default_res_id': self.id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return action
|
|
||||||
|
|
||||||
# 删除合同文件
|
|
||||||
def delete_contract_file(self):
|
|
||||||
self.ensure_one()
|
|
||||||
if self.contract_document_id:
|
|
||||||
try:
|
|
||||||
document = self.contract_document_id
|
|
||||||
|
|
||||||
# 清空关联
|
|
||||||
self.write({
|
|
||||||
'contract_document_id': False,
|
|
||||||
'contract_file': False,
|
|
||||||
'contract_file_name': False
|
|
||||||
})
|
|
||||||
|
|
||||||
# 删除文档
|
|
||||||
if document:
|
|
||||||
document.with_context(no_attachment=True).sudo().unlink()
|
|
||||||
|
|
||||||
self.is_upload_contract_file = False
|
|
||||||
|
|
||||||
# 返回视图动作来刷新当前表单
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'res_model': 'purchase.order',
|
|
||||||
'res_id': self.id,
|
|
||||||
'view_mode': 'form',
|
|
||||||
'view_type': 'form',
|
|
||||||
'target': 'current',
|
|
||||||
'flags': {'mode': 'readonly'},
|
|
||||||
}
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
_logger.error('删除合同文件时出错: %s', str(e))
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'display_notification',
|
|
||||||
'params': {
|
|
||||||
'title': _('错误'),
|
|
||||||
'message': _('删除文件时出现错误'),
|
|
||||||
'type': 'danger',
|
|
||||||
'sticky': True,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'display_notification',
|
|
||||||
'params': {
|
|
||||||
'title': _('提示'),
|
|
||||||
'message': _('没有需要删除的合同文件'),
|
|
||||||
'type': 'warning',
|
|
||||||
'sticky': False,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
|
||||||
access_ir_attachment_wizard,ir.attachment.wizard,model_ir_attachment_wizard,base.group_user,1,1,1,1
|
|
||||||
|
@@ -1,24 +0,0 @@
|
|||||||
<odoo>
|
|
||||||
<data>
|
|
||||||
<!--
|
|
||||||
<template id="listing">
|
|
||||||
<ul>
|
|
||||||
<li t-foreach="objects" t-as="object">
|
|
||||||
<a t-attf-href="#{ root }/objects/#{ object.id }">
|
|
||||||
<t t-esc="object.display_name"/>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
<template id="object">
|
|
||||||
<h1><t t-esc="object.display_name"/></h1>
|
|
||||||
<dl>
|
|
||||||
<t t-foreach="object._fields" t-as="field">
|
|
||||||
<dt><t t-esc="field"/></dt>
|
|
||||||
<dd><t t-esc="object[field]"/></dd>
|
|
||||||
</t>
|
|
||||||
</dl>
|
|
||||||
</template>
|
|
||||||
-->
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<odoo>
|
|
||||||
<data>
|
|
||||||
<record model="ir.ui.view" id="tier_validation_view_purchase_order_form_inherit">
|
|
||||||
<field name="name">tier_validation_view_purchase_order_form_inherit</field>
|
|
||||||
<field name="model">purchase.order</field>
|
|
||||||
<field name="inherit_id" ref="purchase.purchase_order_form"/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<xpath expr="//header/button[@name='button_cancel']" position="replace">
|
|
||||||
</xpath>
|
|
||||||
|
|
||||||
<xpath expr="//header/button[last()]" position="after">
|
|
||||||
<button name="button_cancel" states="draft,to approve,sent,purchase" string="取消" type="object" data-hotkey="x" />
|
|
||||||
</xpath>
|
|
||||||
|
|
||||||
<xpath expr="//header/button[@name='action_rfq_send'][1]" position="before">
|
|
||||||
<field name="validation_status" invisible="1"/>
|
|
||||||
<field name="is_upload_contract_file" invisible="1"/>
|
|
||||||
<button name="upload_contract_file" string="上传合同" type="object" class="oe_highlight" attrs="{'invisible': ['|', ('validation_status', '!=', 'no'), ('is_upload_contract_file', '=', True)]}"/>
|
|
||||||
<button name="delete_contract_file" string="删除合同" type="object" class="oe_highlight" attrs="{'invisible': ['|', ('validation_status', '!=', 'no'), ('is_upload_contract_file', '=', False)]}"/>
|
|
||||||
</xpath>
|
|
||||||
<xpath expr="//notebook/page[1]" position="before">
|
|
||||||
<page string="合同" name="contract_documents"
|
|
||||||
attrs="{'invisible': [('contract_document_id', '=', False)]}"
|
|
||||||
autofocus="autofocus">
|
|
||||||
<group>
|
|
||||||
<group>
|
|
||||||
<field name="contract_document_id" invisible="1"/>
|
|
||||||
<field name="contract_file_name" invisible="1"/>
|
|
||||||
<field name="contract_file"
|
|
||||||
widget="adaptive_viewer"
|
|
||||||
filename="contract_file_name"/>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
</page>
|
|
||||||
</xpath>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- actions opening views on models -->
|
|
||||||
<!--
|
|
||||||
<record model="ir.actions.act_window" id="jikimo_purchase_tier_validation.action_window">
|
|
||||||
<field name="name">jikimo_purchase_tier_validation window</field>
|
|
||||||
<field name="res_model">jikimo_purchase_tier_validation.jikimo_purchase_tier_validation</field>
|
|
||||||
<field name="view_mode">tree,form</field>
|
|
||||||
</record>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- server action to the one above -->
|
|
||||||
<!--
|
|
||||||
<record model="ir.actions.server" id="jikimo_purchase_tier_validation.action_server">
|
|
||||||
<field name="name">jikimo_purchase_tier_validation server</field>
|
|
||||||
<field name="model_id" ref="model_jikimo_purchase_tier_validation_jikimo_purchase_tier_validation"/>
|
|
||||||
<field name="state">code</field>
|
|
||||||
<field name="code">
|
|
||||||
action = {
|
|
||||||
"type": "ir.actions.act_window",
|
|
||||||
"view_mode": "tree,form",
|
|
||||||
"res_model": model._name,
|
|
||||||
}
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- Top menu item -->
|
|
||||||
<!--
|
|
||||||
<menuitem name="jikimo_purchase_tier_validation" id="jikimo_purchase_tier_validation.menu_root"/>
|
|
||||||
-->
|
|
||||||
<!-- menu categories -->
|
|
||||||
<!--
|
|
||||||
<menuitem name="Menu 1" id="jikimo_purchase_tier_validation.menu_1" parent="jikimo_purchase_tier_validation.menu_root"/>
|
|
||||||
<menuitem name="Menu 2" id="jikimo_purchase_tier_validation.menu_2" parent="jikimo_purchase_tier_validation.menu_root"/>
|
|
||||||
-->
|
|
||||||
<!-- actions -->
|
|
||||||
<!--
|
|
||||||
<menuitem name="List" id="jikimo_purchase_tier_validation.menu_1_list" parent="jikimo_purchase_tier_validation.menu_1"
|
|
||||||
action="jikimo_purchase_tier_validation.action_window"/>
|
|
||||||
<menuitem name="Server to list" id="jikimo_purchase_tier_validation" parent="jikimo_purchase_tier_validation.menu_2"
|
|
||||||
action="jikimo_purchase_tier_validation.action_server"/>
|
|
||||||
-->
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
from . import upload_file_wizard
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
from odoo import models, fields, api, _
|
|
||||||
|
|
||||||
|
|
||||||
class IrAttachmentWizard(models.TransientModel):
|
|
||||||
_name = 'ir.attachment.wizard'
|
|
||||||
_description = '文件上传向导'
|
|
||||||
|
|
||||||
attachment = fields.Binary(string='选择文件', required=True)
|
|
||||||
filename = fields.Char(string='文件名')
|
|
||||||
res_model = fields.Char()
|
|
||||||
res_id = fields.Integer()
|
|
||||||
|
|
||||||
# def action_upload_file(self):
|
|
||||||
# self.ensure_one()
|
|
||||||
# # 首先创建 ir.attachment
|
|
||||||
# attachment = self.env['ir.attachment'].create({
|
|
||||||
# 'name': self.filename,
|
|
||||||
# 'type': 'binary',
|
|
||||||
# 'datas': self.attachment,
|
|
||||||
# 'res_model': self.res_model,
|
|
||||||
# 'res_id': self.res_id,
|
|
||||||
# })
|
|
||||||
#
|
|
||||||
# # 获取默认的文档文件夹
|
|
||||||
# workspace = self.env['documents.folder'].search([('name', '=', '采购合同')], limit=1)
|
|
||||||
#
|
|
||||||
# # 创建 documents.document 记录
|
|
||||||
# document = self.env['documents.document'].create({
|
|
||||||
# 'name': self.filename,
|
|
||||||
# 'attachment_id': attachment.id,
|
|
||||||
# 'folder_id': workspace.id,
|
|
||||||
# 'res_model': self.res_model,
|
|
||||||
# 'res_id': self.res_id,
|
|
||||||
# })
|
|
||||||
#
|
|
||||||
# return {
|
|
||||||
# 'type': 'ir.actions.client',
|
|
||||||
# 'tag': 'display_notification',
|
|
||||||
# 'params': {
|
|
||||||
# 'title': _('成功'),
|
|
||||||
# 'message': _('文件上传成功'),
|
|
||||||
# 'type': 'success',
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
|
|
||||||
def action_upload_file(self):
|
|
||||||
self.ensure_one()
|
|
||||||
# 获取当前用户的 partner_id
|
|
||||||
current_partner = self.env.user.partner_id
|
|
||||||
# 首先创建 ir.attachment
|
|
||||||
attachment = self.env['ir.attachment'].create({
|
|
||||||
'name': self.filename,
|
|
||||||
'type': 'binary',
|
|
||||||
'datas': self.attachment,
|
|
||||||
'res_model': self.res_model,
|
|
||||||
'res_id': self.res_id,
|
|
||||||
})
|
|
||||||
|
|
||||||
# 获取默认的文档文件夹
|
|
||||||
workspace = self.env['documents.folder'].search([('name', '=', '采购合同')], limit=1)
|
|
||||||
|
|
||||||
# 创建 documents.document 记录
|
|
||||||
document = self.env['documents.document'].create({
|
|
||||||
'name': self.filename,
|
|
||||||
'attachment_id': attachment.id,
|
|
||||||
'folder_id': workspace.id,
|
|
||||||
'res_model': self.res_model,
|
|
||||||
'res_id': self.res_id,
|
|
||||||
'partner_id': current_partner.id,
|
|
||||||
})
|
|
||||||
|
|
||||||
# 更新采购订单的合同文档字段
|
|
||||||
purchase_order = self.env['purchase.order'].browse(self.res_id)
|
|
||||||
purchase_order.write({
|
|
||||||
'contract_document_id': document.id,
|
|
||||||
'is_upload_contract_file': True
|
|
||||||
})
|
|
||||||
|
|
||||||
# 显示成功消息并关闭向导
|
|
||||||
message = {
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'display_notification',
|
|
||||||
'params': {
|
|
||||||
'title': _('成功'),
|
|
||||||
'message': _('文件上传成功'),
|
|
||||||
'type': 'success',
|
|
||||||
'sticky': False, # 自动消失
|
|
||||||
'next': {
|
|
||||||
'type': 'ir.actions.act_window_close'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return message
|
|
||||||
|
|
||||||
|
|
||||||
# def action_upload_file(self):
|
|
||||||
# self.ensure_one()
|
|
||||||
# attachment = self.env['ir.attachment'].create({
|
|
||||||
# 'name': self.filename,
|
|
||||||
# 'type': 'binary',
|
|
||||||
# 'datas': self.attachment,
|
|
||||||
# 'res_model': self.res_model,
|
|
||||||
# 'res_id': self.res_id,
|
|
||||||
# })
|
|
||||||
# return {
|
|
||||||
# 'type': 'ir.actions.client',
|
|
||||||
# 'tag': 'display_notification',
|
|
||||||
# 'params': {
|
|
||||||
# 'title': _('成功'),
|
|
||||||
# 'message': _('文件上传成功'),
|
|
||||||
# 'type': 'success',
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<odoo>
|
|
||||||
<record id="view_upload_file_wizard_form" model="ir.ui.view">
|
|
||||||
<field name="name">ir.attachment.wizard.form</field>
|
|
||||||
<field name="model">ir.attachment.wizard</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<form string="上传文件">
|
|
||||||
<group>
|
|
||||||
<field name="attachment" widget="binary" filename="filename" options="{'accepted_file_extensions': '.pdf,.doc,.docx,.jpg,.jpeg,.png'}"/>
|
|
||||||
<field name="filename" invisible="1"/>
|
|
||||||
<field name="res_model" invisible="1"/>
|
|
||||||
<field name="res_id" invisible="1"/>
|
|
||||||
</group>
|
|
||||||
<footer>
|
|
||||||
<button name="action_upload_file" string="确认上传" type="object" class="btn-primary"/>
|
|
||||||
<button string="取消" class="btn-secondary" special="cancel"/>
|
|
||||||
</footer>
|
|
||||||
</form>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
</odoo>
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from . import models
|
|
||||||
from . import controllers
|
|
||||||
|
|
||||||
from odoo import api, SUPERUSER_ID
|
|
||||||
|
|
||||||
def _data_install(cr, registry):
|
|
||||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
|
||||||
# 获取所有需要设置的产品模板
|
|
||||||
env.ref('jikimo_sale_multiple_supply_methods.product_template_purchase').product_variant_id.write({'active': False, 'is_bfm': True})
|
|
||||||
env.ref('jikimo_sale_multiple_supply_methods.product_template_manual_processing').product_variant_id.write({'active': False, 'single_manufacturing': True, 'is_bfm': True})
|
|
||||||
env.ref('jikimo_sale_multiple_supply_methods.product_template_default').product_variant_id.write({'active': False, 'is_bfm': True})
|
|
||||||
env.ref('jikimo_sale_multiple_supply_methods.product_template_embryo_customer_provided').product_variant_id.write({'active': False})
|
|
||||||
env.ref('jikimo_sale_multiple_supply_methods.product_template_outsourcing').product_variant_id.write({'active': False, 'is_bfm': True})
|
|
||||||
|
|
||||||
# 为三步制造增加规则
|
|
||||||
warehouse = env['stock.warehouse'].search([('company_id', '=', env.company.id)], limit=1)
|
|
||||||
product_route_id = warehouse.pbm_route_id
|
|
||||||
# 创建规则:原料存货区 -> 制造前, 坯料存货区 -> 制造前, 制造后 -> 坯料存货区, 制造后 -> 成品存货区
|
|
||||||
raw_material_location_id = env['stock.location'].search([('name', '=', '坯料存货区')], limit=1)
|
|
||||||
picking_type_production = warehouse.pbm_type_id
|
|
||||||
picking_type_stock = warehouse.sam_type_id
|
|
||||||
material_location_id = env['stock.location'].search([('name', '=', '原料存货区')], limit=1)
|
|
||||||
# 为mto增加规则
|
|
||||||
mto_route_id = env.ref('stock.route_warehouse0_mto')
|
|
||||||
# 创建规则:原料存货区 -> 外包位置, 坯料存货区 -> 外包位置
|
|
||||||
subcontracting_location_id = env.company.subcontracting_location_id
|
|
||||||
picking_type_subcontracting = warehouse.subcontracting_resupply_type_id
|
|
||||||
# 为补给外包商增加规则
|
|
||||||
resupply_route_id = warehouse.subcontracting_route_id
|
|
||||||
|
|
||||||
rules_data = [
|
|
||||||
{
|
|
||||||
'name': 'WH: 原料存货区 → 制造前',
|
|
||||||
'location_src_id': material_location_id.id,
|
|
||||||
'location_dest_id': warehouse.pbm_loc_id.id,
|
|
||||||
'route_id': product_route_id.id,
|
|
||||||
'picking_type_id': picking_type_production.id,
|
|
||||||
'action': 'pull',
|
|
||||||
'sequence': 20,
|
|
||||||
'warehouse_id': warehouse.id,
|
|
||||||
'procure_method': 'mts_else_mto',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'WH: 坯料存货区 → 制造前',
|
|
||||||
'location_src_id': raw_material_location_id.id,
|
|
||||||
'location_dest_id': warehouse.pbm_loc_id.id,
|
|
||||||
'route_id': product_route_id.id,
|
|
||||||
'picking_type_id': picking_type_production.id,
|
|
||||||
'action': 'pull',
|
|
||||||
'sequence': 21,
|
|
||||||
'warehouse_id': warehouse.id,
|
|
||||||
'procure_method': 'mts_else_mto',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'WH: 制造后 → 坯料存货区',
|
|
||||||
'location_src_id': warehouse.sam_loc_id.id,
|
|
||||||
'location_dest_id': raw_material_location_id.id,
|
|
||||||
'route_id': product_route_id.id,
|
|
||||||
'picking_type_id': picking_type_stock.id,
|
|
||||||
'action': 'push',
|
|
||||||
'sequence': 23,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'WH: 制造后 → 成品存货区',
|
|
||||||
'location_src_id': warehouse.sam_loc_id.id,
|
|
||||||
'location_dest_id': env['stock.location'].search([('name', '=', '成品存货区')], limit=1).id,
|
|
||||||
'route_id': product_route_id.id,
|
|
||||||
'picking_type_id': picking_type_stock.id,
|
|
||||||
'action': 'push',
|
|
||||||
'sequence': 24,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'WH: 原料存货区 → 外包位置 (MTO)',
|
|
||||||
'location_src_id': material_location_id.id,
|
|
||||||
'location_dest_id': subcontracting_location_id.id,
|
|
||||||
'route_id': mto_route_id.id,
|
|
||||||
'picking_type_id': picking_type_subcontracting.id,
|
|
||||||
'action': 'pull',
|
|
||||||
'sequence': 24,
|
|
||||||
'warehouse_id': warehouse.id,
|
|
||||||
'procure_method': 'mts_else_mto',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'WH: 坯料存货区 → 外包位置 (MTO)',
|
|
||||||
'location_src_id': raw_material_location_id.id,
|
|
||||||
'location_dest_id': subcontracting_location_id.id,
|
|
||||||
'route_id': mto_route_id.id,
|
|
||||||
'picking_type_id': picking_type_subcontracting.id,
|
|
||||||
'action': 'pull',
|
|
||||||
'sequence': 25,
|
|
||||||
'warehouse_id': warehouse.id,
|
|
||||||
'procure_method': 'mts_else_mto',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'WH: 坯料存货区 → 外包位置',
|
|
||||||
'location_src_id': raw_material_location_id.id,
|
|
||||||
'location_dest_id': subcontracting_location_id.id,
|
|
||||||
'route_id': resupply_route_id.id,
|
|
||||||
'picking_type_id': picking_type_subcontracting.id,
|
|
||||||
'action': 'pull',
|
|
||||||
'sequence': 26,
|
|
||||||
'warehouse_id': warehouse.id,
|
|
||||||
'procure_method': 'make_to_stock',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
# 遍历每个规则数据,执行创建或更新操作
|
|
||||||
for rule_data in rules_data:
|
|
||||||
_create_or_update_stock_rule(env, rule_data)
|
|
||||||
|
|
||||||
def _create_or_update_stock_rule(env, rule_data):
|
|
||||||
# 尝试查找现有的 stock.rule
|
|
||||||
existing_rule = env['stock.rule'].search([
|
|
||||||
('name', '=', rule_data['name']),
|
|
||||||
('route_id', '=', rule_data.get('route_id'))
|
|
||||||
], limit=1)
|
|
||||||
|
|
||||||
if existing_rule:
|
|
||||||
# 如果存在,更新现有记录
|
|
||||||
existing_rule.write(rule_data)
|
|
||||||
else:
|
|
||||||
# 如果不存在,创建新记录
|
|
||||||
env['stock.rule'].create(rule_data)
|
|
||||||
|
|
||||||
def _data_uninstall(cr, registry):
|
|
||||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
|
||||||
warehouse = env['stock.warehouse'].search([('company_id', '=', env.company.id)], limit=1)
|
|
||||||
product_route_id = warehouse.pbm_route_id
|
|
||||||
resupply_route_id = warehouse.subcontracting_route_id
|
|
||||||
mto_route_id = env.ref('stock.route_warehouse0_mto')
|
|
||||||
# Fail unlink means that the route is used somewhere (e.g. route_id on stock.rule). In this case
|
|
||||||
# we don't try to do anything.
|
|
||||||
try:
|
|
||||||
with env.cr.savepoint():
|
|
||||||
env['stock.rule'].search([('name', 'in', ('WH: 原料存货区 → 制造前', 'WH: 坯料存货区 → 制造前', 'WH: 制造后 → 坯料存货区', 'WH: 制造后 → 成品存货区')), ('route_id', '=', product_route_id.id)]).unlink()
|
|
||||||
env['stock.rule'].search([('name', 'in', ('WH: 原料存货区 → 外包位置 (MTO)', 'WH: 坯料存货区 → 外包位置 (MTO)')), ('route_id', '=', mto_route_id.id)]).unlink()
|
|
||||||
env['stock.rule'].search([('name', '=', 'WH: 坯料存货区 → 外包位置'), ('route_id', '=', resupply_route_id.id)]).unlink()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
{
|
|
||||||
'name': '机企猫 多供货方式',
|
|
||||||
'version': '16.0.1.0.0',
|
|
||||||
'summary': """ 报价单提供(自动化产线加工/人工线下加工/外购/委外加工)多种供货方式选择 """,
|
|
||||||
'author': 'fox',
|
|
||||||
'website': '',
|
|
||||||
'category': '',
|
|
||||||
'depends': ['sf_dlm', 'sale_stock', 'sf_sale', 'sale'],
|
|
||||||
"data": [
|
|
||||||
'security/ir.model.access.csv',
|
|
||||||
'data/stock_routes.xml',
|
|
||||||
'data/product_data.xml',
|
|
||||||
# 'views/product_product_views.xml',
|
|
||||||
],'assets': {
|
|
||||||
# 'web.assets_backend': [
|
|
||||||
# 'jikimo_sale_multiple_supply_methods/static/src/**/*'
|
|
||||||
# ],
|
|
||||||
},
|
|
||||||
'post_init_hook': '_data_install',
|
|
||||||
'uninstall_hook': '_data_uninstall',
|
|
||||||
'application': True,
|
|
||||||
'installable': True,
|
|
||||||
'auto_install': False,
|
|
||||||
'license': 'LGPL-3',
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<odoo>
|
|
||||||
<data noupdate="1">
|
|
||||||
<record id="product_template_manual_processing" model="product.template">
|
|
||||||
<field name="name">人工线下加工模板</field>
|
|
||||||
<field name="active" eval="False"/>
|
|
||||||
<field name="categ_id" ref="sf_dlm.product_category_finished_sf"/>
|
|
||||||
<field name="route_ids"
|
|
||||||
eval="[ref('stock.route_warehouse0_mto'), ref('mrp.route_warehouse0_manufacture')]"/>
|
|
||||||
<field name="invoice_policy">delivery</field>
|
|
||||||
<field name="detailed_type">product</field>
|
|
||||||
<field name="purchase_ok">false</field>
|
|
||||||
<field name="uom_id" ref="uom.product_uom_unit"/>
|
|
||||||
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
|
||||||
<field name="company_id" ref="base.main_company"/>
|
|
||||||
<field name="single_manufacturing">true</field>
|
|
||||||
<field name="tracking">serial</field>
|
|
||||||
<!-- <field name="categ_type">成品</field> -->
|
|
||||||
<field name="is_manual_processing">true</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="product_template_purchase" model="product.template">
|
|
||||||
<field name="name">成品外购模板</field>
|
|
||||||
<field name="active" eval="False"/>
|
|
||||||
<field name="categ_id" ref="sf_dlm.product_category_finished_sf"/>
|
|
||||||
<field name="route_ids"
|
|
||||||
eval="[ref('stock.route_warehouse0_mto'), ref('purchase_stock.route_warehouse0_buy')]"/>
|
|
||||||
<field name="tracking">serial</field>
|
|
||||||
<field name="detailed_type">product</field>
|
|
||||||
<field name="uom_id" ref="uom.product_uom_unit"/>
|
|
||||||
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
|
||||||
<field name="company_id" ref="base.main_company"/>
|
|
||||||
<!-- <field name="categ_type">成品</field> -->
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="product_template_outsourcing" model="product.template">
|
|
||||||
<field name="name">成品委外加工模板</field>
|
|
||||||
<field name="active" eval="False"/>
|
|
||||||
<field name="categ_id" ref="sf_dlm.product_category_finished_sf"/>
|
|
||||||
<field name="route_ids"
|
|
||||||
eval="[ref('stock.route_warehouse0_mto'), ref('purchase_stock.route_warehouse0_buy'), ref('mrp_subcontracting.route_resupply_subcontractor_mto')]"/>
|
|
||||||
<field name="tracking">serial</field>
|
|
||||||
<field name="detailed_type">product</field>
|
|
||||||
<field name="uom_id" ref="uom.product_uom_unit"/>
|
|
||||||
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
|
||||||
<field name="company_id" ref="base.main_company"/>
|
|
||||||
<!-- <field name="categ_type">成品</field> -->
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="product_template_default" model="product.template">
|
|
||||||
<field name="name">成品初始化模板</field>
|
|
||||||
<field name="active" eval="False"/>
|
|
||||||
<field name="categ_id" ref="sf_dlm.product_category_finished_sf"/>
|
|
||||||
<field name="route_ids" eval="[]"/>
|
|
||||||
<field name="tracking">serial</field>
|
|
||||||
<field name="detailed_type">product</field>
|
|
||||||
<field name="uom_id" ref="uom.product_uom_unit"/>
|
|
||||||
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
|
||||||
<field name="company_id" ref="base.main_company"/>
|
|
||||||
<!-- <field name="categ_type">成品</field> -->
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- 供应商信息(业务平台),由于数据是python创建,只能指定ID -->
|
|
||||||
<record id="product_supplierinfo_bfm" model="product.supplierinfo">
|
|
||||||
<field name="partner_id" eval="91"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="product_template_embryo_customer_provided" model="product.template">
|
|
||||||
<field name="name">坯料客供料模板</field>
|
|
||||||
<field name="active" eval="False"/>
|
|
||||||
<field name="categ_id" ref="sf_dlm.product_category_embryo_sf"/>
|
|
||||||
<field name="route_ids" eval="[
|
|
||||||
ref('stock.route_warehouse0_mto'),
|
|
||||||
ref('mrp_subcontracting.route_resupply_subcontractor_mto'),
|
|
||||||
ref('jikimo_sale_multiple_supply_methods.route_material_processing')]"/>
|
|
||||||
<field name="sale_ok">false</field>
|
|
||||||
<field name="tracking">serial</field>
|
|
||||||
<field name="detailed_type">product</field>
|
|
||||||
<field name="uom_id" ref="uom.product_uom_unit"/>
|
|
||||||
<field name="uom_po_id" ref="uom.product_uom_unit"/>
|
|
||||||
<field name="company_id" ref="base.main_company"/>
|
|
||||||
<!-- <field name="categ_type">坯料</field> -->
|
|
||||||
<field name="seller_ids" eval="[ref('jikimo_sale_multiple_supply_methods.product_supplierinfo_bfm')]"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="sf_dlm.product_embryo_sf_self_machining" model="product.product">
|
|
||||||
<field name="is_manual_processing">true</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="sf_dlm.product_embryo_sf_self_machining" model="product.product">
|
|
||||||
<field name="route_ids" eval="[(4, ref('mrp_subcontracting.route_resupply_subcontractor_mto'))]"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="sf_dlm.product_embryo_sf_purchase" model="product.product">
|
|
||||||
<field name="route_ids" eval="[(4, ref('mrp_subcontracting.route_resupply_subcontractor_mto'))]"/>
|
|
||||||
</record>
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<odoo>
|
|
||||||
<data noupdate="1">
|
|
||||||
<record id="route_material_processing" model="stock.route">
|
|
||||||
<field name="name">带料加工</field>
|
|
||||||
<field name="product_selectable">true</field>
|
|
||||||
<field name="warehouse_selectable">true</field>
|
|
||||||
<field name="warehouse_ids" eval="[ref('stock.warehouse0')]"/>
|
|
||||||
<field name="sequence">16</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="material_picking_in" model="stock.picking.type">
|
|
||||||
<field name="name">客供料入库</field>
|
|
||||||
<field name="code">incoming</field>
|
|
||||||
<field name="active">true</field>
|
|
||||||
<field name="company_id" ref="base.main_company"/>
|
|
||||||
<field name="sequence_code">DL</field>
|
|
||||||
<field name="warehouse_id" ref="stock.warehouse0"/>
|
|
||||||
<field name="default_location_src_id" ref="stock.stock_location_customers"/>
|
|
||||||
<field name="default_location_dest_id" eval="25"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="rule_material_receiving" model="stock.rule">
|
|
||||||
<field name="name">带料收货</field>
|
|
||||||
<field name="route_id" ref="route_material_processing"/>
|
|
||||||
<field name="location_dest_id" ref="stock.stock_location_company"/>
|
|
||||||
<field name="location_src_id" ref="stock.stock_location_customers"/>
|
|
||||||
<field name="picking_type_id" ref="material_picking_in"/>
|
|
||||||
<field name="action">pull</field>
|
|
||||||
</record>
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from . import product_template
|
|
||||||
from . import mrp_bom
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
from odoo import models, fields
|
|
||||||
|
|
||||||
class MrpBom(models.Model):
|
|
||||||
_inherit = 'mrp.bom'
|
|
||||||
|
|
||||||
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品后再次进行创建bom
|
|
||||||
def bom_create(self, product, bom_type, product_type):
|
|
||||||
bom_id = super(MrpBom, self).bom_create(product, bom_type, product_type)
|
|
||||||
|
|
||||||
# 成品的供应商从模板中获取
|
|
||||||
if product_type == 'product':
|
|
||||||
bom_id.subcontractor_id = product.product_tmpl_id.seller_ids.partner_id.id
|
|
||||||
return bom_id
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
from odoo import models, fields, api
|
|
||||||
|
|
||||||
class ProductTemplate(models.Model):
|
|
||||||
_inherit = 'product.template'
|
|
||||||
|
|
||||||
is_manual_processing = fields.Boolean(string='人工线下加工')
|
|
||||||
is_customer_provided = fields.Boolean(string='客供料')
|
|
||||||
|
|
||||||
def copy_template(self, product_template_id):
|
|
||||||
if not isinstance(product_template_id, ProductTemplate):
|
|
||||||
raise ValueError('%s必须是ProductTemplate类型' % product_template_id)
|
|
||||||
|
|
||||||
self.route_ids = product_template_id.route_ids
|
|
||||||
self.categ_id = product_template_id.categ_id
|
|
||||||
self.invoice_policy = product_template_id.invoice_policy
|
|
||||||
self.detailed_type = product_template_id.detailed_type
|
|
||||||
self.purchase_ok = product_template_id.purchase_ok
|
|
||||||
self.uom_id = product_template_id.uom_id
|
|
||||||
self.uom_po_id = product_template_id.uom_po_id
|
|
||||||
self.company_id = product_template_id.company_id
|
|
||||||
self.single_manufacturing = product_template_id.single_manufacturing
|
|
||||||
self.tracking = product_template_id.tracking
|
|
||||||
self.is_bfm = product_template_id.is_bfm
|
|
||||||
self.is_manual_processing = product_template_id.is_manual_processing
|
|
||||||
# 复制 seller_ids
|
|
||||||
self.seller_ids = [(0, 0, {'partner_id': seller.partner_id.id, 'delay': 1.0}) for seller in product_template_id.seller_ids]
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
|
||||||
access_sale_order_group_production_engineer,sale.order_group_production_engineer,sale.model_sale_order,sf_base.group_production_engineer,1,1,0,0
|
|
||||||
access_sale_order_line_group_production_engineer,sale_order_line_group_production_engineer,sale.model_sale_order_line,sf_base.group_production_engineer,1,1,0,0
|
|
||||||
access_product_product_group_production_engineer,product_product_group_production_engineer,product.model_product_product,sf_base.group_production_engineer,1,0,0,0
|
|
||||||
access_product_template_group_production_engineer,product_template_group_production_engineer,product.model_product_template,sf_base.group_production_engineer,1,0,0,0
|
|
||||||
access_stock_picking_group_production_engineer,stock_picking_group_production_engineer,stock.model_stock_picking,sf_base.group_production_engineer,1,0,0,0
|
|
||||||
access_stock_move_group_production_engineer,stock_move_group_production_engineer,stock.model_stock_move,sf_base.group_production_engineer,1,0,0,0
|
|
||||||
access_mrp_bom_group_production_engineer,mrp_bom_group_production_engineer,mrp.model_mrp_bom,sf_base.group_production_engineer,1,0,0,0
|
|
||||||
|
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<odoo>
|
|
||||||
<!-- 由于该模块不能依赖sf_dlm_management, 该功能只能在sf_dlm_management中实现,并且依赖该模块-->
|
|
||||||
<record id="view_product_product_form_inherit_sf" model="ir.ui.view">
|
|
||||||
<field name="name">view.product.template.form.inherit.sf</field>
|
|
||||||
<field name="model">product.template</field>
|
|
||||||
<field name="inherit_id" ref="sf_dlm_management.view_sale_product_template_form_inherit_sf"/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<xpath expr="//field[@name='manual_quotation']" position="after">
|
|
||||||
<field name="is_customer_provided" attrs="{'invisible': [('categ_type', 'not in', ['成品', '坯料'])], 'readonly': True}" />
|
|
||||||
</xpath>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
</odoo>
|
|
||||||
|
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ class WorkorderExceptionConroller(http.Controller):
|
|||||||
})
|
})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
|
res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)}
|
||||||
_logger.info('workder_exception error:%s' % e)
|
_logger.info('workder_exception error:%s' % e)
|
||||||
return json.JSONEncoder().encode(res)
|
return json.JSONEncoder().encode(res)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,2 @@
|
|||||||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
||||||
"access_jikimo_workorder_exception","access.jikimo.workorder.exception","model_jikimo_workorder_exception","mrp.group_mrp_user",1,1,1,0
|
"access_jikimo_workorder_exception","access.jikimo.workorder.exception","model_jikimo_workorder_exception","mrp.group_mrp_user",1,1,1,0
|
||||||
"access_jikimo_workorder_exception_group_quality","access.jikimo.workorder.exception.group_quality","model_jikimo_workorder_exception","sf_base.group_quality",1,1,1,0
|
|
||||||
"access_jikimo_workorder_exception_group_quality_director","access.jikimo.workorder.exception.group_quality_director","model_jikimo_workorder_exception","sf_base.group_quality_director",1,1,1,0
|
|
||||||
|
|
||||||
|
|||||||
|
@@ -51,11 +51,11 @@ class JikimoWorkorderException(models.Model):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
def _get_message(self, message_queue_ids):
|
def _get_message(self, message_queue_ids):
|
||||||
contents, _ = super(JikimoWorkorderException, self)._get_message(message_queue_ids)
|
contents = super(JikimoWorkorderException, self)._get_message(message_queue_ids)
|
||||||
url = self.env['ir.config_parameter'].get_param('web.base.url')
|
url = self.env['ir.config_parameter'].get_param('web.base.url')
|
||||||
action_id = self.env.ref('mrp.mrp_production_action').id
|
action_id = self.env.ref('mrp.mrp_production_action').id
|
||||||
for index, content in enumerate(contents):
|
for index, content in enumerate(contents):
|
||||||
exception_id = self.env['jikimo.workorder.exception'].browse(message_queue_ids[index].res_id)
|
exception_id = self.env['jikimo.workorder.exception'].browse(message_queue_ids[index].res_id)
|
||||||
url = url + '/web#id=%s&view_type=form&action=%s' % (exception_id.workorder_id.production_id.id, action_id)
|
url = url + '/web#id=%s&view_type=form&action=%s' % (exception_id.workorder_id.production_id.id, action_id)
|
||||||
contents[index] = content.replace('{{url}}', url)
|
contents[index] = content.replace('{{url}}', url)
|
||||||
return contents, message_queue_ids
|
return contents
|
||||||
|
|||||||
@@ -1273,18 +1273,3 @@ msgstr ""
|
|||||||
#: model:product.template,description_sale:mrp_workorder.product_template_stool_top
|
#: model:product.template,description_sale:mrp_workorder.product_template_stool_top
|
||||||
msgid "wooden stool top"
|
msgid "wooden stool top"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. module: mrp_workorder
|
|
||||||
#: model:quality.point.test_type,name:mrp_workorder.test_type_register_consumed_materials
|
|
||||||
msgid "Register Consumed Materials"
|
|
||||||
msgstr "登记消耗材料"
|
|
||||||
|
|
||||||
#. module: mrp_workorder
|
|
||||||
#: model:quality.point.test_type,name:mrp_workorder.test_type_register_byproducts
|
|
||||||
msgid "Register By-products"
|
|
||||||
msgstr "按产品注册"
|
|
||||||
|
|
||||||
#. module: mrp_workorder
|
|
||||||
#: model:quality.point.test_type,name:mrp_workorder.test_type_print_label
|
|
||||||
msgid "Print label"
|
|
||||||
msgstr "打印标签"
|
|
||||||
@@ -138,7 +138,7 @@ if env.user.has_group('mrp.group_mrp_workorder_dependencies'):
|
|||||||
<button name="openMenuPopup" t-att-disabled="isBlocked" class="btn btn-secondary o_workorder_icon_btn fa fa-bars" type="workorder_event" title="menu"/>
|
<button name="openMenuPopup" t-att-disabled="isBlocked" class="btn btn-secondary o_workorder_icon_btn fa fa-bars" type="workorder_event" title="menu"/>
|
||||||
<span groups="mrp_workorder.group_mrp_wo_tablet_timer">
|
<span groups="mrp_workorder.group_mrp_wo_tablet_timer">
|
||||||
<button name="button_pending" type="object" class="btn btn-secondary" attrs="{'invisible': ['|', ('is_user_working', '=', False), ('working_state', '=', 'blocked')]}" barcode_trigger="pause" string="PAUSE"/>
|
<button name="button_pending" type="object" class="btn btn-secondary" attrs="{'invisible': ['|', ('is_user_working', '=', False), ('working_state', '=', 'blocked')]}" barcode_trigger="pause" string="PAUSE"/>
|
||||||
<button name="button_start" type="object" class="btn btn-warning" attrs="{'invisible': ['|', '|', ('is_user_working', '=', True), ('working_state', '=', 'blocked'), ('state', '=', ('done','rework', 'cancel'))]}" barcode_trigger="pause" string="CONTINUE"/>
|
<button name="button_start" type="object" class="btn btn-warning" attrs="{'invisible': ['|', '|', ('is_user_working', '=', True), ('working_state', '=', 'blocked'), ('state', '=', ('done', 'cancel'))]}" barcode_trigger="pause" string="CONTINUE"/>
|
||||||
<button name="button_unblock" type="object" class="btn btn-secondary btn-danger o_unblock" attrs="{'invisible': [('working_state', '!=', 'blocked')]}">Unblock</button>
|
<button name="button_unblock" type="object" class="btn btn-secondary btn-danger o_unblock" attrs="{'invisible': [('working_state', '!=', 'blocked')]}">Unblock</button>
|
||||||
<field name="duration" widget="mrp_timer" class="ms-1" readonly="1"/>
|
<field name="duration" widget="mrp_timer" class="ms-1" readonly="1"/>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1050,13 +1050,3 @@ msgstr "工作中心故障"
|
|||||||
#: model:ir.model.fields,field_description:quality.field_quality_point_test_type__active
|
#: model:ir.model.fields,field_description:quality.field_quality_point_test_type__active
|
||||||
msgid "active"
|
msgid "active"
|
||||||
msgstr "有效"
|
msgstr "有效"
|
||||||
|
|
||||||
#. module: quality
|
|
||||||
#: model:quality.point.test_type,name:quality.test_type_instructions
|
|
||||||
msgid "Instructions"
|
|
||||||
msgstr "使用说明"
|
|
||||||
|
|
||||||
#. module: quality
|
|
||||||
#: model:quality.point.test_type,name:quality.test_type_picture
|
|
||||||
msgid "Take a Picture"
|
|
||||||
msgstr "照片"
|
|
||||||
@@ -15,7 +15,7 @@ class TestType(models.Model):
|
|||||||
_description = "Quality Control Test Type"
|
_description = "Quality Control Test Type"
|
||||||
|
|
||||||
# Used instead of selection field in order to hide a choice depending on the view.
|
# Used instead of selection field in order to hide a choice depending on the view.
|
||||||
name = fields.Char('Name', required=True,translate=True)
|
name = fields.Char('Name', required=True)
|
||||||
technical_name = fields.Char('Technical name', required=True)
|
technical_name = fields.Char('Technical name', required=True)
|
||||||
active = fields.Boolean('active', default=True)
|
active = fields.Boolean('active', default=True)
|
||||||
|
|
||||||
|
|||||||
@@ -1185,14 +1185,3 @@ msgstr "请先进行质量检查!"
|
|||||||
#: model_terms:ir.ui.view,arch_db:quality_control.quality_alert_team_view_form
|
#: model_terms:ir.ui.view,arch_db:quality_control.quality_alert_team_view_form
|
||||||
msgid "e.g. The QA Masters"
|
msgid "e.g. The QA Masters"
|
||||||
msgstr "例如:QA大师"
|
msgstr "例如:QA大师"
|
||||||
|
|
||||||
|
|
||||||
#. module: quality_control
|
|
||||||
#: model:quality.point.test_type,name:quality_control.test_type_passfail
|
|
||||||
msgid "Pass - Fail"
|
|
||||||
msgstr "通过-失败"
|
|
||||||
|
|
||||||
#. module: quality_control
|
|
||||||
#: model:quality.point.test_type,name:quality_control.test_type_measure
|
|
||||||
msgid "Measure"
|
|
||||||
msgstr "测量"
|
|
||||||
@@ -6,4 +6,3 @@ from . import stock_move
|
|||||||
from . import stock_move_line
|
from . import stock_move_line
|
||||||
from . import stock_picking
|
from . import stock_picking
|
||||||
from . import stock_lot
|
from . import stock_lot
|
||||||
from . import product_category
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
||||||
from math import sqrt
|
|
||||||
from dateutil.relativedelta import relativedelta
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import random
|
|
||||||
|
|
||||||
from odoo import api, models, fields, _
|
|
||||||
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_round
|
|
||||||
from odoo.osv.expression import OR
|
|
||||||
|
|
||||||
|
|
||||||
class ProductCategory(models.Model):
|
|
||||||
_inherit = 'product.category'
|
|
||||||
@api.model
|
|
||||||
def name_search(self, name='', args=None, operator='ilike', limit=100):
|
|
||||||
if args is None:
|
|
||||||
args = []
|
|
||||||
# 添加过滤条件,确保只返回名称为 'abc' 的记录
|
|
||||||
args += [('name', 'not in', ['Saleable', 'Expenses', 'Deliveries'])]
|
|
||||||
|
|
||||||
# 调用父类的 name_search 方法
|
|
||||||
return super(ProductCategory, self).name_search(name, args=args, operator=operator, limit=limit)
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def search(self, args, limit=100, offset=0, order=None, count=False):
|
|
||||||
# 添加过滤条件,确保只返回名称不在指定列表中的记录
|
|
||||||
args += [('name', 'not in', ['Saleable', 'Expenses', 'Deliveries'])]
|
|
||||||
|
|
||||||
# 调用父类的 search 方法
|
|
||||||
return super(ProductCategory, self).search(args, limit=limit, offset=offset, order=order, count=count)
|
|
||||||
@@ -7,7 +7,6 @@ from datetime import datetime
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
from odoo import api, models, fields, _
|
from odoo import api, models, fields, _
|
||||||
from odoo.api import depends
|
|
||||||
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_round
|
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_round
|
||||||
from odoo.osv.expression import OR
|
from odoo.osv.expression import OR
|
||||||
|
|
||||||
@@ -123,13 +122,7 @@ class QualityPoint(models.Model):
|
|||||||
|
|
||||||
class QualityCheck(models.Model):
|
class QualityCheck(models.Model):
|
||||||
_inherit = "quality.check"
|
_inherit = "quality.check"
|
||||||
part_name = fields.Char('零件名称', compute='_compute_part_name_number', readonly=True)
|
|
||||||
part_number = fields.Char('零件图号', compute='_compute_part_name_number', readonly=True)
|
|
||||||
@depends('product_id')
|
|
||||||
def _compute_part_name_number(self):
|
|
||||||
for record in self:
|
|
||||||
record.part_number = record.product_id.part_number
|
|
||||||
record.part_name = record.product_id.part_name
|
|
||||||
failure_message = fields.Html(related='point_id.failure_message', readonly=True)
|
failure_message = fields.Html(related='point_id.failure_message', readonly=True)
|
||||||
measure = fields.Float('Measure', default=0.0, digits='Quality Tests', tracking=True)
|
measure = fields.Float('Measure', default=0.0, digits='Quality Tests', tracking=True)
|
||||||
measure_success = fields.Selection([
|
measure_success = fields.Selection([
|
||||||
|
|||||||
@@ -203,7 +203,7 @@
|
|||||||
<record id="quality_alert_action_check" model="ir.actions.act_window">
|
<record id="quality_alert_action_check" model="ir.actions.act_window">
|
||||||
<field name="name">Quality Alerts</field>
|
<field name="name">Quality Alerts</field>
|
||||||
<field name="res_model">quality.alert</field>
|
<field name="res_model">quality.alert</field>
|
||||||
<field name="view_mode">tree,kanban,form,pivot,graph,calendar</field>
|
<field name="view_mode">kanban,tree,form,pivot,graph,calendar</field>
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
<p class="o_view_nocontent_smiling_face">
|
<p class="o_view_nocontent_smiling_face">
|
||||||
Create a new quality alert
|
Create a new quality alert
|
||||||
@@ -389,8 +389,6 @@
|
|||||||
<field name="name" decoration-bf="1"/>
|
<field name="name" decoration-bf="1"/>
|
||||||
<field name="measure_on" optional="show"/>
|
<field name="measure_on" optional="show"/>
|
||||||
<field name='product_id' optional="show"/>
|
<field name='product_id' optional="show"/>
|
||||||
<field name="part_name" optional="hide"/>
|
|
||||||
<field name='part_number' optional="show"/>
|
|
||||||
<field name="lot_id" invisible="context.get('show_lots_text')"/>
|
<field name="lot_id" invisible="context.get('show_lots_text')"/>
|
||||||
<field name="lot_name" invisible="not context.get('show_lots_text')"/>
|
<field name="lot_name" invisible="not context.get('show_lots_text')"/>
|
||||||
<field name="picking_id" optional="hide" string="Transfer"/>
|
<field name="picking_id" optional="hide" string="Transfer"/>
|
||||||
|
|||||||
@@ -394,30 +394,3 @@ class MachineToolCategory(models.Model):
|
|||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
category = fields.Selection([('shukong', u'数控'), ('putong', u'普通')], string=u'机床类别',
|
category = fields.Selection([('shukong', u'数控'), ('putong', u'普通')], string=u'机床类别',
|
||||||
default='shukong')
|
default='shukong')
|
||||||
|
|
||||||
|
|
||||||
class MachiningAccuracy(models.Model):
|
|
||||||
_name = 'sf.machining.accuracy'
|
|
||||||
_description = '加工精度'
|
|
||||||
name = fields.Char('一般公差', index=True)
|
|
||||||
standard_tolerance = fields.Char(string="标准公差")
|
|
||||||
sync_id = fields.Char('同步ID')
|
|
||||||
|
|
||||||
|
|
||||||
class ReSaleOrder(models.Model):
|
|
||||||
_inherit = 'sale.order'
|
|
||||||
|
|
||||||
person_of_delivery = fields.Char('收货人')
|
|
||||||
telephone_of_delivery = fields.Char('电话号码')
|
|
||||||
address_of_delivery = fields.Char('联系地址')
|
|
||||||
|
|
||||||
|
|
||||||
class EmbryoRedundancy(models.Model):
|
|
||||||
_name = "sf.embryo.redundancy"
|
|
||||||
|
|
||||||
code = fields.Char('编码', required=True)
|
|
||||||
name = fields.Char('名称', required=True)
|
|
||||||
long = fields.Float('长度(mm)', required=True)
|
|
||||||
width = fields.Float('宽度(mm)', required=True)
|
|
||||||
height = fields.Float('高度(mm)', required=True)
|
|
||||||
active = fields.Boolean('有效', default=True)
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class MrsMaterialModel(models.Model):
|
|||||||
finish_machining = fields.Float("精加工Vc(m/min)")
|
finish_machining = fields.Float("精加工Vc(m/min)")
|
||||||
remark = fields.Text("备注")
|
remark = fields.Text("备注")
|
||||||
gain_way = fields.Selection(
|
gain_way = fields.Selection(
|
||||||
[("自加工", "自加工"), ("外协", "委外加工"), ("采购", "采购")],
|
[("自加工", "自加工"), ("外协", "外协"), ("采购", "采购")],
|
||||||
default="", string="获取方式")
|
default="", string="获取方式")
|
||||||
supplier_ids = fields.One2many('sf.supplier.sort', 'materials_model_id', string='供应商')
|
supplier_ids = fields.One2many('sf.supplier.sort', 'materials_model_id', string='供应商')
|
||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
@@ -100,7 +100,6 @@ class MrsProductionProcess(models.Model):
|
|||||||
travel_day = fields.Float('路途天数/d')
|
travel_day = fields.Float('路途天数/d')
|
||||||
sequence = fields.Integer('排序')
|
sequence = fields.Integer('排序')
|
||||||
|
|
||||||
|
|
||||||
# class MrsProcessingTechnology(models.Model):
|
# class MrsProcessingTechnology(models.Model):
|
||||||
# _name = 'sf.processing.technology'
|
# _name = 'sf.processing.technology'
|
||||||
# _description = '加工工艺'
|
# _description = '加工工艺'
|
||||||
@@ -158,9 +157,7 @@ class MrsProductionProcessParameter(models.Model):
|
|||||||
for parameter in self:
|
for parameter in self:
|
||||||
if parameter.process_id:
|
if parameter.process_id:
|
||||||
name = parameter.process_id.name + '-' + parameter.name
|
name = parameter.process_id.name + '-' + parameter.name
|
||||||
else:
|
result.append((parameter.id, name))
|
||||||
name = parameter.name
|
|
||||||
result.append((parameter.id, name))
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# 获取表面工艺的获取方式
|
# 获取表面工艺的获取方式
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<record id="group_quality" model="res.groups">
|
<record id="group_quality" model="res.groups">
|
||||||
<field name="name">质检岗</field>
|
<field name="name">质检岗</field>
|
||||||
<field name="category_id" ref="base.module_category_manufacturing_quality"/>
|
<field name="category_id" ref="base.module_category_manufacturing_quality"/>
|
||||||
</record>
|
</record>
|
||||||
@@ -46,11 +46,6 @@
|
|||||||
<field name="category_id" ref="base.module_category_manufacturing_manufacturing"/>
|
<field name="category_id" ref="base.module_category_manufacturing_manufacturing"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="group_production_engineer" model="res.groups">
|
|
||||||
<field name="name">工艺工程师</field>
|
|
||||||
<field name="implied_ids" eval="[(4, ref('group_sf_mrp_user'))]"/>
|
|
||||||
<field name="category_id" ref="base.module_category_manufacturing_manufacturing"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record model="ir.module.category" id="module_category_plan">
|
<record model="ir.module.category" id="module_category_plan">
|
||||||
<field name="name">计划</field>
|
<field name="name">计划</field>
|
||||||
@@ -70,7 +65,7 @@
|
|||||||
<record id="group_plan_dispatch" model="res.groups">
|
<record id="group_plan_dispatch" model="res.groups">
|
||||||
<field name="name">计划调度岗</field>
|
<field name="name">计划调度岗</field>
|
||||||
<field name="category_id" ref="module_category_plan"/>
|
<field name="category_id" ref="module_category_plan"/>
|
||||||
<!-- <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/> -->
|
<!-- <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/> -->
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="group_plan_director" model="res.groups">
|
<record id="group_plan_director" model="res.groups">
|
||||||
|
|||||||
@@ -247,10 +247,3 @@ access_sf_cutting_tool_type_group_sf_stock_manager,sf_cutting_tool_type_group_sf
|
|||||||
access_sf_cutting_tool_material_group_plan_dispatch,sf_cutting_tool_material_group_plan_dispatch,model_sf_cutting_tool_material,sf_base.group_plan_dispatch,1,0,0,0
|
access_sf_cutting_tool_material_group_plan_dispatch,sf_cutting_tool_material_group_plan_dispatch,model_sf_cutting_tool_material,sf_base.group_plan_dispatch,1,0,0,0
|
||||||
access_sf_functional_cutting_tool_model_group_plan_dispatch,sf_functional_cutting_tool_model_group_plan_dispatch,model_sf_functional_cutting_tool_model,sf_base.group_plan_dispatch,1,0,0,0
|
access_sf_functional_cutting_tool_model_group_plan_dispatch,sf_functional_cutting_tool_model_group_plan_dispatch,model_sf_functional_cutting_tool_model,sf_base.group_plan_dispatch,1,0,0,0
|
||||||
access_sf_cutting_tool_type_group_plan_dispatch,sf_cutting_tool_type_group_plan_dispatch,model_sf_cutting_tool_type,sf_base.group_plan_dispatch,1,0,0,0
|
access_sf_cutting_tool_type_group_plan_dispatch,sf_cutting_tool_type_group_plan_dispatch,model_sf_cutting_tool_type,sf_base.group_plan_dispatch,1,0,0,0
|
||||||
|
|
||||||
|
|
||||||
access_sf_machining_accuracy,sf_machining_accuracy,model_sf_machining_accuracy,base.group_user,1,0,0,0
|
|
||||||
access_sf_machining_accuracy_admin,sf_machining_accuracy_admin,model_sf_machining_accuracy,base.group_system,1,0,0,0
|
|
||||||
|
|
||||||
access_sf_embryo_redundancy,sf_embryo_redundancy,model_sf_embryo_redundancy,base.group_user,1,0,0,0
|
|
||||||
access_sf_embryo_redundancy_admin,sf_embryo_redundancy_admin,model_sf_embryo_redundancy,base.group_system,1,0,0,0
|
|
||||||
|
|||||||
|
@@ -1,125 +0,0 @@
|
|||||||
// 获取表格数据
|
|
||||||
function getDomData() {
|
|
||||||
const dom = $('div[name=cutting_speed_ids]')
|
|
||||||
if (!dom.length) return
|
|
||||||
const table = dom.find('.o_list_table')
|
|
||||||
const thead = table.children('thead')
|
|
||||||
const tbody = table.children('tbody')
|
|
||||||
const tbody_child = tbody.children()
|
|
||||||
const hideTheadDom = thead.find('[data-name=process_capability]')
|
|
||||||
hideTheadDom.hide().next().hide()
|
|
||||||
hideTheadDom.before('<th customTh>精加工</th><th customTh>粗加工</th>')
|
|
||||||
tbody_child.each(function () {
|
|
||||||
const dom = $(this).children('[name=process_capability]')
|
|
||||||
if(!dom.length) return
|
|
||||||
dom.css('cssText', 'display: none!important').next().css('cssText', 'display: none!important')
|
|
||||||
const isCu = dom.text() == '粗加工' // 是否粗加工
|
|
||||||
const v = dom.next().text() // 切削速度
|
|
||||||
dom.after(`<td customSpeed="1" name="process_capability" is="精加工" val="${ v }">${!isCu ? v : ''}</td><td customSpeed="1" name="process_capability" is="粗加工" val="${ v }">${isCu ? v : ''}</td>`)
|
|
||||||
setListenClick()
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
handleTbody(tbody, newTableData, ΦList, table)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听点击
|
|
||||||
function setListenClick() {
|
|
||||||
$(document).click(function (e) {
|
|
||||||
if ($(e.target).attr('customSpeed')) {
|
|
||||||
const orginV = $('[customInput=1]').children('input').val()
|
|
||||||
$('[customInput=1]').parent().html(orginV)
|
|
||||||
const v = $(e.target).attr('val')
|
|
||||||
const is = $(e.target).attr('is')
|
|
||||||
$(e.target).html('')
|
|
||||||
const input = $('<div customInput="1" is="' + is + '" class="o_field_widget o_field_char"><input class="o_input" type="text" autocomplete="off" maxlength="20"></div>')
|
|
||||||
input.children('input').val(v)
|
|
||||||
$(e.target).append(input)
|
|
||||||
input.children('input').focus()
|
|
||||||
input.children('input').select()
|
|
||||||
} else if ($(e.target).attr('customInput')) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
const orginV = $('[customInput=1]').children('input').val()
|
|
||||||
$('[customInput=1]').parent().html(orginV)
|
|
||||||
const v = $(e.target).attr('val')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
$(document).off('change') // 防止重复绑定
|
|
||||||
$(document).on('change', '[customInput] input', async function () {
|
|
||||||
$(this).parents('td').attr('val', $(this).val())
|
|
||||||
$(this).parents('td').siblings('[customspeed]').attr('val', $(this).val())
|
|
||||||
var eve1 = new Event('change')
|
|
||||||
var eve2 = new Event('input')
|
|
||||||
var eve3 = new Event('click')
|
|
||||||
let patchSpeedDom = $(this).parents('td').siblings('[name=cutting_speed]')
|
|
||||||
let patchProcessDom = $(this).parents('td').siblings('[name=process_capability]')
|
|
||||||
$(this).parents('td').siblings('[customspeed]').text('') // 清空其他加工类型的数据
|
|
||||||
await timeOut(500)
|
|
||||||
patchProcessDom[0].dispatchEvent(eve3)
|
|
||||||
await timeOut(200)
|
|
||||||
const processVal = $(this).parent().attr('is')
|
|
||||||
patchProcessDom.find('select').val(`"${processVal}"`) // 设置源select的val为“加工类型 is”、
|
|
||||||
patchProcessDom.attr("data-tooltip", `${processVal}`)
|
|
||||||
patchProcessDom.find('select')[0].dispatchEvent(eve1)
|
|
||||||
|
|
||||||
patchSpeedDom[0].dispatchEvent(eve3)
|
|
||||||
await timeOut(200)
|
|
||||||
patchSpeedDom.find('input').val($(this).val())
|
|
||||||
await timeOut(50)
|
|
||||||
patchSpeedDom.find('input')[0].dispatchEvent(eve2)
|
|
||||||
patchSpeedDom.find('input')[0].dispatchEvent(eve1)
|
|
||||||
})
|
|
||||||
$(document).off('blur') // 防止重复绑定
|
|
||||||
$(document).on('blur', '[customInput] input', async function () {
|
|
||||||
if(!$(this).length) return
|
|
||||||
|
|
||||||
$(this).parents('td').siblings('[customspeed]').text('') // 清空其他加工类型的数据
|
|
||||||
let patchProcessDom = $(this).parents('td').siblings('[name=process_capability]')
|
|
||||||
try {
|
|
||||||
patchProcessDom[0].dispatchEvent(new Event('click'))
|
|
||||||
const processVal = $(this).parent().attr('is')
|
|
||||||
patchProcessDom.find('select').val(`"${processVal}"`) // 设置源select的val为“加工类型 is”、
|
|
||||||
patchProcessDom.attr("data-tooltip", `${processVal}`)
|
|
||||||
patchProcessDom.find('select')[0].dispatchEvent(new Event('change'))
|
|
||||||
} catch {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
function timeOut(time) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
setTimeout(() => {
|
|
||||||
resolve()
|
|
||||||
}, time)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function listenAdd() {
|
|
||||||
$('td.o_field_x2many_list_row_add a').click(async function () {
|
|
||||||
await timeOut(500)
|
|
||||||
const tr = $('.o_list_table').children('tbody').children('tr').eq(-2)
|
|
||||||
if(tr.children('td').eq(2).text() == '') {
|
|
||||||
const dom = tr.children('[name=process_capability]')
|
|
||||||
if(!dom.length) return
|
|
||||||
dom.css('cssText', 'display: none!important').next().css('cssText', 'display: none!important')
|
|
||||||
const isCu = dom.text() == '粗加工' // 是否粗加工
|
|
||||||
const v = dom.next().text() // 切削速度
|
|
||||||
dom.after(`<td customSpeed="1" name="process_capability" is="精加工" val="${ v }">${!isCu ? v : ''}</td><td customSpeed="1" name="process_capability" is="粗加工" val="${ v }">${isCu ? v : ''}</td>`)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function listenSave() {
|
|
||||||
$('.o_form_button_save').click( async function () {
|
|
||||||
await timeOut(1000)
|
|
||||||
if($(this).parent().next().length) return
|
|
||||||
$('th[customTh],td[cusomSpeed]').remove()
|
|
||||||
getDomData()
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
listenAdd()
|
|
||||||
listenSave()
|
|
||||||
getDomData()
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
// 因为表格可以拖动设置宽度,所以需要用js设置初始宽度
|
|
||||||
function setBasicParamTableWidth() {
|
|
||||||
// const _100px = 'th[data-name="cutting_blade_length"],th[data-name="cutting_blade_length"],th[data-name="name"],th[data-name="tip_handling_size"],th[data-name="cutting_depth_max"],th[data-name="diameter_inner_circle"],th[data-name="diameter_mounting_hole" ],th[data-name="radius_tip_re" ],th[data-name="is_chip_breaker"],th[data-name="chip_breaker_type_code"],th[data-name="blade_profile"]'
|
|
||||||
// const _65px = 'th[data-name="edge_angle"],th[data-name="relief_angle"],[data-name="total_length"],th[data-name="length"],th[data-name="thickness"],th[data-name="blade_number"]'
|
|
||||||
// const _80px = 'th[data-name="arbor_diameter"],th[data-name="head_height"],th[data-name="head_width"],th[data-name="head_length"],th[data-name="blade_diameter"],th[data-name="blade_length"] ,th[data-name="neck_length"] ,th[data-name="neck_diameter"] ,th[data-name="shank_diameter"],th[data-name="shank_length"],th[data-name="tip_diameter"],th[data-name="knife_tip_taper"],th[data-name="blade_helix_angle"] ,th[data-name="blade_width"],th[data-name="blade_depth"]'
|
|
||||||
// const _50px = 'th[data-name="pitch"],th[data-name="width"],th[data-name="height"]'
|
|
||||||
|
|
||||||
const basicParamDom = $('.fixTableCss')
|
|
||||||
// const basicParamDom_100px = basicParamDom.find(_100px) // 四字以上
|
|
||||||
// const basicParamDom_65px = basicParamDom.find(_65px) // 大概三个字加单位
|
|
||||||
// const basicParamDom_80px = basicParamDom.find(_80px) // 大概四个字加单位
|
|
||||||
// const basicParamDom_50px= basicParamDom.find(_50px) // 大概两个字加单位
|
|
||||||
//
|
|
||||||
// basicParamDom_100px.css({'width': '100px', 'max-width': 'auto', ',min-width': 'auto'})
|
|
||||||
// basicParamDom_65px.css({'width': '65px', 'max-width': 'auto', ',min-width': 'auto'})
|
|
||||||
// basicParamDom_80px.css({'width': '80px', 'max-width': 'auto', ',min-width': 'auto'})
|
|
||||||
// basicParamDom_50px.css({'width': '50px', 'max-width': 'auto', ',min-width': 'auto'})
|
|
||||||
let dom = []
|
|
||||||
try {
|
|
||||||
dom = basicParamDom.find('table').find('thead').children().children()
|
|
||||||
|
|
||||||
} catch {
|
|
||||||
dom = []
|
|
||||||
}
|
|
||||||
if (!dom) return
|
|
||||||
dom.each(function () {
|
|
||||||
if ($(this).hasClass('row_no') >= 0) { // 序号列
|
|
||||||
// 不设置 通过css设置
|
|
||||||
}
|
|
||||||
const text = $(this).text().split('(')
|
|
||||||
if ($(this).attr('data-name') == 'name' || text[0].length > 4) {
|
|
||||||
$(this).width('100px')
|
|
||||||
} else if(text[0].length == 4){
|
|
||||||
$(this).width('80px')
|
|
||||||
} else if(text[0].length == 3){
|
|
||||||
$(this).width('65px')
|
|
||||||
} else if(text[0].length == 2){
|
|
||||||
$(this).width('50px')
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
setBasicParamTableWidth()
|
|
||||||
$('.o_field_many2one_selection').on('click', $('#cutting_tool_material_id + ul'), function () {
|
|
||||||
setTimeout(setBasicParamTableWidth, 500)
|
|
||||||
})
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
// 获取表格数据
|
|
||||||
function getDomData() {
|
|
||||||
const dom = $('#updateTable').prev()
|
|
||||||
if (!dom.length) return
|
|
||||||
const table = $('#updateTable').prev().find('.o_list_table')
|
|
||||||
const customTable = table.clone()
|
|
||||||
customTable.addClass('customTable')
|
|
||||||
table.parent().append(customTable)
|
|
||||||
table.hide()
|
|
||||||
const thead = customTable.children('thead')
|
|
||||||
const tbody = customTable.children('tbody')
|
|
||||||
const tableData = []
|
|
||||||
const tbody_child = tbody.children()
|
|
||||||
|
|
||||||
const tbody_child_len = tbody_child.length
|
|
||||||
|
|
||||||
for (let v = 0; v < tbody_child_len; v++) { // 将数据取出来到tableData里面
|
|
||||||
const data = tbody_child[v].innerText.split('\t')
|
|
||||||
// console.log('dom data',data)
|
|
||||||
const [index, deep, name, Φ, value] = data
|
|
||||||
tableData.push({index, deep, name, Φ, value})
|
|
||||||
}
|
|
||||||
const ΦList = [...new Set(tableData.map(_ => _.name))] // ΦList去重
|
|
||||||
const newTableData = {}
|
|
||||||
tableData.forEach(_ => {
|
|
||||||
const key = _.deep + '|' + _.Φ
|
|
||||||
!newTableData[key] ? newTableData[key] = {i: _.index} : '';
|
|
||||||
if (_.Φ) { // 去除没有Φ的脏数据
|
|
||||||
newTableData[key]['Φ' + _.Φ] = _.value
|
|
||||||
newTableData[key]['Φ' + _.Φ + 'i'] = _.index
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// console.log('qwdh',tableData, ΦList, newTableData);
|
|
||||||
|
|
||||||
if (ΦList.filter(_ => _).length == 0) return;
|
|
||||||
handleThead(thead, ΦList)
|
|
||||||
|
|
||||||
handleTbody(tbody, newTableData, ΦList, table)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新设置表头、
|
|
||||||
function handleThead(thead, ΦList) {
|
|
||||||
const dom = thead.children().eq(0).children()
|
|
||||||
const len = dom.length
|
|
||||||
dom.eq(0).attr('rowspan', 2)
|
|
||||||
dom.eq(1).attr('rowspan', 2)
|
|
||||||
len == 5 ? dom.eq(2).attr('rowspan', 2) : ''
|
|
||||||
dom.eq(-2).attr('colspan', ΦList.length)
|
|
||||||
dom.eq(-1).remove()
|
|
||||||
|
|
||||||
const tr = document.createElement('tr')
|
|
||||||
for (let v = 0; v < ΦList.length; v++) {
|
|
||||||
const th = document.createElement('th')
|
|
||||||
th.innerText = 'Φ' + ΦList[v]
|
|
||||||
tr.append(th)
|
|
||||||
}
|
|
||||||
thead.append(tr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新设置表格
|
|
||||||
function handleTbody(tbody, newTableData, ΦList, table) {
|
|
||||||
console.log(newTableData)
|
|
||||||
tbody.html('')
|
|
||||||
let i = 0
|
|
||||||
const data = Object.keys(newTableData)
|
|
||||||
// data.sort((a, b) => {
|
|
||||||
// a = a.split('=')[1].split('%')[0]
|
|
||||||
// b = b.split('=')[1].split('%')[0]
|
|
||||||
// return a - b
|
|
||||||
// })
|
|
||||||
// console.log('wqoqw ',ΦList)
|
|
||||||
data.forEach(_ => {
|
|
||||||
i++
|
|
||||||
const tr = $('<tr class="o_data_row"></tr>')
|
|
||||||
const td0 = $('<td></td>')
|
|
||||||
td0.text(i)
|
|
||||||
tr.append(td0)
|
|
||||||
const lit = _.split('|')
|
|
||||||
//
|
|
||||||
const td1 = $('<td></td>')
|
|
||||||
const td2 = $('<td></td>')
|
|
||||||
td1.text(lit[0])
|
|
||||||
td2.text(lit[1] || '')
|
|
||||||
tr.append(td1)
|
|
||||||
tr.append(td2)
|
|
||||||
ΦList.forEach(Φ => {
|
|
||||||
const td = $('<td class="o_data_cell cursor-pointer o_field_cell o_list_char"></td>')
|
|
||||||
td.text(newTableData[_]['Φ' + Φ])
|
|
||||||
td.attr('col', newTableData[_]['Φ' + Φ + 'i'])
|
|
||||||
td.attr('val', newTableData[_]['Φ' + Φ])
|
|
||||||
td.attr('coustomTd', 1)
|
|
||||||
tr.append(td)
|
|
||||||
})
|
|
||||||
// // for (let j = 0; j < ΦList.length; j++) {
|
|
||||||
// // const td = document.createElement('td')
|
|
||||||
// // td.innerText = newTableData[data[v]][_]
|
|
||||||
// // th.append(td)
|
|
||||||
// // }
|
|
||||||
tbody.append(tr)
|
|
||||||
})
|
|
||||||
// $(document).click(function (e) {
|
|
||||||
// if ($(e.target).attr('coustomTd')) {
|
|
||||||
// const orginV = $('[coustomInput=1]').children('input').val()
|
|
||||||
// $('[coustomInput=1]').parent().html(orginV)
|
|
||||||
// const v = $(e.target).attr('val')
|
|
||||||
// console.log($(e.target));
|
|
||||||
// $(e.target).html('')
|
|
||||||
// const input = $('<div coustomInput="1" name="feed_per_tooth" class="o_field_widget o_field_char"><input class="o_input" type="text" autocomplete="off" maxlength="20"></div>')
|
|
||||||
// input.children('input').val(v)
|
|
||||||
// $(e.target).append(input)
|
|
||||||
// input.children('input').focus()
|
|
||||||
// input.children('input').select()
|
|
||||||
// } else if ($(e.target).attr('coustomInput')) {
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// const orginV = $('[coustomInput=1]').children('input').val()
|
|
||||||
// $('[coustomInput=1]').parent().html(orginV)
|
|
||||||
// const v = $(e.target).attr('val')
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// $(document).off('change') // 防止重复绑定
|
|
||||||
// $(document).on('change', '[coustomInput] input', function () {
|
|
||||||
// $(this).parents('td').attr('val', $(this).val());
|
|
||||||
// var eve1 = new Event('change');
|
|
||||||
// var eve2 = new Event('input');
|
|
||||||
// var eve3 = new Event('click');
|
|
||||||
// const i = $(this).parents('td').attr('col');
|
|
||||||
// let patchDom = table.find('tbody').children('tr').eq(i - 1);
|
|
||||||
//
|
|
||||||
// if (patchDom.length === 0) {
|
|
||||||
// console.error('No such row found');
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// patchDom = patchDom.children().eq(-1);
|
|
||||||
//
|
|
||||||
// setTimeout(() => {
|
|
||||||
// if (patchDom.length === 0) {
|
|
||||||
// console.error('No such cell found');
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// patchDom[0].dispatchEvent(eve3); // Simulate click event
|
|
||||||
//
|
|
||||||
// setTimeout(() => {
|
|
||||||
// patchDom = patchDom.find('input');
|
|
||||||
// if (patchDom.length === 0) {
|
|
||||||
// console.error('No input found in the target cell');
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// patchDom.val($(this).val());
|
|
||||||
// patchDom[0].dispatchEvent(eve2);
|
|
||||||
// patchDom[0].dispatchEvent(eve1);
|
|
||||||
// }, 200);
|
|
||||||
// }, 500);
|
|
||||||
// });
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
getDomData()
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
.o_list_renderer .o_list_table tbody > tr > td:not(.o_list_record_selector):not(.o_handle_cell):not(.o_list_button):not(.o_list_record_remove) {
|
|
||||||
white-space: nowrap !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-truncate {
|
|
||||||
overflow: unset !important;
|
|
||||||
text-overflow: unset !important;
|
|
||||||
white-space: unset !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 设置表格不超出页面宽度
|
|
||||||
.o_form_view .o_field_widget .o_list_renderer {
|
|
||||||
width: calc(100% - 64px) !important;
|
|
||||||
margin:0 auto;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表格针对处理
|
|
||||||
.fixTableCss {
|
|
||||||
text-align: center;
|
|
||||||
.o_list_number_th,.o_list_number {
|
|
||||||
text-align: center!important;
|
|
||||||
}
|
|
||||||
.ui-sortable {
|
|
||||||
tr > td:first-child {
|
|
||||||
padding: 0!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.row_no {
|
|
||||||
padding: 0!important;;
|
|
||||||
width: 35px!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
th[data-name="total_length"],th[data-name="length"],th[data-name="thickness"] {
|
|
||||||
.flex-row-reverse {
|
|
||||||
span {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 其他不能用js处理的表格
|
|
||||||
.otherTableFix {
|
|
||||||
th[data-name="cutting_tool_material_id"] {
|
|
||||||
width: 100px!important;
|
|
||||||
}
|
|
||||||
th[data-name="ramping_angle_max"],th[data-name="ramping_angle_min"] {
|
|
||||||
width: 200px!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
.img-fluid {
|
.img-fluid {
|
||||||
max-width: unset !important;
|
max-width: unset !important;
|
||||||
width: 40px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.o_inner_group .img-fluid {
|
.o_inner_group .img-fluid {
|
||||||
|
|||||||
@@ -614,45 +614,4 @@
|
|||||||
<field name="res_model">sf.machine.control_system</field>
|
<field name="res_model">sf.machine.control_system</field>
|
||||||
<field name="view_mode">tree</field>
|
<field name="view_mode">tree</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
#------------------加工精度------------------
|
|
||||||
<record model="ir.ui.view" id="tree_sf_machining_accuracy_view">
|
|
||||||
<field name="name">tree.sf.machining.accuracy</field>
|
|
||||||
<field name="model">sf.machining.accuracy</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<tree string="加工精度" create="0" edit="0" delete="0">
|
|
||||||
<field name="name"/>
|
|
||||||
<field name="standard_tolerance"/>
|
|
||||||
</tree>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="action_sf_machining_accuracy" model="ir.actions.act_window">
|
|
||||||
<field name="name">加工精度</field>
|
|
||||||
<field name="type">ir.actions.act_window</field>
|
|
||||||
<field name="res_model">sf.machining.accuracy</field>
|
|
||||||
<field name="view_mode">tree</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
#------------------坯料冗余量------------------
|
|
||||||
<record model="ir.ui.view" id="tree_sf_embryo_redundancy_view">
|
|
||||||
<field name="name">tree.sf.embryo.redundancy</field>
|
|
||||||
<field name="model">sf.embryo.redundancy</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<tree string="坯料冗余量" create="0" edit="0" delete="0">
|
|
||||||
<field name="name"/>
|
|
||||||
<field name="code"/>
|
|
||||||
<field name="long"/>
|
|
||||||
<field name="width"/>
|
|
||||||
<field name="height"/>
|
|
||||||
</tree>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="action_sf_embryo_redundancy" model="ir.actions.act_window">
|
|
||||||
<field name="name">坯料冗余量</field>
|
|
||||||
<field name="type">ir.actions.act_window</field>
|
|
||||||
<field name="res_model">sf.embryo.redundancy</field>
|
|
||||||
<field name="view_mode">tree</field>
|
|
||||||
</record>
|
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -141,25 +141,12 @@
|
|||||||
sequence="1"
|
sequence="1"
|
||||||
action="action_sf_machine_brand"/>
|
action="action_sf_machine_brand"/>
|
||||||
|
|
||||||
<menuitem
|
|
||||||
id="menu_sf_embryo_redundancy"
|
|
||||||
parent="menu_sf_base"
|
|
||||||
name="坯料冗余"
|
|
||||||
sequence="2"
|
|
||||||
action="action_sf_embryo_redundancy"/>
|
|
||||||
|
|
||||||
<menuitem
|
|
||||||
id="menu_sf_machining_accuracy"
|
|
||||||
parent="menu_sf_base"
|
|
||||||
name="加工精度"
|
|
||||||
sequence="3"
|
|
||||||
action="action_sf_machining_accuracy"/>
|
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
id="menu_sf_machine_control_system"
|
id="menu_sf_machine_control_system"
|
||||||
parent="menu_sf_base"
|
parent="menu_sf_base"
|
||||||
name="数控系统"
|
name="数控系统"
|
||||||
sequence="4"
|
sequence="1"
|
||||||
action="action_sf_machine_control_system"/>
|
action="action_sf_machine_control_system"/>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -360,7 +360,6 @@
|
|||||||
<field name="cooling_jacket"/>
|
<field name="cooling_jacket"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
<script src="/sf_base/static/js/setTableWidth.js?time=3"></script>
|
|
||||||
</page>
|
</page>
|
||||||
<page string="切削速度Vc"
|
<page string="切削速度Vc"
|
||||||
attrs="{'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))]}">
|
attrs="{'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))]}">
|
||||||
@@ -381,9 +380,6 @@
|
|||||||
<field name="cutting_speed"/>
|
<field name="cutting_speed"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
<script src="/sf_base/static/js/customTable.js?time=3"></script>
|
|
||||||
<script src="/sf_base/static/js/setTableWidth.js?time=3"></script>
|
|
||||||
|
|
||||||
</page>
|
</page>
|
||||||
<page string="每齿走刀量fz"
|
<page string="每齿走刀量fz"
|
||||||
attrs="{'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))]}">
|
attrs="{'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))]}">
|
||||||
@@ -396,8 +392,6 @@
|
|||||||
<field name="feed_per_tooth"/>
|
<field name="feed_per_tooth"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
<div id="updateTable"></div>
|
|
||||||
<script src="/sf_base/static/js/updateTable.js?time=3"></script>
|
|
||||||
<field name="feed_per_tooth_ids_3"
|
<field name="feed_per_tooth_ids_3"
|
||||||
attrs="{'invisible': [('cutting_tool_type', 'not in', ('刀片'))]}">
|
attrs="{'invisible': [('cutting_tool_type', 'not in', ('刀片'))]}">
|
||||||
<tree editable="bottom" class="center" create="0" delete="0">
|
<tree editable="bottom" class="center" create="0" delete="0">
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
|
||||||
|
|
||||||
from odoo import http
|
from odoo import http
|
||||||
from odoo.http import request
|
from odoo.http import request
|
||||||
|
|
||||||
@@ -125,8 +123,7 @@ class Sf_Bf_Connect(http.Controller):
|
|||||||
res['factory_order_no'] = order_id.name
|
res['factory_order_no'] = order_id.name
|
||||||
return json.JSONEncoder().encode(res)
|
return json.JSONEncoder().encode(res)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
traceback_error = traceback.format_exc()
|
logging.info('get_bfm_process_order_list error:%s' % e)
|
||||||
logging.error('get_bfm_process_order_list error: %s' % traceback_error)
|
|
||||||
res['status'] = -1
|
res['status'] = -1
|
||||||
res['message'] = '工厂创建销售订单和产品失败,请联系管理员'
|
res['message'] = '工厂创建销售订单和产品失败,请联系管理员'
|
||||||
request.cr.rollback()
|
request.cr.rollback()
|
||||||
|
|||||||
@@ -151,12 +151,6 @@ class JdEclp(models.Model):
|
|||||||
_logger.info('准备调接口1')
|
_logger.info('准备调接口1')
|
||||||
url1 = config['bfm_url_new'] + '/api/create/jd/order'
|
url1 = config['bfm_url_new'] + '/api/create/jd/order'
|
||||||
requests.post(url1, json=json1, data=None)
|
requests.post(url1, json=json1, data=None)
|
||||||
# ===============修改销售订单状态为【物流中】===================
|
|
||||||
item = self.env['sale.order'].sudo().search([('name', '=', self.origin)])
|
|
||||||
if not item:
|
|
||||||
raise ValidationError('没有查询到订单号为【%s】的销售订单!' % self.origin)
|
|
||||||
else:
|
|
||||||
item.write({'state': 'physical_distribution'})
|
|
||||||
_logger.info('调用成功1')
|
_logger.info('调用成功1')
|
||||||
_logger.info('准备调接口2')
|
_logger.info('准备调接口2')
|
||||||
json2 = {
|
json2 = {
|
||||||
|
|||||||
@@ -36,8 +36,6 @@ class StatusChange(models.Model):
|
|||||||
# 使用super()来调用原始方法(在本例中为'sale.order'模型的'action_confirm'方法)
|
# 使用super()来调用原始方法(在本例中为'sale.order'模型的'action_confirm'方法)
|
||||||
try:
|
try:
|
||||||
res = super(StatusChange, self).action_confirm()
|
res = super(StatusChange, self).action_confirm()
|
||||||
# 修改销售订单状态为【加工中】
|
|
||||||
self.write({'state': 'processing'})
|
|
||||||
logging.info('原生方法返回结果:%s' % res)
|
logging.info('原生方法返回结果:%s' % res)
|
||||||
# 原有方法执行后,进行额外的操作(如调用外部API)
|
# 原有方法执行后,进行额外的操作(如调用外部API)
|
||||||
process_start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
process_start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
<field name="inherit_id" ref="stock.view_picking_form"/>
|
<field name="inherit_id" ref="stock.view_picking_form"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//form//sheet//notebook//page[@name='operations']" position="after">
|
<xpath expr="//form//sheet//notebook//page[@name='operations']" position="after">
|
||||||
<page string="发货信息" name="tracking" attrs="{'invisible': [('picking_type_code', '!=', 'outgoing')]}">
|
<page string="发货信息" name="tracking">
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="senderNickName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
|
<field name="senderNickName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<data noupdate="1">
|
<data>
|
||||||
<record id="product_category_embryo_sf" model="product.category">
|
<record id="product_category_embryo_sf" model="product.category">
|
||||||
<field name="name">坯料</field>
|
<field name="name">坯料</field>
|
||||||
<field name="type">坯料</field>
|
<field name="type">坯料</field>
|
||||||
|
|||||||
@@ -1,3 +1 @@
|
|||||||
from . import product_supplierinfo
|
from . import product_supplierinfo
|
||||||
from . import stock_rule_inherit
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
import logging
|
|
||||||
from itertools import groupby
|
|
||||||
from odoo import models, fields, api, _
|
|
||||||
|
|
||||||
|
|
||||||
class StockRuleInherit(models.Model):
|
|
||||||
_inherit = 'stock.rule'
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _run_buy(self, procurements):
|
|
||||||
# 判断补货组的采购类型
|
|
||||||
procurements_group = {'standard': [], 'outsourcing': []}
|
|
||||||
for procurement, rule in procurements:
|
|
||||||
is_outsourcing = False
|
|
||||||
product = procurement.product_id
|
|
||||||
# 获取主 BOM
|
|
||||||
bom = self.env['mrp.bom'].search([('product_tmpl_id', '=', product.product_tmpl_id.id)], limit=1)
|
|
||||||
|
|
||||||
if bom:
|
|
||||||
# 遍历 BOM 中的组件(即坯料等)
|
|
||||||
for line in bom.bom_line_ids:
|
|
||||||
raw_material = line.product_id
|
|
||||||
# 检查路线
|
|
||||||
for route in raw_material.route_ids:
|
|
||||||
# print('route.name:', route.name)
|
|
||||||
if route.name == '按订单补给外包商':
|
|
||||||
is_outsourcing = True
|
|
||||||
|
|
||||||
if is_outsourcing:
|
|
||||||
procurements_group['outsourcing'].append((procurement, rule))
|
|
||||||
else:
|
|
||||||
procurements_group['standard'].append((procurement, rule))
|
|
||||||
|
|
||||||
for key, value in procurements_group.items():
|
|
||||||
super(StockRuleInherit, self)._run_buy(value)
|
|
||||||
|
|
||||||
if key == 'outsourcing':
|
|
||||||
for procurement, rule in value:
|
|
||||||
supplier = procurement.values.get('supplier')
|
|
||||||
if supplier:
|
|
||||||
domain = rule._make_po_get_domain(procurement.company_id, procurement.values,
|
|
||||||
supplier.partner_id)
|
|
||||||
logging.info("domain=============: %s", domain)
|
|
||||||
po = self.env['purchase.order'].sudo().search([
|
|
||||||
('partner_id', '=', supplier.partner_id.id),
|
|
||||||
('company_id', '=', procurement.company_id.id), # 保证公司一致
|
|
||||||
('origin', 'like', procurement.origin), # 根据来源匹配
|
|
||||||
('state', '=', 'draft') # 状态为草稿
|
|
||||||
], limit=1)
|
|
||||||
logging.info("po=: %s", po)
|
|
||||||
if po:
|
|
||||||
po.write({'purchase_type': 'outsourcing'})
|
|
||||||
|
|
||||||
# # 首先调用父类的 _run_buy 方法,以保留原有逻辑
|
|
||||||
# super(StockRuleInherit, self)._run_buy(procurements)
|
|
||||||
|
|
||||||
# 然后在这里添加自定义的逻辑
|
|
||||||
# for procurement, rule in procurements:
|
|
||||||
# product = procurement.product_id
|
|
||||||
# # 获取主 BOM
|
|
||||||
# bom = self.env['mrp.bom'].search([('product_tmpl_id', '=', product.product_tmpl_id.id)], limit=1)
|
|
||||||
|
|
||||||
# if bom:
|
|
||||||
# # 遍历 BOM 中的组件(即坯料等)
|
|
||||||
# for line in bom.bom_line_ids:
|
|
||||||
# raw_material = line.product_id
|
|
||||||
# # 检查路线
|
|
||||||
# for route in raw_material.route_ids:
|
|
||||||
# # print('route.name:', route.name)
|
|
||||||
# if route.name == '按订单补给外包商': # 或者用 route.id 检查精确的路线
|
|
||||||
# print("按订单补给外包商============是")
|
|
||||||
# # 使用 procurement.values['supplier'] 获取供应商
|
|
||||||
# supplier = procurement.values.get('supplier')
|
|
||||||
# if supplier:
|
|
||||||
# domain = rule._make_po_get_domain(procurement.company_id, procurement.values,
|
|
||||||
# supplier.partner_id)
|
|
||||||
# logging.info("domain=============: %s", domain)
|
|
||||||
# po = self.env['purchase.order'].sudo().search([
|
|
||||||
# ('partner_id', '=', supplier.partner_id.id),
|
|
||||||
# ('company_id', '=', procurement.company_id.id), # 保证公司一致
|
|
||||||
# ('origin', '=', procurement.origin), # 根据来源匹配
|
|
||||||
# ('state', '=', 'draft') # 状态为草稿
|
|
||||||
# ], limit=1)
|
|
||||||
# logging.info("po=: %s", po)
|
|
||||||
# if po:
|
|
||||||
# po.write({'purchase_type': 'outsourcing'})
|
|
||||||
# break
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
""",
|
""",
|
||||||
'category': 'sf',
|
'category': 'sf',
|
||||||
'website': 'https://www.sf.jikimo.com',
|
'website': 'https://www.sf.jikimo.com',
|
||||||
'depends': ['sf_sale', 'sf_dlm', 'sf_manufacturing','jikimo_attachment_viewer'],
|
'depends': ['sf_sale', 'sf_dlm', 'sf_manufacturing'],
|
||||||
'data': [
|
'data': [
|
||||||
'data/stock_data.xml',
|
'data/stock_data.xml',
|
||||||
'views/product_template_management_view.xml',
|
'views/product_template_management_view.xml',
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<record id="mrp.product_template_action" model="ir.actions.act_window">
|
<record id="mrp.product_template_action" model="ir.actions.act_window">
|
||||||
<field name="view_mode">tree,kanban,form,activity</field>
|
|
||||||
<field name="context">
|
<field name="context">
|
||||||
{"search_default_categ_id":1,"search_default_consumable": 1, 'default_detailed_type': 'product'}
|
{"search_default_categ_id":1,"search_default_consumable": 1, 'default_detailed_type': 'product'}
|
||||||
</field>
|
</field>
|
||||||
@@ -16,10 +15,10 @@
|
|||||||
<field name='categ_id' class="custom_required" attrs="{'readonly': [('id', '!=', False)]}"/>
|
<field name='categ_id' class="custom_required" attrs="{'readonly': [('id', '!=', False)]}"/>
|
||||||
<field name='is_bfm' invisible="1"/>
|
<field name='is_bfm' invisible="1"/>
|
||||||
<field name='categ_type' invisible="1"/>
|
<field name='categ_type' invisible="1"/>
|
||||||
<field name='part_name' attrs="{'invisible': [('categ_type', '!=', '成品')]}"/>
|
|
||||||
<field name='part_number' attrs="{'invisible': [('categ_type', '!=', '成品')]}"/>
|
<field name='part_number' attrs="{'invisible': [('categ_type', '!=', '成品')]}"/>
|
||||||
|
<field name='machining_drawings' attrs="{'invisible': [('categ_type', '!=', '成品')]}" widget="adaptive_viewer"/>
|
||||||
|
<field name='quality_standard' attrs="{'invisible': [('categ_type', '!=', '成品')]}" widget="adaptive_viewer"/>
|
||||||
<field name='manual_quotation' attrs="{'invisible':[('upload_model_file', '=', [])]}"/>
|
<field name='manual_quotation' attrs="{'invisible':[('upload_model_file', '=', [])]}"/>
|
||||||
<field name="is_customer_provided" attrs="{'invisible': [('categ_type', 'not in', ['成品', '坯料'])], 'readonly': True}" />
|
|
||||||
<field name="upload_model_file"
|
<field name="upload_model_file"
|
||||||
widget="many2many_binary"
|
widget="many2many_binary"
|
||||||
attrs="{'invisible': ['|', '|',('categ_type', '!=', '成品'),('categ_type', '=', False),('is_bfm','=', True)]}"/>
|
attrs="{'invisible': ['|', '|',('categ_type', '!=', '成品'),('categ_type', '=', False),('is_bfm','=', True)]}"/>
|
||||||
@@ -66,9 +65,6 @@
|
|||||||
attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}"
|
attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}"
|
||||||
domain="[('fixture_model_id','=',fixture_model_id)]"/>
|
domain="[('fixture_model_id','=',fixture_model_id)]"/>
|
||||||
</field>
|
</field>
|
||||||
<xpath expr="//field[@name='uom_id']" position="before">
|
|
||||||
<field name="is_manual_processing" attrs="{'invisible': [('categ_type', 'not in', ['成品', '坯料'])], 'readonly': True}" />
|
|
||||||
</xpath>
|
|
||||||
<xpath expr="//label[@for='volume']" position="before">
|
<xpath expr="//label[@for='volume']" position="before">
|
||||||
<label for="length" string="尺寸"
|
<label for="length" string="尺寸"
|
||||||
attrs="{'invisible':[('product_variant_count', '>', 1), ('is_product_variant', '=', False)]}"/>
|
attrs="{'invisible':[('product_variant_count', '>', 1), ('is_product_variant', '=', False)]}"/>
|
||||||
@@ -115,17 +111,6 @@
|
|||||||
'刀具')], 'required': True}
|
'刀具')], 'required': True}
|
||||||
</attribute>
|
</attribute>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//sheet//notebook" position="inside">
|
|
||||||
<page string="2D加工图纸" attrs="{'invisible': [('categ_type', 'not in', ['成品', '坯料'])]}">
|
|
||||||
<field name='machining_drawings' widget="adaptive_viewer"/>
|
|
||||||
</page>
|
|
||||||
</xpath>
|
|
||||||
<xpath expr="//sheet//notebook" position="inside">
|
|
||||||
<page string="质检标准" attrs="{'invisible': [('categ_type', 'not in', ['成品', '坯料'])]}">
|
|
||||||
<field name='quality_standard' widget="adaptive_viewer"/>
|
|
||||||
|
|
||||||
</page>
|
|
||||||
</xpath>
|
|
||||||
<!-- <xpath expr="//field[@name='default_code']" position="attributes">-->
|
<!-- <xpath expr="//field[@name='default_code']" position="attributes">-->
|
||||||
<!-- <attribute name="attrs">{'readonly': [('categ_type', '=', '刀具')], 'invisible':-->
|
<!-- <attribute name="attrs">{'readonly': [('categ_type', '=', '刀具')], 'invisible':-->
|
||||||
<!-- [('product_variant_count', '>' , 1)]}-->
|
<!-- [('product_variant_count', '>' , 1)]}-->
|
||||||
|
|||||||
@@ -2,4 +2,3 @@
|
|||||||
|
|
||||||
from . import hr_employee
|
from . import hr_employee
|
||||||
from . import res_config_setting
|
from . import res_config_setting
|
||||||
from . import res_users
|
|
||||||
|
|||||||
@@ -11,52 +11,6 @@ class JkmPracticeEmployee(models.Model):
|
|||||||
|
|
||||||
we_id = fields.Char(string='企微ID', index=True)
|
we_id = fields.Char(string='企微ID', index=True)
|
||||||
|
|
||||||
@api.model_create_multi
|
|
||||||
def create(self, vals_list):
|
|
||||||
for val in vals_list:
|
|
||||||
if 'work_email' in val:
|
|
||||||
val["we_id"] = self._get_we_id(val.get('work_email'))
|
|
||||||
return super(JkmPracticeEmployee, self).create(vals_list)
|
|
||||||
|
|
||||||
def write(self, vals):
|
|
||||||
if 'work_email' in vals:
|
|
||||||
vals["we_id"] = self._get_we_id(vals.get('work_email'))
|
|
||||||
return super(JkmPracticeEmployee, self).write(vals)
|
|
||||||
|
|
||||||
def unlink(self):
|
|
||||||
for record in self:
|
|
||||||
res_partner_obj = record.env['res.partner'].sudo().search([('email', '=', record.work_email)])
|
|
||||||
if res_partner_obj:
|
|
||||||
res_partner_obj.unlink()
|
|
||||||
res = super(JkmPracticeEmployee, self).unlink()
|
|
||||||
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
@api.depends('work_contact_id', 'work_contact_id.mobile', 'work_contact_id.email')
|
|
||||||
def _compute_work_contact_details(self):
|
|
||||||
for employee in self:
|
|
||||||
if employee.work_contact_id:
|
|
||||||
employee.mobile_phone = employee.work_contact_id.mobile
|
|
||||||
employee.work_email = employee.work_contact_id.email
|
|
||||||
if employee.work_contact_id.email:
|
|
||||||
employee.we_id = self._get_we_id(employee.work_contact_id.email)
|
|
||||||
|
|
||||||
def _get_we_id(self, work_email):
|
|
||||||
json1 = {
|
|
||||||
'params': {
|
|
||||||
'work_email': work_email
|
|
||||||
}
|
|
||||||
}
|
|
||||||
url = '/api/get/we_id/info'
|
|
||||||
config = self.env['res.config.settings'].get_values()
|
|
||||||
ret = requests.post((config['ims_url'] + url), json=json1, data={})
|
|
||||||
result = ret.json()['result']
|
|
||||||
if result['code'] == 200:
|
|
||||||
if result['we_id']:
|
|
||||||
return result['we_id']
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _employee_info_sync(self):
|
def _employee_info_sync(self):
|
||||||
url = '/api/get/organization'
|
url = '/api/get/organization'
|
||||||
config = self.env['res.config.settings'].get_values()
|
config = self.env['res.config.settings'].get_values()
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
import random
|
|
||||||
from odoo import models, fields, api
|
|
||||||
from odoo.http import request
|
|
||||||
from odoo.exceptions import AccessDenied
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class ResUsers(models.Model):
|
|
||||||
_inherit = 'res.users'
|
|
||||||
|
|
||||||
we_employee_id = fields.Char(string=u'企业微信账号', related='employee_id.we_id', default="")
|
|
||||||
@@ -1264,7 +1264,6 @@ class Sf_Dashboard_Connect(http.Controller):
|
|||||||
"""
|
"""
|
||||||
获取
|
获取
|
||||||
"""
|
"""
|
||||||
logging.info("kw=============:%s" % kw)
|
|
||||||
res = {'status': 1, 'message': '成功', 'data': {}}
|
res = {'status': 1, 'message': '成功', 'data': {}}
|
||||||
# 连接数据库
|
# 连接数据库
|
||||||
conn = psycopg2.connect(**db_config)
|
conn = psycopg2.connect(**db_config)
|
||||||
|
|||||||
@@ -10,9 +10,6 @@
|
|||||||
<searchpanel>
|
<searchpanel>
|
||||||
<field name="routing_type" select="multi" string="工序类型" icon="fa-building" enable_counters="1"/>
|
<field name="routing_type" select="multi" string="工序类型" icon="fa-building" enable_counters="1"/>
|
||||||
<field name="state" select="multi" string="状态" icon="fa-building" enable_counters="1"/>
|
<field name="state" select="multi" string="状态" icon="fa-building" enable_counters="1"/>
|
||||||
|
|
||||||
<field name="construction_period_status" select="multi" icon="fa-building" enable_counters="1"/>
|
|
||||||
<field name="tag_type" select="multi" icon="fa-building" enable_counters="1"/>
|
|
||||||
<!-- <field name="manual_quotation" select="multi" string="" icon="fa-building" enable_counters="1"/>-->
|
<!-- <field name="manual_quotation" select="multi" string="" icon="fa-building" enable_counters="1"/>-->
|
||||||
</searchpanel>
|
</searchpanel>
|
||||||
|
|
||||||
|
|||||||
@@ -2,4 +2,3 @@
|
|||||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
from . import wizard
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
'views/equipment_maintenance_standards_views.xml',
|
'views/equipment_maintenance_standards_views.xml',
|
||||||
'views/maintenance_request_views.xml',
|
'views/maintenance_request_views.xml',
|
||||||
'views/maintenance_equipment_category_views.xml',
|
'views/maintenance_equipment_category_views.xml',
|
||||||
'wizard/maintenance_request_wizard.xml',
|
|
||||||
],
|
],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
'application': False,
|
'application': False,
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import json
|
import json
|
||||||
import base64
|
import base64
|
||||||
import logging
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import requests
|
import requests
|
||||||
from odoo.addons.sf_base.commons.common import Common
|
from odoo.addons.sf_base.commons.common import Common
|
||||||
from odoo import api, fields, models, _
|
from odoo import api, fields, models, _
|
||||||
from odoo.exceptions import UserError, ValidationError
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
class SfMaintenanceEquipmentCategory(models.Model):
|
class SfMaintenanceEquipmentCategory(models.Model):
|
||||||
@@ -123,13 +122,6 @@ class SfMaintenanceEquipment(models.Model):
|
|||||||
'sf_maintenance_equipment_ids', string='设备维保标准')
|
'sf_maintenance_equipment_ids', string='设备维保标准')
|
||||||
eq_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备保养标准',
|
eq_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备保养标准',
|
||||||
domain="[('maintenance_type','=','保养')]")
|
domain="[('maintenance_type','=','保养')]")
|
||||||
|
|
||||||
initial_action_date = fields.Date(string='重置保养日期')
|
|
||||||
initial_action_date_old = fields.Date(string='重置保养日期(旧)')
|
|
||||||
next_action_date = fields.Date(string='下次预防保养')
|
|
||||||
|
|
||||||
initial_overhaul_date = fields.Date(string='重置维修日期')
|
|
||||||
initial_overhaul_date_old = fields.Date(string='重置维修日期(旧)')
|
|
||||||
overhaul_date = fields.Date(string='下次预防检修')
|
overhaul_date = fields.Date(string='下次预防检修')
|
||||||
overhaul_period = fields.Integer(string='预防检修频次')
|
overhaul_period = fields.Integer(string='预防检修频次')
|
||||||
overhaul_duration = fields.Float(string='检修时长')
|
overhaul_duration = fields.Float(string='检修时长')
|
||||||
@@ -137,61 +129,6 @@ class SfMaintenanceEquipment(models.Model):
|
|||||||
overhaul_id = fields.Many2one('equipment.maintenance.standards', string='设备检修标准',
|
overhaul_id = fields.Many2one('equipment.maintenance.standards', string='设备检修标准',
|
||||||
domain="[('maintenance_type','=','检修')]")
|
domain="[('maintenance_type','=','检修')]")
|
||||||
|
|
||||||
def confirm_maintenance(self):
|
|
||||||
"""
|
|
||||||
确认保养/检修
|
|
||||||
"""
|
|
||||||
context = self.env.context
|
|
||||||
if context['type'] == '保养':
|
|
||||||
if not self.initial_action_date:
|
|
||||||
raise ValidationError('重置保养日期不能为空!!')
|
|
||||||
elif self.initial_action_date < fields.Date.today():
|
|
||||||
raise ValidationError('重置保养日期不能小于当前日期!!')
|
|
||||||
elif context['type'] == '检修':
|
|
||||||
if not self.initial_overhaul_date:
|
|
||||||
raise ValidationError('重置检修日期不能为空!!')
|
|
||||||
elif self.initial_overhaul_date < fields.Date.today():
|
|
||||||
raise ValidationError('重置检修日期不能小于当前日期!!')
|
|
||||||
|
|
||||||
request_ids = self.env['maintenance.request'].search([('stage_id.done', '=', False),
|
|
||||||
('equipment_id', '=', self.id),
|
|
||||||
('maintenance_type', '=', 'preventive'),
|
|
||||||
('sf_maintenance_type', '=', context['type'])])
|
|
||||||
|
|
||||||
if not request_ids:
|
|
||||||
return self.create_maintenance_request(context['type'])
|
|
||||||
else:
|
|
||||||
return {
|
|
||||||
"type": "ir.actions.act_window",
|
|
||||||
"res_model": "maintenance.request.wizard",
|
|
||||||
"views": [[False, "form"]],
|
|
||||||
"target": "new",
|
|
||||||
'context': {
|
|
||||||
'equipment_id': self.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def create_maintenance_request(self, maintenance_request_type):
|
|
||||||
"""
|
|
||||||
根据条件创建维保计划
|
|
||||||
"""
|
|
||||||
if maintenance_request_type == '保养':
|
|
||||||
self._create_new_request(self.initial_action_date + timedelta(days=self.period))
|
|
||||||
self.initial_action_date_old = self.initial_action_date
|
|
||||||
elif maintenance_request_type == '检修':
|
|
||||||
self._create_new_request1(self.initial_overhaul_date + timedelta(days=self.overhaul_period))
|
|
||||||
self.initial_overhaul_date_old = self.initial_overhaul_date
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'display_notification',
|
|
||||||
'params': {
|
|
||||||
'title': f'创建{maintenance_request_type}计划',
|
|
||||||
'message': f'新{maintenance_request_type}维保计划创建成功',
|
|
||||||
'type': 'success',
|
|
||||||
'next': {'type': 'ir.actions.act_window_close'},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@api.onchange('eq_maintenance_id', 'overhaul_id')
|
@api.onchange('eq_maintenance_id', 'overhaul_id')
|
||||||
def _compute_equipment_maintenance_standards_ids(self):
|
def _compute_equipment_maintenance_standards_ids(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
@@ -654,13 +591,11 @@ class SfMaintenanceEquipment(models.Model):
|
|||||||
('equipment_id', '=', equipment.id),
|
('equipment_id', '=', equipment.id),
|
||||||
('sf_maintenance_type', '=', '保养'),
|
('sf_maintenance_type', '=', '保养'),
|
||||||
('stage_id.done', '!=', True),
|
('stage_id.done', '!=', True),
|
||||||
('active', '!=', False),
|
|
||||||
('close_date', '=', False)], order="request_date asc", limit=1)
|
('close_date', '=', False)], order="request_date asc", limit=1)
|
||||||
last_maintenance_done = self.env['maintenance.request'].search([
|
last_maintenance_done = self.env['maintenance.request'].search([
|
||||||
('equipment_id', '=', equipment.id),
|
('equipment_id', '=', equipment.id),
|
||||||
('sf_maintenance_type', '=', '保养'),
|
('sf_maintenance_type', '=', '保养'),
|
||||||
('stage_id.done', '=', True),
|
('stage_id.done', '=', True),
|
||||||
('active', '!=', False),
|
|
||||||
('close_date', '!=', False)], order="close_date desc", limit=1)
|
('close_date', '!=', False)], order="close_date desc", limit=1)
|
||||||
if next_maintenance_todo and last_maintenance_done:
|
if next_maintenance_todo and last_maintenance_done:
|
||||||
next_date = next_maintenance_todo.request_date
|
next_date = next_maintenance_todo.request_date
|
||||||
@@ -689,9 +624,7 @@ class SfMaintenanceEquipment(models.Model):
|
|||||||
if next_date < date_now:
|
if next_date < date_now:
|
||||||
next_date = date_now
|
next_date = date_now
|
||||||
else:
|
else:
|
||||||
if not equipment.initial_action_date:
|
next_date = equipment.effective_date + timedelta(days=equipment.period)
|
||||||
raise ValidationError('重置保养日期不能为空!!!')
|
|
||||||
next_date = equipment.initial_action_date + timedelta(days=equipment.period)
|
|
||||||
equipment.next_action_date = next_date
|
equipment.next_action_date = next_date
|
||||||
else:
|
else:
|
||||||
self.next_action_date = False
|
self.next_action_date = False
|
||||||
@@ -702,13 +635,11 @@ class SfMaintenanceEquipment(models.Model):
|
|||||||
('equipment_id', '=', equipment.id),
|
('equipment_id', '=', equipment.id),
|
||||||
('sf_maintenance_type', '=', '检修'),
|
('sf_maintenance_type', '=', '检修'),
|
||||||
('stage_id.done', '!=', True),
|
('stage_id.done', '!=', True),
|
||||||
('active', '!=', False),
|
|
||||||
('close_date', '=', False)], order="request_date asc", limit=1)
|
('close_date', '=', False)], order="request_date asc", limit=1)
|
||||||
last_maintenance_done = self.env['maintenance.request'].search([
|
last_maintenance_done = self.env['maintenance.request'].search([
|
||||||
('equipment_id', '=', equipment.id),
|
('equipment_id', '=', equipment.id),
|
||||||
('sf_maintenance_type', '=', '检修'),
|
('sf_maintenance_type', '=', '检修'),
|
||||||
('stage_id.done', '=', True),
|
('stage_id.done', '=', True),
|
||||||
('active', '!=', False),
|
|
||||||
('close_date', '!=', False)], order="close_date desc", limit=1)
|
('close_date', '!=', False)], order="close_date desc", limit=1)
|
||||||
if next_maintenance_todo and last_maintenance_done:
|
if next_maintenance_todo and last_maintenance_done:
|
||||||
next_date = next_maintenance_todo.request_date
|
next_date = next_maintenance_todo.request_date
|
||||||
@@ -737,9 +668,7 @@ class SfMaintenanceEquipment(models.Model):
|
|||||||
if next_date < date_now:
|
if next_date < date_now:
|
||||||
next_date = date_now
|
next_date = date_now
|
||||||
else:
|
else:
|
||||||
if not equipment.initial_overhaul_date:
|
next_date = equipment.effective_date + timedelta(days=equipment.overhaul_period)
|
||||||
raise ValidationError('重置维修日期不能为空')
|
|
||||||
next_date = equipment.initial_overhaul_date + timedelta(days=equipment.overhaul_period)
|
|
||||||
equipment.overhaul_date = next_date
|
equipment.overhaul_date = next_date
|
||||||
else:
|
else:
|
||||||
self.overhaul_date = False
|
self.overhaul_date = False
|
||||||
@@ -806,7 +735,6 @@ class SfMaintenanceEquipment(models.Model):
|
|||||||
next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False),
|
next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False),
|
||||||
('equipment_id', '=', equipment.id),
|
('equipment_id', '=', equipment.id),
|
||||||
('maintenance_type', '=', 'preventive'),
|
('maintenance_type', '=', 'preventive'),
|
||||||
('active', '=', True),
|
|
||||||
('request_date', '=', equipment.next_action_date),
|
('request_date', '=', equipment.next_action_date),
|
||||||
('sf_maintenance_type', '=', '保养')])
|
('sf_maintenance_type', '=', '保养')])
|
||||||
if not next_requests:
|
if not next_requests:
|
||||||
@@ -815,7 +743,6 @@ class SfMaintenanceEquipment(models.Model):
|
|||||||
next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False),
|
next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False),
|
||||||
('equipment_id', '=', equipment.id),
|
('equipment_id', '=', equipment.id),
|
||||||
('maintenance_type', '=', 'preventive'),
|
('maintenance_type', '=', 'preventive'),
|
||||||
('active', '=', True),
|
|
||||||
('request_date', '=', equipment.overhaul_date),
|
('request_date', '=', equipment.overhaul_date),
|
||||||
('sf_maintenance_type', '=', '检修')])
|
('sf_maintenance_type', '=', '检修')])
|
||||||
if not next_requests:
|
if not next_requests:
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
import logging
|
|
||||||
import datetime
|
import datetime
|
||||||
import requests
|
import requests
|
||||||
from odoo import api, fields, models, _
|
from odoo import api, fields, models, _
|
||||||
@@ -63,22 +62,22 @@ class SfMaintenanceEquipmentOEE(models.Model):
|
|||||||
("封存(报废)", "封存(报废)")],
|
("封存(报废)", "封存(报废)")],
|
||||||
default='正常', string="机床状态", related='equipment_id.state')
|
default='正常', string="机床状态", related='equipment_id.state')
|
||||||
|
|
||||||
online_time = fields.Char('开机时长(小时)', readonly='True')
|
online_time = fields.Char('开机时长(小时)', reaonly='True')
|
||||||
|
|
||||||
offline_time = fields.Char('关机时长(小时)', readonly='True')
|
offline_time = fields.Char('关机时长(小时)', reaonly='True')
|
||||||
idle_nums = fields.Integer('待机次数', readonly='True')
|
idle_nums = fields.Integer('待机次数', reaonly='True')
|
||||||
# 待机时长
|
# 待机时长
|
||||||
|
|
||||||
idle_time = fields.Char('待机时长(小时)', readonly='True')
|
idle_time = fields.Char('待机时长(小时)', reaonly='True')
|
||||||
|
|
||||||
# 待机率
|
# 待机率
|
||||||
idle_rate = fields.Char('待机率(%)', readonly='True')
|
idle_rate = fields.Char('待机率(%)', reaonly='True')
|
||||||
|
|
||||||
work_time = fields.Char('加工时长(小时)', readonly='True')
|
work_time = fields.Char('加工时长(小时)', reaonly='True')
|
||||||
work_rate = fields.Char('可用率(%)', readonly='True')
|
work_rate = fields.Char('可用率(%)', reaonly='True')
|
||||||
fault_time = fields.Char('故障时长(小时)', readonly='True')
|
fault_time = fields.Char('故障时长(小时)', reaonly='True')
|
||||||
fault_rate = fields.Char('故障率(%)', readonly='True')
|
fault_rate = fields.Char('故障率(%)', reaonly='True')
|
||||||
fault_nums = fields.Integer('故障次数', readonly='True')
|
fault_nums = fields.Integer('故障次数', reaonly='True')
|
||||||
|
|
||||||
# 设备故障日志
|
# 设备故障日志
|
||||||
sf_maintenance_logs_ids = fields.One2many('sf.maintenance.logs', 'maintenance_equipment_oee_id', '设备故障日志',
|
sf_maintenance_logs_ids = fields.One2many('sf.maintenance.logs', 'maintenance_equipment_oee_id', '设备故障日志',
|
||||||
@@ -91,18 +90,11 @@ class SfMaintenanceEquipmentOEE(models.Model):
|
|||||||
|
|
||||||
def get_running_datas(self):
|
def get_running_datas(self):
|
||||||
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
|
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
|
||||||
logging.info("base_url=============:%s" % base_url)
|
url_time = base_url + '/api/RunningTimeDetail'
|
||||||
# 只有当原始 URL 使用 http 时才替换为 https
|
|
||||||
if base_url.startswith("http://"):
|
|
||||||
secure_base_url = base_url.replace("http://", "https://")
|
|
||||||
else:
|
|
||||||
secure_base_url = base_url
|
|
||||||
url_time = secure_base_url + '/api/RunningTimeDetail'
|
|
||||||
logging.info("url_time=============:%s" % url_time)
|
|
||||||
cnc_list_obj = self.env['maintenance.equipment'].sudo().search(
|
cnc_list_obj = self.env['maintenance.equipment'].sudo().search(
|
||||||
[('function_type', '!=', False), ('active', '=', True)])
|
[('function_type', '!=', False), ('active', '=', True)])
|
||||||
machine_list = list(map(lambda x: x.code, cnc_list_obj))
|
machine_list = list(map(lambda x: x.code, cnc_list_obj))
|
||||||
logging.info("machine_list=============:%s" % machine_list)
|
# print('machine_list: %s' % machine_list)
|
||||||
|
|
||||||
data_time = {
|
data_time = {
|
||||||
"machine_list": str(machine_list)
|
"machine_list": str(machine_list)
|
||||||
@@ -375,25 +367,25 @@ class SfMaintenanceEquipmentOEELog(models.Model):
|
|||||||
[("ZXJGZX", "钻铣加工中心"), ("CXJGZX", "车削加工中心"), ("FHJGZX", "复合加工中心")],
|
[("ZXJGZX", "钻铣加工中心"), ("CXJGZX", "车削加工中心"), ("FHJGZX", "复合加工中心")],
|
||||||
default="", string="功能类型")
|
default="", string="功能类型")
|
||||||
machine_tool_picture = fields.Binary('设备图片')
|
machine_tool_picture = fields.Binary('设备图片')
|
||||||
type_id = fields.Many2one('sf.machine_tool.type', '品牌型号', readonly='True')
|
type_id = fields.Many2one('sf.machine_tool.type', '品牌型号', reaonly='True')
|
||||||
state = fields.Selection([("加工", "加工"), ("关机", "关机"), ("待机", "待机"), ("故障", "故障"),
|
state = fields.Selection([("加工", "加工"), ("关机", "关机"), ("待机", "待机"), ("故障", "故障"),
|
||||||
("检修", "检修"), ("保养", "保养")], default="", string="实时状态")
|
("检修", "检修"), ("保养", "保养")], default="", string="实时状态")
|
||||||
online_time = fields.Char('开机时长', readonly='True')
|
online_time = fields.Char('开机时长', reaonly='True')
|
||||||
|
|
||||||
offline_time = fields.Char('关机时长', readonly='True')
|
offline_time = fields.Char('关机时长', reaonly='True')
|
||||||
offline_nums = fields.Integer('关机次数', readonly='True')
|
offline_nums = fields.Integer('关机次数', reaonly='True')
|
||||||
# 待机时长
|
# 待机时长
|
||||||
|
|
||||||
idle_time = fields.Char('待机时长', readonly='True')
|
idle_time = fields.Char('待机时长', reaonly='True')
|
||||||
|
|
||||||
# 待机率
|
# 待机率
|
||||||
idle_rate = fields.Char('待机率', readonly='True')
|
idle_rate = fields.Char('待机率', reaonly='True')
|
||||||
|
|
||||||
work_time = fields.Char('加工时长', readonly='True')
|
work_time = fields.Char('加工时长', reaonly='True')
|
||||||
work_rate = fields.Char('可用率', readonly='True')
|
work_rate = fields.Char('可用率', reaonly='True')
|
||||||
fault_time = fields.Char('故障时长', readonly='True')
|
fault_time = fields.Char('故障时长', reaonly='True')
|
||||||
fault_rate = fields.Char('故障率', readonly='True')
|
fault_rate = fields.Char('故障率', reaonly='True')
|
||||||
fault_nums = fields.Integer('故障次数', readonly='True')
|
fault_nums = fields.Integer('故障次数', reaonly='True')
|
||||||
|
|
||||||
detail_ids = fields.One2many('maintenance.equipment.oee.log.detail', 'log_id', string='日志详情')
|
detail_ids = fields.One2many('maintenance.equipment.oee.log.detail', 'log_id', string='日志详情')
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ class SfMaintenanceEquipmentCategory(models.Model):
|
|||||||
equipment_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备维保标准',
|
equipment_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备维保标准',
|
||||||
domain="[('maintenance_type','=',sf_maintenance_type)]")
|
domain="[('maintenance_type','=',sf_maintenance_type)]")
|
||||||
|
|
||||||
active = fields.Boolean('有效', default=True)
|
|
||||||
|
|
||||||
@api.onchange('sf_maintenance_type')
|
@api.onchange('sf_maintenance_type')
|
||||||
def _compute_equipment_maintenance_request_id(self):
|
def _compute_equipment_maintenance_request_id(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
|
|||||||
@@ -20,12 +20,7 @@ access_maintenance_equipment_agv_log,maintenance_equipment_agv_log,model_mainten
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
access_maintenance_system_user,equipment.request system user,maintenance.model_maintenance_request,base.group_user,1,1,1,0
|
access_maintenance_system_user,equipment.request system user,maintenance.model_maintenance_request,base.group_user,1,0,0,0
|
||||||
access_maintenance_wizard_system_user,maintenance.request.wizard system user,model_maintenance_request_wizard,base.group_user,1,1,1,0
|
|
||||||
access_maintenance_sf_group_equipment_user,equipment.request_sf_group_equipment_user,maintenance.model_maintenance_request,sf_group_equipment_user,1,1,1,0
|
|
||||||
access_maintenance_wizard_sf_group_equipment_user,maintenance_wizard_sf_group_equipment_user,model_maintenance_request_wizard,sf_group_equipment_user,1,1,1,0
|
|
||||||
access_maintenance_sf_group_equipment_manager,equipment.request_sf_group_equipment_manager,maintenance.model_maintenance_request,sf_group_equipment_manager,1,1,1,0
|
|
||||||
access_maintenance_wizard_sf_group_equipment_manager,maintenance_wizard_sf_group_equipment_manager,model_maintenance_request_wizard,sf_group_equipment_manager,1,1,1,0
|
|
||||||
|
|
||||||
access_maintenance_equipment_group_plan_dispatch,maintenance.equipment,maintenance.model_maintenance_equipment,sf_base.group_plan_dispatch,1,0,0,0
|
access_maintenance_equipment_group_plan_dispatch,maintenance.equipment,maintenance.model_maintenance_equipment,sf_base.group_plan_dispatch,1,0,0,0
|
||||||
access_maintenance_equipment_oee_group_plan_dispatch,maintenance_equipment_oee,model_maintenance_equipment_oee,sf_base.group_plan_dispatch,1,0,0,0
|
access_maintenance_equipment_oee_group_plan_dispatch,maintenance_equipment_oee,model_maintenance_equipment_oee,sf_base.group_plan_dispatch,1,0,0,0
|
||||||
|
|||||||
|
@@ -76,61 +76,33 @@
|
|||||||
<field name="equipment_maintenance_id"/>
|
<field name="equipment_maintenance_id"/>
|
||||||
|
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='user_id']" position="replace">
|
<xpath expr="//field[@name='user_id']" position="replace">
|
||||||
<field name="user_id" string="维保人"/>
|
<field name="user_id" string="维保人"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='close_date']" position="replace">
|
<xpath expr="//field[@name='close_date']" position="replace">
|
||||||
<field name="close_date" attrs="{'invisible': [('done', '!=', True)]}" readonly="True"
|
<field name="close_date" attrs="{'invisible': [('done', '!=', True)]}" readonly="True" string="维保日期"/>
|
||||||
string="维保日期"/>
|
</xpath>
|
||||||
</xpath>
|
|
||||||
|
|
||||||
<xpath expr="//field[@name='request_date']" position="attributes">
|
|
||||||
<attribute name="string">计划维保日期</attribute>
|
|
||||||
</xpath>
|
|
||||||
|
|
||||||
<sheet>
|
<sheet>
|
||||||
|
|
||||||
<notebook>
|
<notebook>
|
||||||
<page string="维保标准" attrs="{'invisible': [('equipment_maintenance_id', '=', False)]}"
|
<page string="维保标准" attrs="{'invisible': [('equipment_maintenance_id', '=', False)]}" context="{'default_standard_id': 'id'}">
|
||||||
context="{'default_standard_id': 'id'}">
|
|
||||||
<field name="maintenance_standards" widget="one2many_list">
|
<field name="maintenance_standards" widget="one2many_list">
|
||||||
<tree multi_edit="" editable="">
|
<tree multi_edit="" editable="">
|
||||||
<field name="name" class="table_custom_required"/>
|
<field name="name" class="table_custom_required"/>
|
||||||
<field name="maintenance_standards" class="table_custom_required"/>
|
<field name="maintenance_standards" class="table_custom_required"/>
|
||||||
<field name="images" force_save="1" required="1" class="table_custom_required">
|
<field name="images" force_save="1" required="1" class="table_custom_required">
|
||||||
</field>
|
</field>
|
||||||
<field name="remark" class="table_custom_required"/>
|
<field name="remark" class="table_custom_required"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</page>
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
|
|
||||||
|
|
||||||
</sheet>
|
</sheet>
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="maintenance_request_view_tree_sf" model="ir.ui.view">
|
|
||||||
<field name="name">maintenance.request.view.tree.sf</field>
|
|
||||||
<field name="model">maintenance.request</field>
|
|
||||||
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_tree"/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<xpath expr="//field[@name='request_date']" position="replace">
|
|
||||||
<field name="request_date" string="计划维保日期"/>
|
|
||||||
</xpath>
|
|
||||||
<xpath expr="//field[@name='user_id']" position="after">
|
|
||||||
<field name="sf_maintenance_type"/>
|
|
||||||
</xpath>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="equipment_request_view_search_sf" model="ir.ui.view">
|
|
||||||
<field name="name">maintenance.request.view.search.sf</field>
|
|
||||||
<field name="model">maintenance.request</field>
|
|
||||||
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_search"/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<xpath expr="//filter[@name='inactive']" position="replace">
|
|
||||||
<filter string="不活跃的" name="inactive" domain="[('archive', '=', True)]"/>
|
|
||||||
<filter string="已归档" name="in_active" domain="[('active', '=', False)]"/>
|
|
||||||
</xpath>
|
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@@ -138,8 +110,8 @@
|
|||||||
<record id="hr_equipment_request_action1" model="ir.actions.act_window">
|
<record id="hr_equipment_request_action1" model="ir.actions.act_window">
|
||||||
<field name="name">维保计划</field>
|
<field name="name">维保计划</field>
|
||||||
<field name="res_model">maintenance.request</field>
|
<field name="res_model">maintenance.request</field>
|
||||||
<field name="view_mode">tree,kanban,form,pivot,graph,calendar</field>
|
<field name="view_mode">kanban,tree,form,pivot,graph,calendar</field>
|
||||||
<field name="view_id" ref="sf_maintenance.maintenance_request_view_tree_sf"/>
|
<field name="view_id" ref="maintenance.hr_equipment_request_view_kanban"/>
|
||||||
<field name="context">{'default_user_id': uid}</field>
|
<field name="context">{'default_user_id': uid}</field>
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
<p class="o_view_nocontent_smiling_face">
|
<p class="o_view_nocontent_smiling_face">
|
||||||
|
|||||||
@@ -60,9 +60,9 @@
|
|||||||
<field name="function_type"/>
|
<field name="function_type"/>
|
||||||
<field name="code" readonly="1"/>
|
<field name="code" readonly="1"/>
|
||||||
<field name="equipment_type" invisible="1"/>
|
<field name="equipment_type" invisible="1"/>
|
||||||
<field name="brand_id" force_save="1"/>
|
<field name="brand_id" force_save="1" />
|
||||||
<field name="type_id" attrs="{'required': [('equipment_type', '=', '机床')]}"
|
<field name="type_id" attrs="{'required': [('equipment_type', '=', '机床')]}"
|
||||||
domain="[('brand_id', '=', brand_id)]"/>
|
domain="[('brand_id', '=', brand_id)]" />
|
||||||
<field name="machine_tool_category" readonly="1" attrs="{'invisible': [('type_id', '=', False)]}"
|
<field name="machine_tool_category" readonly="1" attrs="{'invisible': [('type_id', '=', False)]}"
|
||||||
force_save="1"/>
|
force_save="1"/>
|
||||||
<field name="run_time" force_save="1"/>
|
<field name="run_time" force_save="1"/>
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
<group>
|
<group>
|
||||||
<group string="基础参数">
|
<group string="基础参数">
|
||||||
<field name="control_system_id" attrs="{'required': [('equipment_type', '=', '机床')]}"
|
<field name="control_system_id" attrs="{'required': [('equipment_type', '=', '机床')]}"
|
||||||
options="{'no_create': True}"/>
|
options="{'no_create': True}" />
|
||||||
<label for="workbench_L" string="工作台尺寸(mm)"/>
|
<label for="workbench_L" string="工作台尺寸(mm)"/>
|
||||||
<div class="test_model">
|
<div class="test_model">
|
||||||
<label for="workbench_L" string="长"/>
|
<label for="workbench_L" string="长"/>
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
<field name="workbench_W" class="o_address_zip"
|
<field name="workbench_W" class="o_address_zip"
|
||||||
attrs="{'required': [('equipment_type', '=', '机床')]}"
|
attrs="{'required': [('equipment_type', '=', '机床')]}"
|
||||||
options="{'format': false}"/>
|
options="{'format': false}"/>
|
||||||
<span>&nbsp;</span>
|
<span>&nbsp;</span>
|
||||||
<label for="workbench_H" string="高"/>
|
<label for="workbench_H" string="高"/>
|
||||||
<field name="workbench_H" class="o_address_zip"
|
<field name="workbench_H" class="o_address_zip"
|
||||||
attrs="{'required': [('equipment_type', '=', '机床')]}"
|
attrs="{'required': [('equipment_type', '=', '机床')]}"
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
<!-- <field name="guide_rail" required="1"/>-->
|
<!-- <field name="guide_rail" required="1"/>-->
|
||||||
<field name="number_of_axles" attrs="{'required': [('equipment_type', '=', '机床')]}"
|
<field name="number_of_axles" attrs="{'required': [('equipment_type', '=', '机床')]}"
|
||||||
widget="radio"
|
widget="radio"
|
||||||
options="{'horizontal': true}"/>
|
options="{'horizontal': true}" />
|
||||||
<label for="x_axis" string="加工行程(mm)"
|
<label for="x_axis" string="加工行程(mm)"
|
||||||
attrs="{'invisible': [('number_of_axles', '=', False)]}"/>
|
attrs="{'invisible': [('number_of_axles', '=', False)]}"/>
|
||||||
<div class="test_model"
|
<div class="test_model"
|
||||||
@@ -196,8 +196,8 @@
|
|||||||
<field name="T_tool_time"/>
|
<field name="T_tool_time"/>
|
||||||
<field name="C_tool_time"/>
|
<field name="C_tool_time"/>
|
||||||
</group>
|
</group>
|
||||||
<group string="主轴">
|
<group string="主轴">
|
||||||
<field name="taper_type_id" attrs="{'required': [('equipment_type', '=', '机床')]}"/>
|
<field name="taper_type_id" attrs="{'required': [('equipment_type', '=', '机床')]}" />
|
||||||
<label for="distance_min" string="主轴端面-工作台距离(mm)"/>
|
<label for="distance_min" string="主轴端面-工作台距离(mm)"/>
|
||||||
<div class="test_model">
|
<div class="test_model">
|
||||||
<label for="distance_min" string="最小(min)"/>
|
<label for="distance_min" string="最小(min)"/>
|
||||||
@@ -237,7 +237,7 @@
|
|||||||
<field name="c_precision"/>
|
<field name="c_precision"/>
|
||||||
<field name="c_precision_repeat"/>
|
<field name="c_precision_repeat"/>
|
||||||
</group>
|
</group>
|
||||||
<group string="进给参数">
|
<group string="进给参数">
|
||||||
<field name="X_axis_rapid_traverse_speed"/>
|
<field name="X_axis_rapid_traverse_speed"/>
|
||||||
<field name="Y_axis_rapid_traverse_speed"/>
|
<field name="Y_axis_rapid_traverse_speed"/>
|
||||||
<field name="Z_axis_rapid_traverse_speed"/>
|
<field name="Z_axis_rapid_traverse_speed"/>
|
||||||
@@ -252,21 +252,21 @@
|
|||||||
|
|
||||||
|
|
||||||
</page>
|
</page>
|
||||||
<page string="AGV运行日志" name="sf_equipment"
|
<page string="AGV运行日志" name="sf_equipment"
|
||||||
attrs="{'invisible': [('equipment_type', '!=', 'AGV小车')]}">
|
attrs="{'invisible': [('equipment_type', '!=', 'AGV小车')]}">
|
||||||
<field name="agv_logs">
|
<field name="agv_logs">
|
||||||
<tree create="1" edit="1" delete="1" editable="bottom">
|
<tree create="1" edit="1" delete="1" editable="bottom">
|
||||||
<field name='run_type'/>
|
<field name = 'run_type'/>
|
||||||
<field name='run_code'/>
|
<field name = 'run_code'/>
|
||||||
<field name='run_first'/>
|
<field name = 'run_first'/>
|
||||||
<field name='run_last'/>
|
<field name = 'run_last'/>
|
||||||
<field name='production_line'/>
|
<field name = 'production_line'/>
|
||||||
<field name='workorder'/>
|
<field name = 'workorder'/>
|
||||||
<field name='time'/>
|
<field name = 'time'/>
|
||||||
<field name='state'/>
|
<field name = 'state'/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</page>
|
</page>
|
||||||
|
|
||||||
<page string="设备参数" name="sf_equipment"
|
<page string="设备参数" name="sf_equipment"
|
||||||
attrs="{'invisible': [('equipment_type', '!=', 'AGV小车')]}">
|
attrs="{'invisible': [('equipment_type', '!=', 'AGV小车')]}">
|
||||||
@@ -979,58 +979,31 @@
|
|||||||
</group>
|
</group>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//field[@name='next_action_date']" position="before">
|
||||||
|
|
||||||
<xpath expr="//page[@name='maintenance']" position="replace">
|
<field name='eq_maintenance_id' force_save="1" widget="many2one"/>
|
||||||
<page string="维保" name="maintenance">
|
|
||||||
<group>
|
|
||||||
<group string="保养">
|
|
||||||
<field name='eq_maintenance_id' force_save="1" widget="many2one"/>
|
|
||||||
<field name="initial_action_date"/>
|
|
||||||
<field name="next_action_date" string="下次预防保养"/>
|
|
||||||
<label for="period" string="预防保养频次"/>
|
|
||||||
<div class="o_row">
|
|
||||||
<field name="period"/>
|
|
||||||
days
|
|
||||||
</div>
|
|
||||||
<label for="maintenance_duration" string="保养时长"/>
|
|
||||||
<div class="o_row">
|
|
||||||
<field name="maintenance_duration"/>
|
|
||||||
hours
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-lg-6 o_setting_box" style="white-space: nowrap">
|
|
||||||
<button name="confirm_maintenance" string="确认保养" type="object"
|
|
||||||
class="oe_highlight" context="{'type': '保养'}"/>
|
|
||||||
</div>
|
|
||||||
</group>
|
|
||||||
<group string="检修">
|
|
||||||
<field name='overhaul_id'/>
|
|
||||||
<field name="initial_overhaul_date"/>
|
|
||||||
<field name="overhaul_date" string="下次预防检修"/>
|
|
||||||
<label for="overhaul_period" string="预防检修频次"/>
|
|
||||||
<div class="o_row">
|
|
||||||
<field name="overhaul_period"/>
|
|
||||||
days
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label for="overhaul_duration" string="检修时长"/>
|
|
||||||
<div class="o_row">
|
|
||||||
<field name="overhaul_duration"/>
|
|
||||||
hours
|
|
||||||
</div>
|
|
||||||
<field name='equipment_maintenance_standards_ids' widget="many2many_tags"
|
|
||||||
invisible="1"/>
|
|
||||||
|
|
||||||
<div class="col-12 col-lg-6 o_setting_box" style="white-space: nowrap">
|
|
||||||
<button name="confirm_maintenance" string="确认检修" type="object"
|
|
||||||
class="oe_highlight" context="{'type': '检修'}"/>
|
|
||||||
</div>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
|
|
||||||
|
|
||||||
</page>
|
|
||||||
</xpath>
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//div[hasclass('o_row')][field[@name='maintenance_duration']]" position="after">
|
||||||
|
|
||||||
|
|
||||||
|
<field name='overhaul_id' options="{'no_create':True}"/>
|
||||||
|
<field name="overhaul_date" string="下次预防检修"/>
|
||||||
|
<label for="overhaul_period" string="预防检修频次"/>
|
||||||
|
<div class="o_row">
|
||||||
|
<field name="overhaul_period"/>
|
||||||
|
days
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label for="overhaul_duration" string="检修时长"/>
|
||||||
|
<div class="o_row">
|
||||||
|
<field name="overhaul_duration"/>
|
||||||
|
hours
|
||||||
|
</div>
|
||||||
|
<field name='equipment_maintenance_standards_ids' widget="many2many_tags" invisible="1"/>
|
||||||
|
|
||||||
|
</xpath>
|
||||||
<xpath expr="//page[@name='description']" position="attributes">
|
<xpath expr="//page[@name='description']" position="attributes">
|
||||||
<attribute name="invisible">1</attribute>
|
<attribute name="invisible">1</attribute>
|
||||||
</xpath>
|
</xpath>
|
||||||
@@ -1216,7 +1189,7 @@
|
|||||||
<field name="name" readonly="1"/>
|
<field name="name" readonly="1"/>
|
||||||
<field name="type" readonly="1"/>
|
<field name="type" readonly="1"/>
|
||||||
<field name="image" widget="image" readonly="1"/>
|
<field name="image" widget="image" readonly="1"/>
|
||||||
<!-- <field name="equipment_id"/>-->
|
<!-- <field name="equipment_id"/>-->
|
||||||
<field name="active" invisible="1"/>
|
<field name="active" invisible="1"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
from . import maintenance_request_wizard
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
from odoo import fields, models
|
|
||||||
|
|
||||||
|
|
||||||
class MaintenanceRequestWizard(models.TransientModel):
|
|
||||||
_name = 'maintenance.request.wizard'
|
|
||||||
_description = '维保二次确认弹窗'
|
|
||||||
|
|
||||||
name = fields.Char('')
|
|
||||||
|
|
||||||
def submit(self):
|
|
||||||
context = self.env.context
|
|
||||||
equipment_id = self.env['maintenance.equipment'].sudo().search([('id', '=', context['equipment_id'])])
|
|
||||||
request_ids = self.env['maintenance.request'].search([('stage_id.done', '=', False),
|
|
||||||
('equipment_id', '=', equipment_id.id),
|
|
||||||
('maintenance_type', '=', 'preventive'),
|
|
||||||
('sf_maintenance_type', '=', context['type'])])
|
|
||||||
request_ids.write({'active': False})
|
|
||||||
return equipment_id.create_maintenance_request(context['type'])
|
|
||||||
|
|
||||||
def cancel(self):
|
|
||||||
context = self.env.context
|
|
||||||
equipment_id = self.env['maintenance.equipment'].sudo().search([('id', '=', context['equipment_id'])])
|
|
||||||
if context['type'] == '保养':
|
|
||||||
equipment_id.initial_action_date = equipment_id.initial_action_date_old
|
|
||||||
elif context['type'] == '检修':
|
|
||||||
equipment_id.initial_overhaul_date = equipment_id.initial_overhaul_date_old
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
<openerp>
|
|
||||||
<data>
|
|
||||||
<record id="action_maintenance_request_wizard" model="ir.actions.act_window">
|
|
||||||
<field name="name">维保计划</field>
|
|
||||||
<field name="res_model">maintenance.request.wizard</field>
|
|
||||||
<field name="view_mode">form</field>
|
|
||||||
<field name="target">new</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record model="ir.ui.view" id="maintenance_request_wizard_form_view">
|
|
||||||
<field name="name">maintenance.request.wizard.form.view</field>
|
|
||||||
<field name="model">maintenance.request.wizard</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<form>
|
|
||||||
<div>
|
|
||||||
<field name="name" invisible="1"/>
|
|
||||||
有未执行的历史维保计划,是否创建新维保计划!!
|
|
||||||
</div>
|
|
||||||
<footer>
|
|
||||||
<button string="确认" name="submit" type="object" class="oe_highlight"/>
|
|
||||||
<button string="取消" name="cancel" type="object" class="oe_highlight"/>
|
|
||||||
</footer>
|
|
||||||
</form>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
|
|
||||||
</data>
|
|
||||||
</openerp>
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
{
|
{
|
||||||
'name': '机企猫智能工厂 制造管理',
|
'name': '机企猫智能工厂 制造管理',
|
||||||
'version': '1.1',
|
'version': '1.0',
|
||||||
'summary': '智能工厂制造模块',
|
'summary': '智能工厂制造模块',
|
||||||
'sequence': 1,
|
'sequence': 1,
|
||||||
'description': """
|
'description': """
|
||||||
@@ -10,9 +10,8 @@
|
|||||||
""",
|
""",
|
||||||
'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', 'jikimo_sale_multiple_supply_methods'],
|
'depends': ['sf_base', 'sf_maintenance', 'web_widget_model_viewer', 'sf_warehouse'],
|
||||||
'data': [
|
'data': [
|
||||||
'data/cron_data.xml',
|
|
||||||
'data/stock_data.xml',
|
'data/stock_data.xml',
|
||||||
'data/empty_racks_data.xml',
|
'data/empty_racks_data.xml',
|
||||||
'data/panel_data.xml',
|
'data/panel_data.xml',
|
||||||
@@ -22,9 +21,6 @@
|
|||||||
'wizard/workpiece_delivery_views.xml',
|
'wizard/workpiece_delivery_views.xml',
|
||||||
'wizard/rework_wizard_views.xml',
|
'wizard/rework_wizard_views.xml',
|
||||||
'wizard/production_wizard_views.xml',
|
'wizard/production_wizard_views.xml',
|
||||||
'wizard/production_technology_wizard_views.xml',
|
|
||||||
'wizard/production_technology_re_adjust_wizard_views.xml',
|
|
||||||
'wizard/mrp_workorder_batch_replan_wizard_views.xml',
|
|
||||||
'views/mrp_views_menus.xml',
|
'views/mrp_views_menus.xml',
|
||||||
'views/agv_scheduling_views.xml',
|
'views/agv_scheduling_views.xml',
|
||||||
'views/stock_lot_views.xml',
|
'views/stock_lot_views.xml',
|
||||||
@@ -33,14 +29,10 @@
|
|||||||
'views/production_line_view.xml',
|
'views/production_line_view.xml',
|
||||||
'views/mrp_workcenter_views.xml',
|
'views/mrp_workcenter_views.xml',
|
||||||
'views/mrp_workorder_view.xml',
|
'views/mrp_workorder_view.xml',
|
||||||
'views/stock_picking_view.xml',
|
|
||||||
'views/model_type_view.xml',
|
'views/model_type_view.xml',
|
||||||
'views/agv_setting_views.xml',
|
'views/agv_setting_views.xml',
|
||||||
'views/sf_maintenance_equipment.xml',
|
'views/sf_maintenance_equipment.xml',
|
||||||
'views/res_config_settings_views.xml',
|
'views/res_config_settings_views.xml',
|
||||||
'views/sale_order_views.xml',
|
|
||||||
'views/mrp_workorder_batch_replan.xml',
|
|
||||||
'views/purchase_order_view.xml',
|
|
||||||
],
|
],
|
||||||
'assets': {
|
'assets': {
|
||||||
|
|
||||||
@@ -53,10 +45,6 @@
|
|||||||
'sf_manufacturing/static/src/scss/kanban_change.scss',
|
'sf_manufacturing/static/src/scss/kanban_change.scss',
|
||||||
'sf_manufacturing/static/src/xml/button_show_on_tree.xml',
|
'sf_manufacturing/static/src/xml/button_show_on_tree.xml',
|
||||||
'sf_manufacturing/static/src/js/workpiece_delivery_wizard_confirm.js',
|
'sf_manufacturing/static/src/js/workpiece_delivery_wizard_confirm.js',
|
||||||
'sf_manufacturing/static/src/js/agv_scheduling_resend_confirm.js',
|
|
||||||
'sf_manufacturing/static/src/js/agv_scheduling_cancel_confirm.js',
|
|
||||||
'sf_manufacturing/static/src/js/qr.js',
|
|
||||||
'sf_manufacturing/static/src/xml/qr.xml',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
from . import controllers
|
from . import controllers
|
||||||
from . import workpiece
|
from . import workpiece
|
||||||
from . import main
|
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
import logging
|
|
||||||
import json
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
from odoo import http
|
|
||||||
from odoo.http import request
|
|
||||||
from odoo.addons.sf_bf_connect.controllers.controllers import Sf_Bf_Connect
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class JikimoSaleRoutePicking(Sf_Bf_Connect):
|
|
||||||
|
|
||||||
@http.route('/api/bfm_process_order/list', type='http', auth='sf_token', methods=['GET', 'POST'], csrf=False,
|
|
||||||
cors="*")
|
|
||||||
def get_bfm_process_order_list(self, **kw):
|
|
||||||
"""
|
|
||||||
接收业务平台加工订单分配工厂时传送来的订单数据并生成销售订单和产品及坯料
|
|
||||||
:param kw:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
res = {'status': 1, 'factory_order_no': ''}
|
|
||||||
# _logger.info('get_bfm_process_order_list:%s' % kw['order_number'])
|
|
||||||
try:
|
|
||||||
product_id = request.env.ref('jikimo_sale_multiple_supply_methods.product_template_default').with_context(active_test=False).sudo().product_variant_id
|
|
||||||
_logger.info('product_id:%s' % product_id)
|
|
||||||
company_id = request.env.ref('base.main_company').sudo()
|
|
||||||
bfm_process_order_list = json.loads(kw['bfm_process_order_list'])
|
|
||||||
order_id = request.env['sale.order'].with_user(request.env.ref("base.user_admin")).sale_order_create(
|
|
||||||
company_id, kw['delivery_name'], kw['delivery_telephone'], kw['delivery_address'],
|
|
||||||
kw['delivery_end_date'], kw['payments_way'], kw['pay_way'], kw['order_number'], state='draft')
|
|
||||||
i = 1
|
|
||||||
# 给sale_order的default_code字段赋值
|
|
||||||
# aa = request.env['sale.order'].sudo().search([('name', '=', order_id.name)])
|
|
||||||
# _logger.info('get_bfm_process_or===================================:%s' % order_id.name)
|
|
||||||
order_id.default_code = kw['order_number']
|
|
||||||
if kw.get('logistics_way'):
|
|
||||||
order_id.logistics_way = kw['logistics_way']
|
|
||||||
for item in bfm_process_order_list:
|
|
||||||
if item.get('embryo_redundancy_id'):
|
|
||||||
item['embryo_redundancy'] = request.env['sf.embryo.redundancy'].sudo().search([('code', '=', item['embryo_redundancy_id'])], limit=1)
|
|
||||||
item['embryo_redundancy_id'] = item['embryo_redundancy'].id
|
|
||||||
product = request.env['product.template'].sudo().product_create(product_id, item, order_id,
|
|
||||||
kw['order_number'], i)
|
|
||||||
product.product_tmpl_id.is_customer_provided = True if item['embryo_redundancy_id'] else False
|
|
||||||
order_id.with_user(request.env.ref("base.user_admin")).sale_order_create_line(product, item)
|
|
||||||
i += 1
|
|
||||||
res['factory_order_no'] = order_id.name
|
|
||||||
except Exception as e:
|
|
||||||
traceback_error = traceback.format_exc()
|
|
||||||
logging.error('get_bfm_process_order_list error: %s' % traceback_error)
|
|
||||||
res['status'] = -1
|
|
||||||
res['message'] = '工厂创建销售订单和产品失败,请联系管理员'
|
|
||||||
request.cr.rollback()
|
|
||||||
return json.JSONEncoder().encode(res)
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
<odoo>
|
|
||||||
<data noupdate="1">
|
|
||||||
<record model="ir.cron" id="ir_cron_update_construction_period_status">
|
|
||||||
<field name="name">工期状态变更</field>
|
|
||||||
<field name="model_id" ref="model_mrp_workorder"/>
|
|
||||||
<field name="state">code</field>
|
|
||||||
<field name="code">model._corn_update_construction_period_status()</field>
|
|
||||||
<field name="interval_number">12</field>
|
|
||||||
<field name="interval_type">hours</field>
|
|
||||||
<field name="numbercall">-1</field>
|
|
||||||
<field name="doall" eval="False"/>
|
|
||||||
<field name="user_id" ref="base.user_root"/>
|
|
||||||
<field name="active" eval="True"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record model="ir.cron" id="ir_cron_update_delivery_status">
|
|
||||||
<field name="name">交期状态变更</field>
|
|
||||||
<field name="model_id" ref="model_mrp_production"/>
|
|
||||||
<field name="state">code</field>
|
|
||||||
<field name="code">model._corn_update_delivery_status()</field>
|
|
||||||
<field name="interval_number">12</field>
|
|
||||||
<field name="interval_type">hours</field>
|
|
||||||
<field name="numbercall">-1</field>
|
|
||||||
<field name="doall" eval="False"/>
|
|
||||||
<field name="user_id" ref="base.user_root"/>
|
|
||||||
<field name="active" eval="True"/>
|
|
||||||
</record>
|
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# migrations/1.1.0/post-migrate.py
|
|
||||||
from odoo import api, SUPERUSER_ID
|
|
||||||
|
|
||||||
def migrate(cr, version):
|
|
||||||
# 获取环境
|
|
||||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
|
||||||
|
|
||||||
# 示例:添加新字段
|
|
||||||
env.ref('sf_dlm.product_embryo_sf_self_machining').product_tmpl_id.write({'categ_type': '坯料'})
|
|
||||||
env.ref('sf_dlm.product_template_sf').product_tmpl_id.write({'categ_type': '成品'})
|
|
||||||
env.ref('sf_dlm.product_embryo_sf_outsource').product_tmpl_id.write({'categ_type': '坯料'})
|
|
||||||
env.ref('sf_dlm.product_embryo_sf_purchase').product_tmpl_id.write({'categ_type': '坯料'})
|
|
||||||
@@ -11,8 +11,3 @@ from . import production_line_base
|
|||||||
from . import agv_setting
|
from . import agv_setting
|
||||||
from . import agv_scheduling
|
from . import agv_scheduling
|
||||||
from . import res_config_setting
|
from . import res_config_setting
|
||||||
from . import sf_technology_design
|
|
||||||
from . import sf_production_common
|
|
||||||
from . import sale_order
|
|
||||||
from . import quick_easy_order
|
|
||||||
from . import purchase_order
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
from odoo import models, fields, api, _
|
from odoo import models, fields, api, _
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
@@ -211,18 +210,9 @@ class AgvScheduling(models.Model):
|
|||||||
def button_cancel(self):
|
def button_cancel(self):
|
||||||
# 弹出二次确认窗口后执行
|
# 弹出二次确认窗口后执行
|
||||||
for rec in self:
|
for rec in self:
|
||||||
|
if rec.state != '待下发':
|
||||||
|
raise UserError('只有待下发状态的AGV调度任务才能取消!')
|
||||||
rec.state = '已取消'
|
rec.state = '已取消'
|
||||||
return {
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'display_notification',
|
|
||||||
'target': 'new',
|
|
||||||
'params': {
|
|
||||||
'message': '任务取消成功!',
|
|
||||||
'type': 'success',
|
|
||||||
'sticky': False,
|
|
||||||
'next': {'type': 'ir.actions.act_window_close'},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def finish_scheduling(self):
|
def finish_scheduling(self):
|
||||||
"""
|
"""
|
||||||
@@ -242,7 +232,7 @@ class AgvScheduling(models.Model):
|
|||||||
agv_route sf.agv.task.route对象
|
agv_route sf.agv.task.route对象
|
||||||
"""
|
"""
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.state not in ['待下发', '配送中']:
|
if rec.state != '待下发':
|
||||||
return False
|
return False
|
||||||
_logger.info('AGV任务调度:下发调度任务,路线为%s' % agv_task_route)
|
_logger.info('AGV任务调度:下发调度任务,路线为%s' % agv_task_route)
|
||||||
rec.state = '配送中'
|
rec.state = '配送中'
|
||||||
@@ -275,44 +265,6 @@ class AgvScheduling(models.Model):
|
|||||||
})
|
})
|
||||||
return super().write(vals)
|
return super().write(vals)
|
||||||
|
|
||||||
def button_cancel_confirm(self):
|
|
||||||
if self.task_delivery_time > fields.Datetime.now() - timedelta(minutes=10):
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'agv_scheduling_cancel_confirm',
|
|
||||||
'params': {
|
|
||||||
'agv_scheduling_id': self.id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
return self.button_cancel()
|
|
||||||
|
|
||||||
def button_resend_confirm(self):
|
|
||||||
if self.task_delivery_time > fields.Datetime.now() - timedelta(minutes=10):
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'agv_scheduling_resend_confirm',
|
|
||||||
'params': {
|
|
||||||
'agv_scheduling_id': self.id,
|
|
||||||
'context': self.env.context,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
return self.button_resend()
|
|
||||||
|
|
||||||
def button_resend(self):
|
|
||||||
self.dispatch_scheduling(self.agv_route_id)
|
|
||||||
return {
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'display_notification',
|
|
||||||
'target': 'new',
|
|
||||||
'params': {
|
|
||||||
'message': '任务重新下发成功!',
|
|
||||||
'type': 'success',
|
|
||||||
'sticky': False,
|
|
||||||
'next': {'type': 'ir.actions.act_window_close'},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ResMrpWorkOrder(models.Model):
|
class ResMrpWorkOrder(models.Model):
|
||||||
_inherit = 'mrp.workorder'
|
_inherit = 'mrp.workorder'
|
||||||
|
|||||||
@@ -6,29 +6,42 @@ class ModelType(models.Model):
|
|||||||
_description = '模型类型'
|
_description = '模型类型'
|
||||||
|
|
||||||
name = fields.Char('名称')
|
name = fields.Char('名称')
|
||||||
# embryo_tolerance = fields.Char('坯料容余')
|
embryo_tolerance = fields.Integer('坯料容余')
|
||||||
embryo_tolerance_id = fields.Many2one('sf.embryo.redundancy', string='坯料冗余')
|
|
||||||
product_routing_tmpl_ids = fields.One2many('sf.product.model.type.routing.sort', 'product_model_type_id',
|
product_routing_tmpl_ids = fields.One2many('sf.product.model.type.routing.sort', 'product_model_type_id',
|
||||||
'成品工序模板(自动化产线加工')
|
'成品工序模板')
|
||||||
embryo_routing_tmpl_ids = fields.One2many('sf.embryo.model.type.routing.sort', 'embryo_model_type_id',
|
embryo_routing_tmpl_ids = fields.One2many('sf.embryo.model.type.routing.sort', 'embryo_model_type_id',
|
||||||
'坯料工序模板(人工线下加工)')
|
'坯料工序模板')
|
||||||
surface_technics_routing_tmpl_ids = fields.One2many('sf.surface_technics.model.type.routing.sort',
|
surface_technics_routing_tmpl_ids = fields.One2many('sf.surface_technics.model.type.routing.sort',
|
||||||
'surface_technics_model_type_id',
|
'surface_technics_model_type_id',
|
||||||
'表面工艺工序模板')
|
'表面工艺工序模板')
|
||||||
manual_product_routing_tmpl_ids = fields.One2many('sf.manual.product.model.type.routing.sort',
|
|
||||||
'manual_product_model_type_id',
|
|
||||||
'成品工序模板(人工线下加工)')
|
|
||||||
|
|
||||||
|
|
||||||
class ProductModelTypeRoutingSort(models.Model):
|
class ProductModelTypeRoutingSort(models.Model):
|
||||||
_name = 'sf.product.model.type.routing.sort'
|
_name = 'sf.product.model.type.routing.sort'
|
||||||
_description = '成品工序排序(自动化产线加工)'
|
_description = '成品工序排序'
|
||||||
|
|
||||||
sequence = fields.Integer('Sequence')
|
sequence = fields.Integer('Sequence')
|
||||||
route_workcenter_id = fields.Many2one('mrp.routing.workcenter',
|
route_workcenter_id = fields.Many2one('mrp.routing.workcenter',
|
||||||
domain=[('routing_type', 'in', ['装夹预调', 'CNC加工', '解除装夹'])])
|
domain=[('routing_type', 'in', ['装夹预调', 'CNC加工', '解除装夹'])])
|
||||||
is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat')
|
is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat')
|
||||||
|
|
||||||
|
# routing_type = fields.Selection([
|
||||||
|
# ('获取CNC加工程序', '获取CNC加工程序'),
|
||||||
|
# ('装夹', '装夹'),
|
||||||
|
# ('前置三元定位检测', '前置三元定位检测'),
|
||||||
|
# ('CNC加工', 'CNC加工'),
|
||||||
|
# ('后置三元质量检测', '后置三元质量检测'),
|
||||||
|
# ('解除装夹', '解除装夹'), ('切割', '切割'), ('表面工艺', '表面工艺')
|
||||||
|
# ], string="工序类型", compute='_compute_route_workcenter_id')
|
||||||
|
#
|
||||||
|
# @api.depends('route_workcenter_id')
|
||||||
|
# def _compute_route_workcenter_id(self):
|
||||||
|
# for record in self:
|
||||||
|
# if record:
|
||||||
|
# record.routing_type = record.route_workcenter_id.routing_type
|
||||||
|
|
||||||
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
|
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
|
||||||
|
|
||||||
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
|
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
|
||||||
product_model_type_id = fields.Many2one('sf.model.type')
|
product_model_type_id = fields.Many2one('sf.model.type')
|
||||||
|
|
||||||
@@ -44,7 +57,24 @@ class EmbryoModelTypeRoutingSort(models.Model):
|
|||||||
sequence = fields.Integer('Sequence')
|
sequence = fields.Integer('Sequence')
|
||||||
route_workcenter_id = fields.Many2one('mrp.routing.workcenter', domain=[('routing_type', 'in', ['切割'])])
|
route_workcenter_id = fields.Many2one('mrp.routing.workcenter', domain=[('routing_type', 'in', ['切割'])])
|
||||||
is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat')
|
is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat')
|
||||||
|
|
||||||
|
# routing_type = fields.Selection([
|
||||||
|
# ('获取CNC加工程序', '获取CNC加工程序'),
|
||||||
|
# ('装夹', '装夹'),
|
||||||
|
# ('前置三元定位检测', '前置三元定位检测'),
|
||||||
|
# ('CNC加工', 'CNC加工'),
|
||||||
|
# ('后置三元质量检测', '后置三元质量检测'),
|
||||||
|
# ('解除装夹', '解除装夹'), ('切割', '切割'), ('表面工艺', '表面工艺')
|
||||||
|
# ], string="工序类型", compute='_compute_route_workcenter_id')
|
||||||
|
#
|
||||||
|
# @api.depends('route_workcenter_id')
|
||||||
|
# def _compute_route_workcenter_id(self):
|
||||||
|
# for record in self:
|
||||||
|
# if record:
|
||||||
|
# record.routing_type = record.route_workcenter_id.routing_type
|
||||||
|
|
||||||
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
|
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
|
||||||
|
|
||||||
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
|
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
|
||||||
embryo_model_type_id = fields.Many2one('sf.model.type')
|
embryo_model_type_id = fields.Many2one('sf.model.type')
|
||||||
|
|
||||||
@@ -60,7 +90,24 @@ class SurfaceTechnicsModelTypeRoutingSort(models.Model):
|
|||||||
sequence = fields.Integer('Sequence')
|
sequence = fields.Integer('Sequence')
|
||||||
route_workcenter_id = fields.Many2one('mrp.routing.workcenter', domain=[('routing_type', 'in', ['表面工艺'])])
|
route_workcenter_id = fields.Many2one('mrp.routing.workcenter', domain=[('routing_type', 'in', ['表面工艺'])])
|
||||||
is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat')
|
is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat')
|
||||||
|
|
||||||
|
# routing_type = fields.Selection([
|
||||||
|
# ('获取CNC加工程序', '获取CNC加工程序'),
|
||||||
|
# ('装夹', '装夹'),
|
||||||
|
# ('前置三元定位检测', '前置三元定位检测'),
|
||||||
|
# ('CNC加工', 'CNC加工'),
|
||||||
|
# ('后置三元质量检测', '后置三元质量检测'),
|
||||||
|
# ('解除装夹', '解除装夹'), ('切割', '切割'), ('表面工艺', '表面工艺')
|
||||||
|
# ], string="工序类型", compute='_compute_route_workcenter_id')
|
||||||
|
#
|
||||||
|
# @api.depends('route_workcenter_id')
|
||||||
|
# def _compute_route_workcenter_id(self):
|
||||||
|
# for record in self:
|
||||||
|
# if record:
|
||||||
|
# record.routing_type = record.route_workcenter_id.routing_type
|
||||||
|
|
||||||
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
|
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
|
||||||
|
|
||||||
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
|
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
|
||||||
surface_technics_model_type_id = fields.Many2one('sf.model.type')
|
surface_technics_model_type_id = fields.Many2one('sf.model.type')
|
||||||
|
|
||||||
@@ -69,18 +116,3 @@ class SurfaceTechnicsModelTypeRoutingSort(models.Model):
|
|||||||
'route_model_type_uniq', 'unique (route_workcenter_id,surface_technics_model_type_id)',
|
'route_model_type_uniq', 'unique (route_workcenter_id,surface_technics_model_type_id)',
|
||||||
'表面工艺工序不能重复!')
|
'表面工艺工序不能重复!')
|
||||||
]
|
]
|
||||||
|
|
||||||
class ManualProductModelTypeRoutingSort(models.Model):
|
|
||||||
_name = 'sf.manual.product.model.type.routing.sort'
|
|
||||||
_description = '成品工序排序(人工线下加工)'
|
|
||||||
|
|
||||||
sequence = fields.Integer('Sequence')
|
|
||||||
route_workcenter_id = fields.Many2one('mrp.routing.workcenter', domain=[('routing_type', 'in', ['人工线下加工'])])
|
|
||||||
is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat')
|
|
||||||
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
|
|
||||||
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
|
|
||||||
manual_product_model_type_id = fields.Many2one('sf.model.type')
|
|
||||||
|
|
||||||
_sql_constraints = [
|
|
||||||
('route_model_type_uniq', 'unique (route_workcenter_id,manual_product_model_type_id)', '成品工序不能重复!')
|
|
||||||
]
|
|
||||||
@@ -8,7 +8,6 @@ import re
|
|||||||
import requests
|
import requests
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
from collections import defaultdict, namedtuple
|
from collections import defaultdict, namedtuple
|
||||||
|
|
||||||
from odoo import api, fields, models, SUPERUSER_ID, _
|
from odoo import api, fields, models, SUPERUSER_ID, _
|
||||||
from odoo.exceptions import UserError, ValidationError
|
from odoo.exceptions import UserError, ValidationError
|
||||||
from odoo.addons.sf_base.commons.common import Common
|
from odoo.addons.sf_base.commons.common import Common
|
||||||
@@ -19,7 +18,6 @@ class MrpProduction(models.Model):
|
|||||||
_inherit = 'mrp.production'
|
_inherit = 'mrp.production'
|
||||||
_description = "制造订单"
|
_description = "制造订单"
|
||||||
_order = 'create_date desc'
|
_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')
|
deadline_of_delivery = fields.Date('订单交期', tracking=True, compute='_compute_deadline_of_delivery')
|
||||||
# tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘")
|
# tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘")
|
||||||
maintenance_count = fields.Integer(compute='_compute_maintenance_count', string="Number of maintenance requests")
|
maintenance_count = fields.Integer(compute='_compute_maintenance_count', string="Number of maintenance requests")
|
||||||
@@ -36,140 +34,15 @@ class MrpProduction(models.Model):
|
|||||||
tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True)
|
tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True)
|
||||||
tool_state_remark2 = fields.Text(string='功能刀具状态备注(无效刀)', readonly=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')
|
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
|
||||||
def _compute_deadline_of_delivery(self):
|
def _compute_deadline_of_delivery(self):
|
||||||
for production in self:
|
for production in self:
|
||||||
# 确保 procurement_group_id 和相关字段存在
|
sale_order_ids = production.procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id.ids
|
||||||
if production.procurement_group_id:
|
if not sale_order_ids or len(sale_order_ids) < 1:
|
||||||
# 获取相关的 sale_id
|
continue
|
||||||
sale_order_id = production.procurement_group_id.mrp_production_ids.mapped(
|
sale_id = self.env['sale.order'].sudo().browse(sale_order_ids[0])
|
||||||
'move_dest_ids.group_id.sale_id')
|
if sale_id:
|
||||||
|
production.deadline_of_delivery = sale_id.deadline_of_delivery
|
||||||
# 确保 sale_order_id 是有效的 ID 列表
|
|
||||||
if sale_order_id:
|
|
||||||
# 获取 sale.order 记录
|
|
||||||
sale_id = self.env['sale.order'].sudo().browse(sale_order_id.ids) # 使用 mapped 返回的 ID 列表
|
|
||||||
|
|
||||||
# 处理 sale_id
|
|
||||||
if sale_id:
|
|
||||||
# 假设我们只需要第一个 sale_id
|
|
||||||
production.deadline_of_delivery = sale_id[0].deadline_of_delivery if sale_id else False
|
|
||||||
else:
|
|
||||||
production.deadline_of_delivery = False
|
|
||||||
else:
|
|
||||||
production.deadline_of_delivery = False
|
|
||||||
|
|
||||||
def _compute_default_delivery_status(self):
|
|
||||||
try:
|
|
||||||
if self.state == 'cancel':
|
|
||||||
return False
|
|
||||||
if not self.deadline_of_delivery:
|
|
||||||
return False
|
|
||||||
hours = self.get_hours_diff()
|
|
||||||
if hours >= 48:
|
|
||||||
return '正常'
|
|
||||||
elif hours > 0 and hours < 48 and self.state != 'done':
|
|
||||||
return '预警'
|
|
||||||
elif hours > 0 and hours < 48 and self.state == 'done':
|
|
||||||
return '正常'
|
|
||||||
else:
|
|
||||||
return '已逾期'
|
|
||||||
except Exception as e:
|
|
||||||
logging.error("Error processing production ID {}: {}".format(self.id, e))
|
|
||||||
raise e
|
|
||||||
|
|
||||||
@api.depends('state', 'deadline_of_delivery')
|
|
||||||
def _compute_delivery_status(self):
|
|
||||||
for production in self:
|
|
||||||
delivery_status = production._compute_default_delivery_status()
|
|
||||||
if delivery_status and production.delivery_status != delivery_status:
|
|
||||||
production.delivery_status = delivery_status
|
|
||||||
|
|
||||||
delivery_status = fields.Selection([('正常', '正常'), ('预警', '预警'), ('已逾期', '已逾期')], string='交期状态',
|
|
||||||
store=True,
|
|
||||||
compute='_compute_delivery_status',
|
|
||||||
default=lambda self: self._compute_default_delivery_status())
|
|
||||||
|
|
||||||
def get_page_all_records(self, model_name, func, domain, page_size=100):
|
|
||||||
# 获取模型对象
|
|
||||||
model = self.env[model_name].sudo()
|
|
||||||
|
|
||||||
# 初始化分页参数
|
|
||||||
page_number = 1
|
|
||||||
while True:
|
|
||||||
# 计算偏移量
|
|
||||||
offset = (page_number - 1) * page_size
|
|
||||||
|
|
||||||
# 获取当前页的数据
|
|
||||||
records = model.search(domain, limit=page_size, offset=offset)
|
|
||||||
|
|
||||||
# 如果没有更多记录,退出循环
|
|
||||||
if not records:
|
|
||||||
break
|
|
||||||
|
|
||||||
# 将当前页的数据添加到结果列表
|
|
||||||
func(records)
|
|
||||||
# 增加页码
|
|
||||||
page_number += 1
|
|
||||||
|
|
||||||
def run_compute_delivery_status(self, records):
|
|
||||||
records._compute_delivery_status()
|
|
||||||
|
|
||||||
def _corn_update_delivery_status(self):
|
|
||||||
need_list = [
|
|
||||||
'draft',
|
|
||||||
'technology_to_confirmed',
|
|
||||||
'confirmed',
|
|
||||||
'pending_cam',
|
|
||||||
'progress',
|
|
||||||
'rework',
|
|
||||||
'scrap',
|
|
||||||
'to_close',
|
|
||||||
]
|
|
||||||
# previous_workorder = self.env['mrp.production'].search([('state', 'in', need_list)])
|
|
||||||
self.get_page_all_records('mrp.production', self.run_compute_delivery_status,
|
|
||||||
[('state', 'in', need_list)], 100)
|
|
||||||
|
|
||||||
def get_hours_diff(self):
|
|
||||||
# 获取当前日期和时间
|
|
||||||
current_datetime = fields.Datetime.now()
|
|
||||||
|
|
||||||
# 将 date_field 转换为 datetime 对象
|
|
||||||
if self.deadline_of_delivery:
|
|
||||||
date_obj = fields.Date.from_string(self.deadline_of_delivery)
|
|
||||||
# 将 date 对象转换为 datetime 对象,设置时间为 00:00:00
|
|
||||||
date_obj = datetime.datetime.combine(date_obj, datetime.time.min)
|
|
||||||
|
|
||||||
# 计算两个日期之间的差值
|
|
||||||
delta = date_obj - current_datetime
|
|
||||||
|
|
||||||
# 返回差值的小时数
|
|
||||||
return int(delta.total_seconds() / 3600)
|
|
||||||
else:
|
|
||||||
return 0.0
|
|
||||||
|
|
||||||
@api.depends('workorder_ids.tool_state_remark')
|
@api.depends('workorder_ids.tool_state_remark')
|
||||||
def _compute_tool_state_remark(self):
|
def _compute_tool_state_remark(self):
|
||||||
@@ -212,7 +85,6 @@ class MrpProduction(models.Model):
|
|||||||
# ])
|
# ])
|
||||||
state = fields.Selection([
|
state = fields.Selection([
|
||||||
('draft', '草稿'),
|
('draft', '草稿'),
|
||||||
('technology_to_confirmed', '待工艺确认'),
|
|
||||||
('confirmed', '待排程'),
|
('confirmed', '待排程'),
|
||||||
('pending_cam', '待加工'),
|
('pending_cam', '待加工'),
|
||||||
('progress', '加工中'),
|
('progress', '加工中'),
|
||||||
@@ -256,14 +128,12 @@ class MrpProduction(models.Model):
|
|||||||
], string='工序状态', default='待装夹')
|
], string='工序状态', default='待装夹')
|
||||||
|
|
||||||
# 零件图号
|
# 零件图号
|
||||||
part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True)
|
part_number = fields.Char('零件图号', readonly=True)
|
||||||
|
|
||||||
# 上传零件图纸
|
# 上传零件图纸
|
||||||
part_drawing = fields.Binary('零件图纸', related='product_id.machining_drawings', readonly=True)
|
part_drawing = fields.Binary('零件图纸', readonly=True)
|
||||||
|
|
||||||
quality_standard = fields.Binary('质检标准', related='product_id.quality_standard', readonly=True)
|
quality_standard = fields.Binary('质检标准', readonly=True)
|
||||||
|
|
||||||
part_name = fields.Char(string='零件名称', related='product_id.part_name', readonly=True)
|
|
||||||
|
|
||||||
@api.depends('product_id.manual_quotation')
|
@api.depends('product_id.manual_quotation')
|
||||||
def _compute_manual_quotation(self):
|
def _compute_manual_quotation(self):
|
||||||
@@ -275,8 +145,6 @@ class MrpProduction(models.Model):
|
|||||||
is_remanufacture = fields.Boolean('是否重新制造', default=False)
|
is_remanufacture = fields.Boolean('是否重新制造', default=False)
|
||||||
remanufacture_count = fields.Integer("重新制造订单数量", compute='_compute_remanufacture_production_ids')
|
remanufacture_count = fields.Integer("重新制造订单数量", compute='_compute_remanufacture_production_ids')
|
||||||
remanufacture_production_id = fields.Many2one('mrp.production', string='')
|
remanufacture_production_id = fields.Many2one('mrp.production', string='')
|
||||||
technology_design_ids = fields.One2many('sf.technology.design', 'production_id', string='工艺设计')
|
|
||||||
is_adjust = fields.Boolean('是否退回调整', default=False)
|
|
||||||
|
|
||||||
@api.depends('remanufacture_production_id')
|
@api.depends('remanufacture_production_id')
|
||||||
def _compute_remanufacture_production_ids(self):
|
def _compute_remanufacture_production_ids(self):
|
||||||
@@ -303,7 +171,7 @@ class MrpProduction(models.Model):
|
|||||||
|
|
||||||
@api.depends(
|
@api.depends(
|
||||||
'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state', 'tool_state',
|
'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state', 'tool_state',
|
||||||
'workorder_ids.state', 'product_qty', 'qty_producing', 'schedule_state', 'programming_state', 'is_adjust')
|
'workorder_ids.state', 'product_qty', 'qty_producing', 'schedule_state')
|
||||||
def _compute_state(self):
|
def _compute_state(self):
|
||||||
for production in self:
|
for production in self:
|
||||||
if not production.state or not production.product_uom_id:
|
if not production.state or not production.product_uom_id:
|
||||||
@@ -333,196 +201,43 @@ class MrpProduction(models.Model):
|
|||||||
precision_rounding=move.product_uom.rounding or move.product_id.uom_id.rounding)
|
precision_rounding=move.product_uom.rounding or move.product_id.uom_id.rounding)
|
||||||
for move in production.move_raw_ids if move.product_id):
|
for move in production.move_raw_ids if move.product_id):
|
||||||
production.state = 'progress'
|
production.state = 'progress'
|
||||||
# 新添加的状态逻辑
|
|
||||||
if production.state in ['to_close', 'progress',
|
# # 新添加的状态逻辑
|
||||||
'technology_to_confirmed'] and production.schedule_state == '未排':
|
if (
|
||||||
if not production.workorder_ids or production.is_adjust is True:
|
production.state == 'to_close' or production.state == 'progress') and production.schedule_state == '未排':
|
||||||
production.state = 'technology_to_confirmed'
|
production.state = 'confirmed'
|
||||||
else:
|
|
||||||
if production.is_adjust is True:
|
|
||||||
production.state = 'technology_to_confirmed'
|
|
||||||
else:
|
|
||||||
production.state = 'confirmed'
|
|
||||||
elif production.state == 'pending_cam' and production.schedule_state == '未排':
|
elif production.state == 'pending_cam' and production.schedule_state == '未排':
|
||||||
production.state = 'confirmed'
|
production.state = 'confirmed'
|
||||||
elif production.state == 'to_close' and production.schedule_state == '已排':
|
elif production.state == 'to_close' and production.schedule_state == '已排':
|
||||||
production.state = 'pending_cam'
|
production.state = 'pending_cam'
|
||||||
elif production.state == 'confirmed' and production.is_adjust is True:
|
|
||||||
production.state = 'technology_to_confirmed'
|
|
||||||
if production.state == 'confirmed' and production.schedule_state == '已排':
|
|
||||||
production.state = 'pending_cam'
|
|
||||||
if production.state == 'progress':
|
if production.state == 'progress':
|
||||||
if all(wo_state not in ('progress', 'done', 'rework', 'scrap') for wo_state in
|
if all(wo_state not in ('progress', 'done', 'rework', 'scrap') for wo_state in
|
||||||
production.workorder_ids.mapped('state')):
|
production.workorder_ids.mapped('state')):
|
||||||
production.state = 'pending_cam'
|
production.state = 'pending_cam'
|
||||||
if production.is_rework is True:
|
if production.is_rework is True:
|
||||||
production.state = 'rework'
|
production.state = 'rework'
|
||||||
if (production.state == 'rework' and production.tool_state == '0'
|
|
||||||
and production.schedule_state == '已排' and production.is_rework is False):
|
|
||||||
production.state = 'pending_cam'
|
|
||||||
# if production.state == 'pending_cam':
|
# if production.state == 'pending_cam':
|
||||||
# if all(wo_state in 'done' for wo_state in production.workorder_ids.mapped('state')):
|
# if all(wo_state in 'done' for wo_state in production.workorder_ids.mapped('state')):
|
||||||
# production.state = 'done'
|
# production.state = 'done'
|
||||||
if any((wo.test_results == '返工' and wo.state == 'done' and production.programming_state in ['已编程'])
|
if any(
|
||||||
or (wo.is_rework is True and wo.state == 'done' and production.programming_state in ['编程中', '已编程'])
|
(
|
||||||
for wo in production.workorder_ids):
|
wo.test_results == '返工' and wo.state == 'done' and production.programming_state in [
|
||||||
|
'已编程']) or (
|
||||||
|
wo.state == 'rework' and production.programming_state == '编程中') or (
|
||||||
|
wo.is_rework is True and wo.state == 'done' and production.programming_state in ['编程中',
|
||||||
|
'已编程'])
|
||||||
|
for wo in
|
||||||
|
production.workorder_ids):
|
||||||
production.state = 'rework'
|
production.state = 'rework'
|
||||||
if any(wo.test_results == '报废' and wo.state == 'done' for wo in production.workorder_ids):
|
if any(wo.test_results == '报废' and wo.state == 'done' for wo in production.workorder_ids):
|
||||||
production.state = 'scrap'
|
production.state = 'scrap'
|
||||||
if any(dr.test_results == '报废' and dr.handle_result == '已处理' for dr in
|
if any(dr.test_results == '报废' and dr.handle_result == '已处理' for dr in
|
||||||
production.detection_result_ids):
|
production.detection_result_ids):
|
||||||
production.state = 'cancel'
|
production.state = 'cancel'
|
||||||
if production.workorder_ids and all(wo_state in ('done', 'rework', 'cancel') for wo_state in production.workorder_ids.mapped('state')):
|
# 如果制造订单的功能刀具为【无效刀】则制造订单状态改为返工
|
||||||
if production.state not in ['scrap', 'rework', 'cancel']:
|
if production.tool_state == '2':
|
||||||
production.state = 'done'
|
production.state = 'rework'
|
||||||
|
|
||||||
# 退回调整
|
|
||||||
def technology_back_adjust(self):
|
|
||||||
process_parameters = []
|
|
||||||
domain = [('state', '=', 'confirmed'), ('origin', '=', self.origin)]
|
|
||||||
if self.production_type == '自动化产线加工':
|
|
||||||
cloud_programming = self._cron_get_programming_state()
|
|
||||||
if cloud_programming['send_state'] == 'sending':
|
|
||||||
raise UserError(_("编程文件正在下发中,请稍后重试"))
|
|
||||||
domain += [('programming_no', '=', self.programming_no)]
|
|
||||||
# 带排程的制造订单
|
|
||||||
production_confirmed = self.env['mrp.production'].search(domain)
|
|
||||||
for special in production_confirmed.technology_design_ids:
|
|
||||||
if special.process_parameters_id:
|
|
||||||
product_production_process = self.env['product.template'].search(
|
|
||||||
[('server_product_process_parameters_id', '=', special.process_parameters_id.id)])
|
|
||||||
if not product_production_process:
|
|
||||||
if special.process_parameters_id not in process_parameters:
|
|
||||||
process_parameters.append(special.process_parameters_id.display_name)
|
|
||||||
if process_parameters:
|
|
||||||
raise UserError(_("【工艺设计】-【参数】为%s的在【产品】中不存在,请先创建", ", ".join(process_parameters)))
|
|
||||||
if production_confirmed:
|
|
||||||
production_count = self.env['mrp.production'].search_count([
|
|
||||||
('origin', '=', self.origin),
|
|
||||||
('product_id', '=', self.product_id.id),
|
|
||||||
('state', '=', 'confirmed')
|
|
||||||
])
|
|
||||||
if production_count > 1:
|
|
||||||
return {
|
|
||||||
'name': _('退回调整'),
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'views': [(self.env.ref(
|
|
||||||
'sf_manufacturing.sf_production_technology_re_adjust_wizard_form_view').id,
|
|
||||||
'form')],
|
|
||||||
'res_model': 'sf.production.technology.re_adjust.wizard',
|
|
||||||
'target': 'new',
|
|
||||||
'context': {
|
|
||||||
'default_production_id': self.id,
|
|
||||||
'default_origin': self.origin,
|
|
||||||
}}
|
|
||||||
else:
|
|
||||||
return {
|
|
||||||
'name': _('退回调整'),
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'views': [(self.env.ref(
|
|
||||||
'sf_manufacturing.sf_production_technology_re_adjust_wizard_confirm_form_view').id,
|
|
||||||
'form')],
|
|
||||||
'res_model': 'sf.production.technology.re_adjust.wizard',
|
|
||||||
'target': 'new',
|
|
||||||
'context': {
|
|
||||||
'default_production_id': self.id,
|
|
||||||
'default_origin': self.origin,
|
|
||||||
}}
|
|
||||||
|
|
||||||
# 工艺确认
|
|
||||||
def technology_confirm(self):
|
|
||||||
process_parameters = []
|
|
||||||
account_moves = []
|
|
||||||
parameters_not = []
|
|
||||||
# 获取原有的工单对应的工序
|
|
||||||
origin_designs = self.workorder_ids.technology_design_id
|
|
||||||
# 获取已删除的工序
|
|
||||||
deleted_designs = origin_designs - self.technology_design_ids
|
|
||||||
if deleted_designs:
|
|
||||||
for deleted_design in deleted_designs:
|
|
||||||
workorder = self.env['mrp.workorder'].search([('technology_design_id', '=', deleted_design.id)])
|
|
||||||
purchase = workorder._get_surface_technics_purchase_ids()
|
|
||||||
account = self.env['account.move'].search([('id', 'in', purchase.invoice_ids.ids)])
|
|
||||||
if account.state not in ['cancel', False]:
|
|
||||||
if purchase.name not in account_moves:
|
|
||||||
account_moves.append(purchase.name)
|
|
||||||
special_design = self.technology_design_ids.filtered(
|
|
||||||
lambda a: a.routing_tag == 'special' and a.is_auto is False)
|
|
||||||
for special in special_design:
|
|
||||||
if special.route_id.routing_type == '表面工艺' and not special.process_parameters_id:
|
|
||||||
parameters_not.append(special.route_id.name)
|
|
||||||
if special.process_parameters_id:
|
|
||||||
product_production_process = self.env['product.template'].search(
|
|
||||||
[('server_product_process_parameters_id', '=', special.process_parameters_id.id)])
|
|
||||||
if not product_production_process:
|
|
||||||
if special.process_parameters_id not in process_parameters:
|
|
||||||
process_parameters.append(special.process_parameters_id.display_name)
|
|
||||||
|
|
||||||
if account_moves:
|
|
||||||
raise UserError(_("请联系工厂生产经理对采购订单为%s生成的账单进行取消", ", ".join(account_moves)))
|
|
||||||
if parameters_not:
|
|
||||||
raise UserError(_("【工艺设计】-【工序】为%s未选择参数,请选择", ", ".join(parameters_not)))
|
|
||||||
if process_parameters:
|
|
||||||
raise UserError(_("【工艺设计】-【参数】为%s的在【产品】中不存在,请先创建", ", ".join(process_parameters)))
|
|
||||||
# 判断同一个加工面的标准工序的顺序是否依次排序
|
|
||||||
error_panel = []
|
|
||||||
technology_design = self.technology_design_ids.filtered(lambda a: a.routing_tag == 'standard').sorted(
|
|
||||||
key=lambda m: m.sequence)
|
|
||||||
for index, design in enumerate(technology_design):
|
|
||||||
routing_type = design.route_id.routing_type
|
|
||||||
if index < len(technology_design) - 1:
|
|
||||||
next_index = index + 1
|
|
||||||
next_design = technology_design[next_index]
|
|
||||||
next_design_routing_type = next_design.route_id.routing_type
|
|
||||||
# logging.info('当前工序和加工面: %s-%s' % (design.route_id.name, design.panel))
|
|
||||||
# logging.info('下一个工序和加工面: %s-%s' % (next_design.route_id.name, next_design.panel))
|
|
||||||
if design.panel is not False:
|
|
||||||
if design.panel != next_design.panel:
|
|
||||||
if index == 0:
|
|
||||||
raise UserError('【加工面】为%s的标准工序里含有其他加工面的工序,请调整后重试' % design.panel)
|
|
||||||
if routing_type not in ['解除装夹']:
|
|
||||||
raise UserError('【加工面】为%s的标准工序顺序有误,请调整后重试' % design.panel)
|
|
||||||
if design.panel == next_design.panel:
|
|
||||||
if (routing_type == '装夹预调' and next_design_routing_type == '解除装夹') or (
|
|
||||||
routing_type == 'CNC加工' and next_design_routing_type == '装夹预调'):
|
|
||||||
if design.panel not in error_panel:
|
|
||||||
error_panel.append(design.panel)
|
|
||||||
else:
|
|
||||||
if not error_panel and not process_parameters:
|
|
||||||
production_count = self.env['mrp.production'].search_count([
|
|
||||||
('origin', '=', self.origin),
|
|
||||||
('product_id', '=', self.product_id.id),
|
|
||||||
('state', '=', 'technology_to_confirmed')
|
|
||||||
])
|
|
||||||
if production_count > 1:
|
|
||||||
return {
|
|
||||||
'name': _('工艺确认'),
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'views': [(self.env.ref(
|
|
||||||
'sf_manufacturing.sf_production_technology_wizard_form_view').id,
|
|
||||||
'form')],
|
|
||||||
'res_model': 'sf.production.technology.wizard',
|
|
||||||
'target': 'new',
|
|
||||||
'context': {
|
|
||||||
'default_production_id': self.id,
|
|
||||||
'default_origin': self.origin,
|
|
||||||
}}
|
|
||||||
else:
|
|
||||||
return {
|
|
||||||
'name': _('工艺确认'),
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
'views': [(self.env.ref(
|
|
||||||
'sf_manufacturing.sf_production_technology_wizard_confirm_form_view').id,
|
|
||||||
'form')],
|
|
||||||
'res_model': 'sf.production.technology.wizard',
|
|
||||||
'target': 'new',
|
|
||||||
'context': {
|
|
||||||
'default_production_id': self.id,
|
|
||||||
'default_origin': self.origin,
|
|
||||||
}}
|
|
||||||
if error_panel:
|
|
||||||
raise UserError(_("【加工面】为%s的标准工序顺序有误,请调整后重试", ", ".join(error_panel)))
|
|
||||||
return True
|
|
||||||
|
|
||||||
def action_check(self):
|
def action_check(self):
|
||||||
"""
|
"""
|
||||||
@@ -724,8 +439,8 @@ class MrpProduction(models.Model):
|
|||||||
if self.move_finished_ids.filtered(lambda m: m.product_id == self.product_id).move_line_ids:
|
if self.move_finished_ids.filtered(lambda m: m.product_id == self.product_id).move_line_ids:
|
||||||
self.move_finished_ids.filtered(
|
self.move_finished_ids.filtered(
|
||||||
lambda m: m.product_id == self.product_id).move_line_ids.lot_id = self.lot_producing_id
|
lambda m: m.product_id == self.product_id).move_line_ids.lot_id = self.lot_producing_id
|
||||||
# if self.product_id.tracking == 'serial':
|
if self.product_id.tracking == 'serial':
|
||||||
# self._set_qty_producing()
|
self._set_qty_producing()
|
||||||
|
|
||||||
# 重载根据工序生成工单的程序:如果产品BOM中没有工序时,
|
# 重载根据工序生成工单的程序:如果产品BOM中没有工序时,
|
||||||
# 根据产品对应的模板类型中工序,去生成工单;
|
# 根据产品对应的模板类型中工序,去生成工单;
|
||||||
@@ -761,89 +476,121 @@ class MrpProduction(models.Model):
|
|||||||
'operation_id': operation.id,
|
'operation_id': operation.id,
|
||||||
'state': 'pending',
|
'state': 'pending',
|
||||||
}]
|
}]
|
||||||
if production.product_id.categ_id.type in ['成品', '坯料']:
|
if production.product_id.categ_id.type == '成品':
|
||||||
# # 根据工序设计生成工单
|
# # 根据加工面板的面数及对应的工序模板生成工单
|
||||||
technology_design_ids = sorted(production.technology_design_ids, key=lambda x: x.sequence)
|
i = 0
|
||||||
for route in technology_design_ids:
|
processing_panel_len = len(production.product_id.model_processing_panel.split(','))
|
||||||
workorder_has = self.env['mrp.workorder'].search(
|
for k in (production.product_id.model_processing_panel.split(',')):
|
||||||
[('technology_design_id', '=', route.id), ('production_id', '=', production.id)])
|
product_routing_workcenter = self.env['sf.product.model.type.routing.sort'].search(
|
||||||
if not workorder_has:
|
[('product_model_type_id', '=', production.product_id.product_model_type_id.id)],
|
||||||
if route.route_id.routing_type not in ['表面工艺']:
|
order='sequence asc'
|
||||||
|
)
|
||||||
|
i += 1
|
||||||
|
for route in product_routing_workcenter:
|
||||||
|
if route.is_repeat is True:
|
||||||
workorders_values.append(
|
workorders_values.append(
|
||||||
self.env['mrp.workorder'].json_workorder_str(production, route))
|
self.env['mrp.workorder'].json_workorder_str(k, production, route, item))
|
||||||
else:
|
# if i == processing_panel_len and route.routing_type == '解除装夹':
|
||||||
|
# workorders_values.append(
|
||||||
|
# self.env['mrp.workorder'].json_workorder_str(k, production, route))
|
||||||
|
# 表面工艺工序
|
||||||
|
# 获取表面工艺id
|
||||||
|
# 工序id
|
||||||
|
surface_technics_arr = []
|
||||||
|
route_workcenter_arr = []
|
||||||
|
for item in production.product_id.product_model_type_id.surface_technics_routing_tmpl_ids:
|
||||||
|
if item.route_workcenter_id.surface_technics_id.id:
|
||||||
|
for process_param in production.product_id.model_process_parameters_ids:
|
||||||
|
logging.info('process_param:%s%s' % (process_param.id, process_param.name))
|
||||||
|
if item.route_workcenter_id.surface_technics_id == process_param.process_id:
|
||||||
|
logging.info(
|
||||||
|
'surface_technics_id:%s%s' % (item.route_workcenter_id.surface_technics_id.id,
|
||||||
|
item.route_workcenter_id.surface_technics_id.name))
|
||||||
|
surface_technics_arr.append(item.route_workcenter_id.surface_technics_id.id)
|
||||||
|
route_workcenter_arr.append(item.route_workcenter_id.id)
|
||||||
|
if surface_technics_arr:
|
||||||
|
production_process = self.env['sf.production.process'].search(
|
||||||
|
[('id', 'in', surface_technics_arr)],
|
||||||
|
order='sequence asc'
|
||||||
|
)
|
||||||
|
for p in production_process:
|
||||||
|
logging.info('production_process:%s' % p.name)
|
||||||
|
# if production_process:
|
||||||
|
process_parameter = production.product_id.model_process_parameters_ids.filtered(
|
||||||
|
lambda pm: pm.process_id.id == p.id)
|
||||||
|
if process_parameter:
|
||||||
|
# 产品为表面工艺服务的供应商
|
||||||
product_production_process = self.env['product.template'].search(
|
product_production_process = self.env['product.template'].search(
|
||||||
[('server_product_process_parameters_id', '=', route.process_parameters_id.id)])
|
[('server_product_process_parameters_id', '=', process_parameter.id)])
|
||||||
workorders_values.append(
|
if product_production_process:
|
||||||
self.env[
|
route_production_process = self.env[
|
||||||
'mrp.workorder']._json_workorder_surface_process_str(
|
'mrp.routing.workcenter'].search(
|
||||||
production, route, product_production_process.seller_ids[0].partner_id.id))
|
[('surface_technics_id', '=', p.id),
|
||||||
|
('id', 'in', route_workcenter_arr)])
|
||||||
|
if route_production_process:
|
||||||
|
workorders_values.append(
|
||||||
|
self.env[
|
||||||
|
'mrp.workorder']._json_workorder_surface_process_str(
|
||||||
|
production, route_production_process,
|
||||||
|
process_parameter,
|
||||||
|
product_production_process.seller_ids[0].partner_id.id))
|
||||||
|
elif production.product_id.categ_id.type == '坯料':
|
||||||
|
embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search(
|
||||||
|
[('embryo_model_type_id', '=', production.product_id.embryo_model_type_id.id)],
|
||||||
|
order='sequence asc'
|
||||||
|
)
|
||||||
|
for route in embryo_routing_workcenter:
|
||||||
|
workorders_values.append(
|
||||||
|
self.env['mrp.workorder'].json_workorder_str('', production, route))
|
||||||
production.workorder_ids = workorders_values
|
production.workorder_ids = workorders_values
|
||||||
for workorder in production.workorder_ids:
|
# for production_item in productions:
|
||||||
workorder.duration_expected = workorder._get_duration_expected()
|
|
||||||
|
|
||||||
# 外协出入库单处理
|
|
||||||
def get_subcontract_pick_purchase(self):
|
|
||||||
production_all = self.sorted(lambda x: x.id)
|
|
||||||
product_id_to_production_names = {}
|
|
||||||
grouped_product_ids = {k: list(g) for k, g in
|
|
||||||
groupby(production_all, key=lambda x: x.product_id.id)}
|
|
||||||
for product_id, pd in grouped_product_ids.items():
|
|
||||||
product_id_to_production_names[product_id] = [p.name for p in pd]
|
|
||||||
for production in production_all:
|
|
||||||
proc_workorders = []
|
|
||||||
process_parameter_workorder = self.env['mrp.workorder'].search(
|
process_parameter_workorder = self.env['mrp.workorder'].search(
|
||||||
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id),
|
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id),
|
||||||
('is_subcontract', '=', True), ('state', '!=', 'cancel')], order='sequence asc')
|
('is_subcontract', '=', True)])
|
||||||
if process_parameter_workorder:
|
if process_parameter_workorder:
|
||||||
# 将这些特殊表面工艺工单的采购单与调拨单置为失效
|
is_pick = False
|
||||||
for workorder in process_parameter_workorder:
|
|
||||||
workorder._get_surface_technics_purchase_ids().write({'state': 'cancel'})
|
|
||||||
workorder.move_subcontract_workorder_ids.write({'state': 'cancel'})
|
|
||||||
workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'cancel'})
|
|
||||||
consecutive_workorders = []
|
consecutive_workorders = []
|
||||||
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.sequence)
|
m = 0
|
||||||
# for i, workorder in enumerate(sorted_workorders):
|
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id)
|
||||||
# # 检查当前工作订单和下一个工作订单是否连续,并且供应商相同
|
for i in range(len(sorted_workorders) - 1):
|
||||||
# if i == 0:
|
if m == 0:
|
||||||
# consecutive_workorders.append(workorder)
|
is_pick = False
|
||||||
# elif workorder.sequence == sorted_workorders[
|
if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \
|
||||||
# i - 1].sequence + 1 and workorder.supplier_id.id == sorted_workorders[i - 1].supplier_id.id:
|
sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \
|
||||||
# consecutive_workorders.append(workorder)
|
sorted_workorders[i].id == sorted_workorders[i + 1].id - 1:
|
||||||
# else:
|
if sorted_workorders[i] not in consecutive_workorders:
|
||||||
# # 处理连续组,如果它不为空
|
consecutive_workorders.append(sorted_workorders[i])
|
||||||
# if consecutive_workorders:
|
consecutive_workorders.append(sorted_workorders[i + 1])
|
||||||
# proc_workorders.append(consecutive_workorders)
|
m += 1
|
||||||
# # 创建外协出入库单和采购订单
|
continue
|
||||||
# # self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production, sorted_workorders)
|
else:
|
||||||
# # self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
|
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||||
# # product_id_to_production_names)
|
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||||
# if i < len(sorted_workorders) - 1:
|
production)
|
||||||
# # 重置连续组,并添加当前工作订单
|
if sorted_workorders[i] in consecutive_workorders:
|
||||||
# consecutive_workorders = [workorder]
|
is_pick = True
|
||||||
# else:
|
consecutive_workorders = []
|
||||||
# # 判断最后一笔:
|
m = 0
|
||||||
# if workorder.sequence == sorted_workorders[
|
# 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单
|
||||||
# i - 1].sequence and workorder.supplier_id.id == sorted_workorders[
|
if is_pick is False:
|
||||||
# i - 1].supplier_id.id:
|
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i],
|
||||||
# consecutive_workorders = [workorder]
|
production)
|
||||||
# else:
|
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||||
# proc_workorders.append([workorder])
|
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||||
# # 立即创建外协出入库单和采购订单
|
production)
|
||||||
# # self.env['stock.picking'].create_outcontract_picking(workorder, production)
|
if sorted_workorders[i] in consecutive_workorders:
|
||||||
# # self.env['purchase.order'].get_purchase_order(workorder, production,
|
is_pick = True
|
||||||
# # product_id_to_production_names)
|
consecutive_workorders = []
|
||||||
# consecutive_workorders = []
|
m = 0
|
||||||
#
|
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||||
# # 处理最后一个组,即使它可能只有一个工作订单
|
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
|
||||||
# if consecutive_workorders:
|
if is_pick is False and m == 0:
|
||||||
# proc_workorders.append(consecutive_workorders)
|
if len(sorted_workorders) == 1:
|
||||||
# self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
|
self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production)
|
||||||
# self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
|
else:
|
||||||
# product_id_to_production_names)
|
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production)
|
||||||
for workorders in reversed(sorted_workorders):
|
for workorder in production.workorder_ids:
|
||||||
self.env['stock.picking'].create_outcontract_picking(workorders, production, sorted_workorders)
|
workorder.duration_expected = workorder._get_duration_expected()
|
||||||
self.env['purchase.order'].get_purchase_order(workorders, production, product_id_to_production_names)
|
|
||||||
|
|
||||||
# 工单排序
|
# 工单排序
|
||||||
def _reset_work_order_sequence1(self, k):
|
def _reset_work_order_sequence1(self, k):
|
||||||
@@ -911,85 +658,7 @@ class MrpProduction(models.Model):
|
|||||||
self._reset_work_order_sequence1(k)
|
self._reset_work_order_sequence1(k)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# 需对不连续工单对应的采购单和外协出入库单做处理
|
|
||||||
def _reset_subcontract_pick_purchase(self):
|
|
||||||
production_all = self.sorted(lambda x: x.id)
|
|
||||||
product_id_to_production_names = {}
|
|
||||||
grouped_product_ids = {k: list(g) for k, g in
|
|
||||||
groupby(production_all, key=lambda x: x.product_id.id)}
|
|
||||||
for product_id, pd in grouped_product_ids.items():
|
|
||||||
product_id_to_production_names[product_id] = [p.name for p in pd]
|
|
||||||
for item in production_all:
|
|
||||||
production_process = product_id_to_production_names.get(item.product_id.id)
|
|
||||||
workorder_sf = item.workorder_ids.filtered(lambda sf: sf.routing_type == '表面工艺')
|
|
||||||
for i, workorder in enumerate(workorder_sf):
|
|
||||||
if i == 0:
|
|
||||||
continue
|
|
||||||
elif workorder.sequence != workorder_sf[i - 1].sequence + 1:
|
|
||||||
# workorder.picking_ids.move_ids = False
|
|
||||||
workorder.picking_ids = False
|
|
||||||
purchase_order = self.env['purchase.order'].search(
|
|
||||||
[('state', '=', 'draft'), ('origin', '=', item.name),
|
|
||||||
('purchase_type', '=', 'consignment')])
|
|
||||||
server_template = self.env['product.template'].search(
|
|
||||||
[('server_product_process_parameters_id', '=',
|
|
||||||
workorder.surface_technics_parameters_id.id),
|
|
||||||
('detailed_type', '=', 'service')])
|
|
||||||
for po in purchase_order:
|
|
||||||
for line in po.order_line:
|
|
||||||
if line.product_id == server_template.product_variant_id:
|
|
||||||
continue
|
|
||||||
if server_template.server_product_process_parameters_id != line.product_id.server_product_process_parameters_id:
|
|
||||||
purchase_order_line = self.env['purchase.order.line'].search(
|
|
||||||
[('product_id', '=', server_template.product_variant_id.id), ('id', '=', line.id),
|
|
||||||
('product_qty', '=', 1)], limit=1, order='id desc')
|
|
||||||
if purchase_order_line:
|
|
||||||
line.unlink()
|
|
||||||
|
|
||||||
def _reset_work_order_sequence(self):
|
def _reset_work_order_sequence(self):
|
||||||
"""
|
|
||||||
工单工序排序方法(新)
|
|
||||||
"""
|
|
||||||
for rec in self:
|
|
||||||
workorder_ids = rec.workorder_ids
|
|
||||||
technology_design_ids = rec.technology_design_ids
|
|
||||||
if workorder_ids.filtered(lambda item: item.state in ('返工', 'rework')):
|
|
||||||
# 获取返工后新生成的工单
|
|
||||||
work_ids = workorder_ids.filtered(lambda item: item.sequence == 0)
|
|
||||||
# 对工单进行逐个插入
|
|
||||||
for work_id in work_ids:
|
|
||||||
order_rework_ids = rec.workorder_ids.filtered(
|
|
||||||
lambda item: (item.sequence > 0 and work_id.name == item.name
|
|
||||||
and work_id.processing_panel == item.processing_panel))
|
|
||||||
order_rework_ids = sorted(order_rework_ids, key=lambda item: item.sequence, reverse=True)
|
|
||||||
work_id.sequence = order_rework_ids[0].sequence + 1
|
|
||||||
# 对该工单之后的工单工序进行加一
|
|
||||||
work_order_ids = rec.workorder_ids.filtered(
|
|
||||||
lambda item: item.sequence >= work_id.sequence and item.id != work_id.id)
|
|
||||||
for work in work_order_ids:
|
|
||||||
work.sequence = work.sequence + 1
|
|
||||||
|
|
||||||
else:
|
|
||||||
# 将工艺设计生成的工单序号赋值给工单的序号
|
|
||||||
for work in workorder_ids:
|
|
||||||
td_ids = technology_design_ids.filtered(
|
|
||||||
lambda item: (item.route_id.name in work.name and item.process_parameters_id
|
|
||||||
and item.process_parameters_id == work.surface_technics_parameters_id) or
|
|
||||||
(item.route_id.name == work.name and item.panel
|
|
||||||
and item.panel == work.processing_panel))
|
|
||||||
if td_ids:
|
|
||||||
work.sequence = td_ids[0].sequence
|
|
||||||
cancel_work_ids = workorder_ids.filtered(lambda item: item.state in ('已取消', 'cancel'))
|
|
||||||
if cancel_work_ids:
|
|
||||||
sequence = max(workorder_ids.filtered(lambda item: item.state not in ('已取消', 'cancel')),
|
|
||||||
key=lambda w: w.sequence).sequence
|
|
||||||
for cw in cancel_work_ids:
|
|
||||||
cw.sequence = sequence + 1
|
|
||||||
|
|
||||||
def _reset_work_order_sequence_1(self):
|
|
||||||
"""
|
|
||||||
工单工序排序方法(旧)
|
|
||||||
"""
|
|
||||||
for rec in self:
|
for rec in self:
|
||||||
workorder_ids = rec.workorder_ids.filtered(lambda item: item.state in ('返工', 'rework'))
|
workorder_ids = rec.workorder_ids.filtered(lambda item: item.state in ('返工', 'rework'))
|
||||||
# 产品模型类型
|
# 产品模型类型
|
||||||
@@ -1085,32 +754,52 @@ class MrpProduction(models.Model):
|
|||||||
self._reset_work_order_sequence()
|
self._reset_work_order_sequence()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def production_process(self, pro_plan):
|
|
||||||
type_map = {'装夹预调': False, 'CNC加工': False, '解除装夹': False}
|
|
||||||
# 最后一次加工结束时间
|
|
||||||
last_time = pro_plan.date_planned_start
|
|
||||||
# 预置时间
|
|
||||||
works = self.workorder_ids
|
|
||||||
for index, work in enumerate(works):
|
|
||||||
count = type_map.get(work.routing_type)
|
|
||||||
date_planned_end = None
|
|
||||||
date_planned_start = None
|
|
||||||
if self.production_type == '自动化产线加工':
|
|
||||||
date_planned_start, date_planned_end, last_time = work.auto_production_process(last_time, count,
|
|
||||||
type_map)
|
|
||||||
elif self.production_type == '':
|
|
||||||
date_planned_start, date_planned_end, last_time = work.manual_offline_process(last_time, index)
|
|
||||||
work.update_work_start_end(date_planned_start, date_planned_end)
|
|
||||||
|
|
||||||
# def
|
|
||||||
def process_range_time(self):
|
def process_range_time(self):
|
||||||
for production in self:
|
for production in self:
|
||||||
works = production.workorder_ids
|
works = production.workorder_ids
|
||||||
pro_plan = self.env['sf.production.plan'].search([('production_id', '=', production.id)], limit=1)
|
pro_plan = self.env['sf.production.plan'].search([('production_id', '=', production.id)], limit=1)
|
||||||
if not pro_plan:
|
if not pro_plan:
|
||||||
continue
|
continue
|
||||||
if production.production_type:
|
type_map = {'装夹预调': False, 'CNC加工': False, '解除装夹': False}
|
||||||
production.production_process(pro_plan)
|
# 最后一次加工结束时间
|
||||||
|
last_time = pro_plan.date_planned_start
|
||||||
|
# 预置时间
|
||||||
|
for work in works:
|
||||||
|
count = type_map.get(work.routing_type)
|
||||||
|
date_planned_end = None
|
||||||
|
date_planned_start = None
|
||||||
|
duration_expected = datetime.timedelta(minutes=work.duration_expected)
|
||||||
|
reserve_time = datetime.timedelta(minutes=work.reserved_duration)
|
||||||
|
if not count:
|
||||||
|
# 第一轮加工
|
||||||
|
if work.routing_type == '装夹预调':
|
||||||
|
date_planned_end = last_time - reserve_time
|
||||||
|
date_planned_start = date_planned_end - duration_expected
|
||||||
|
elif work.routing_type == 'CNC加工':
|
||||||
|
date_planned_start = last_time
|
||||||
|
date_planned_end = last_time + duration_expected
|
||||||
|
last_time = date_planned_end
|
||||||
|
else:
|
||||||
|
date_planned_start = last_time + reserve_time
|
||||||
|
date_planned_end = date_planned_start + duration_expected
|
||||||
|
last_time = date_planned_end
|
||||||
|
type_map.update({work.routing_type: True})
|
||||||
|
else:
|
||||||
|
date_planned_start = last_time + reserve_time
|
||||||
|
date_planned_end = date_planned_start + duration_expected
|
||||||
|
last_time = date_planned_end
|
||||||
|
work.leave_id.write({
|
||||||
|
'date_from': date_planned_start,
|
||||||
|
'date_to': date_planned_end,
|
||||||
|
})
|
||||||
|
# work.write({'date_planned_start': date_planned_start, 'date_planned_finished': date_planned_end})
|
||||||
|
work.date_planned_start = date_planned_start
|
||||||
|
work.date_planned_finished = date_planned_end
|
||||||
|
routing_workcenter = self.env['mrp.routing.workcenter'].sudo().search(
|
||||||
|
[('name', '=', work.routing_type)])
|
||||||
|
|
||||||
|
work.write({'date_planned_start': date_planned_start, 'date_planned_finished': date_planned_end,
|
||||||
|
'duration_expected': routing_workcenter.time_cycle})
|
||||||
|
|
||||||
# 修改标记已完成方法
|
# 修改标记已完成方法
|
||||||
def button_mark_done1(self):
|
def button_mark_done1(self):
|
||||||
@@ -1134,7 +823,6 @@ class MrpProduction(models.Model):
|
|||||||
backorders = backorders - productions_to_backorder
|
backorders = backorders - productions_to_backorder
|
||||||
|
|
||||||
productions_not_to_backorder._post_inventory(cancel_backorder=True)
|
productions_not_to_backorder._post_inventory(cancel_backorder=True)
|
||||||
# 查出最后一张工单完成入库操作
|
|
||||||
# if self.workorder_ids.filtered(lambda w: w.routing_type in ['表面工艺']):
|
# if self.workorder_ids.filtered(lambda w: w.routing_type in ['表面工艺']):
|
||||||
# move_finish = self.env['stock.move'].search([('created_production_id', '=', self.id)])
|
# move_finish = self.env['stock.move'].search([('created_production_id', '=', self.id)])
|
||||||
# if move_finish:
|
# if move_finish:
|
||||||
@@ -1235,16 +923,6 @@ class MrpProduction(models.Model):
|
|||||||
cloud_programming = None
|
cloud_programming = None
|
||||||
if self.programming_state in ['已编程']:
|
if self.programming_state in ['已编程']:
|
||||||
cloud_programming = self._cron_get_programming_state()
|
cloud_programming = self._cron_get_programming_state()
|
||||||
result_ids = self.detection_result_ids.filtered(lambda dr: dr.handle_result == '待处理')
|
|
||||||
work_id_list = []
|
|
||||||
if result_ids:
|
|
||||||
work_id_list = [self.workorder_ids.filtered(
|
|
||||||
lambda wk: (wk.name == result_id.routing_type and wk.processing_panel == result_id.processing_panel
|
|
||||||
and wk.state == 'done')).id
|
|
||||||
for result_id in result_ids]
|
|
||||||
workorder_ids = self.workorder_ids.filtered(
|
|
||||||
lambda wk: wk.technology_design_id.routing_tag == 'standard' and wk.state not in ['rework', 'cancel'])
|
|
||||||
logging.info('标准工艺工单【%s】' % workorder_ids)
|
|
||||||
return {
|
return {
|
||||||
'name': _('返工'),
|
'name': _('返工'),
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
@@ -1253,8 +931,6 @@ class MrpProduction(models.Model):
|
|||||||
'target': 'new',
|
'target': 'new',
|
||||||
'context': {
|
'context': {
|
||||||
'default_production_id': self.id,
|
'default_production_id': self.id,
|
||||||
'default_workorder_ids': workorder_ids.ids if workorder_ids.ids != [] else self.workorder_ids.ids,
|
|
||||||
'default_hidden_workorder_ids': ','.join(map(str, work_id_list)) if work_id_list != [] else '',
|
|
||||||
'default_reprogramming_num': cloud_programming['reprogramming_num'],
|
'default_reprogramming_num': cloud_programming['reprogramming_num'],
|
||||||
'default_programming_state': cloud_programming['programming_state'],
|
'default_programming_state': cloud_programming['programming_state'],
|
||||||
'default_is_reprogramming': True if cloud_programming['programming_state'] in ['已下发'] else False
|
'default_is_reprogramming': True if cloud_programming['programming_state'] in ['已下发'] else False
|
||||||
@@ -1408,15 +1084,13 @@ class MrpProduction(models.Model):
|
|||||||
raise_user_error=not self.env.context.get('from_orderpoint'))
|
raise_user_error=not self.env.context.get('from_orderpoint'))
|
||||||
productions = self.env['mrp.production'].sudo().search(
|
productions = self.env['mrp.production'].sudo().search(
|
||||||
[('origin', '=', self.origin)], order='id desc', limit=1)
|
[('origin', '=', self.origin)], order='id desc', limit=1)
|
||||||
productions.write({'programming_no': self.programming_no, 'is_remanufacture': True})
|
|
||||||
move = self.env['stock.move'].search([('origin', '=', productions.name)], order='id desc')
|
move = self.env['stock.move'].search([('origin', '=', productions.name)], order='id desc')
|
||||||
for mo in move:
|
for mo in move:
|
||||||
domain = []
|
if mo.procure_method == 'make_to_order' and mo.name != productions.name:
|
||||||
if mo.location_id.barcode == 'WH-POSTPRODUCTION' and mo.rule_id.picking_type_id.barcode == 'PC':
|
if mo.name == '/':
|
||||||
domain = [('barcode', '=', 'WH-PC'), ('sequence_code', '=', 'PC')]
|
domain = [('barcode', '=', 'WH-PC'), ('sequence_code', '=', 'PC')]
|
||||||
elif mo.location_id.barcode == 'PL' and mo.rule_id.picking_type_id.barcode == 'INT':
|
elif mo.name == '拉':
|
||||||
domain = [('barcode', '=', 'WH-INTERNAL'), ('sequence_code', '=', 'INT')]
|
domain = [('barcode', '=', 'WH-INTERNAL'), ('sequence_code', '=', 'INT')]
|
||||||
if domain:
|
|
||||||
picking_type = self.env['stock.picking.type'].search(domain)
|
picking_type = self.env['stock.picking.type'].search(domain)
|
||||||
mo.write({'picking_type_id': picking_type.id})
|
mo.write({'picking_type_id': picking_type.id})
|
||||||
mo._assign_picking()
|
mo._assign_picking()
|
||||||
@@ -1434,6 +1108,7 @@ class MrpProduction(models.Model):
|
|||||||
mo_move.write({'reference': sfp_move.reference, 'partner_id': sfp_move.partner_id.id,
|
mo_move.write({'reference': sfp_move.reference, 'partner_id': sfp_move.partner_id.id,
|
||||||
'picking_id': sfp_move.picking_id.id, 'picking_type_id': sfp_move.picking_type_id.id,
|
'picking_id': sfp_move.picking_id.id, 'picking_type_id': sfp_move.picking_type_id.id,
|
||||||
'production_id': False})
|
'production_id': False})
|
||||||
|
productions.write({'programming_no': self.programming_no, 'is_remanufacture': True})
|
||||||
# productions.procurement_group_id.mrp_production_ids.move_dest_ids.write(
|
# productions.procurement_group_id.mrp_production_ids.move_dest_ids.write(
|
||||||
# {'group_id': self.env['procurement.group'].search([('name', '=', sale_order.name)])})
|
# {'group_id': self.env['procurement.group'].search([('name', '=', sale_order.name)])})
|
||||||
stock_picking_remanufacture = self.env['stock.picking'].search([('origin', '=', productions.name)])
|
stock_picking_remanufacture = self.env['stock.picking'].search([('origin', '=', productions.name)])
|
||||||
@@ -1467,6 +1142,7 @@ class MrpProduction(models.Model):
|
|||||||
if purchase_orders.origin.find(productions.name) == -1:
|
if purchase_orders.origin.find(productions.name) == -1:
|
||||||
purchase_orders.origin += ',' + productions.name
|
purchase_orders.origin += ',' + productions.name
|
||||||
if item['is_reprogramming'] is False:
|
if item['is_reprogramming'] is False:
|
||||||
|
productions._create_workorder(item)
|
||||||
productions.programming_state = '已编程'
|
productions.programming_state = '已编程'
|
||||||
else:
|
else:
|
||||||
productions.programming_state = '编程中'
|
productions.programming_state = '编程中'
|
||||||
@@ -1496,131 +1172,6 @@ class MrpProduction(models.Model):
|
|||||||
'user_id': production.user_id.id}
|
'user_id': production.user_id.id}
|
||||||
return production_values_str
|
return production_values_str
|
||||||
|
|
||||||
# 增加制造订单类型
|
|
||||||
production_type = fields.Selection(
|
|
||||||
[('自动化产线加工', '自动化产线加工'), ('人工线下加工', '人工线下加工')],
|
|
||||||
string='制造类型',
|
|
||||||
compute='_compute_production_type',
|
|
||||||
store=True
|
|
||||||
)
|
|
||||||
|
|
||||||
@api.depends('product_id.is_manual_processing')
|
|
||||||
def _compute_production_type(self):
|
|
||||||
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):
|
|
||||||
"""
|
|
||||||
重载创建制造订单的方法,单个制造订单,同一成品只创建一个采购组,用于后续单据的创建
|
|
||||||
"""
|
|
||||||
product_group_id = {}
|
|
||||||
for vals in vals_list:
|
|
||||||
if not vals.get('name', False) or vals['name'] == _('New'):
|
|
||||||
picking_type_id = vals.get('picking_type_id')
|
|
||||||
if not picking_type_id:
|
|
||||||
picking_type_id = self._get_default_picking_type_id(vals.get('company_id', self.env.company.id))
|
|
||||||
vals['picking_type_id'] = picking_type_id
|
|
||||||
vals['name'] = self.env['stock.picking.type'].browse(picking_type_id).sequence_id.next_by_id()
|
|
||||||
if not vals.get('procurement_group_id'):
|
|
||||||
product_id = self.env['product.product'].browse(vals['product_id'])
|
|
||||||
if product_id.product_tmpl_id.single_manufacturing:
|
|
||||||
if product_id.id not in product_group_id.keys():
|
|
||||||
procurement_group_vals = self._prepare_procurement_group_vals(vals)
|
|
||||||
group_id = self.env["procurement.group"].create(procurement_group_vals).id
|
|
||||||
vals['procurement_group_id'] = group_id
|
|
||||||
product_group_id[product_id.id] = group_id
|
|
||||||
else:
|
|
||||||
vals['procurement_group_id'] = product_group_id[product_id.id]
|
|
||||||
return super(MrpProduction, self).create(vals_list)
|
|
||||||
|
|
||||||
@api.depends('procurement_group_id.stock_move_ids.created_purchase_line_id.order_id',
|
|
||||||
'procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id')
|
|
||||||
def _compute_purchase_order_count(self):
|
|
||||||
for production in self:
|
|
||||||
# 找到来源的第一张制造订单的采购组
|
|
||||||
if production.product_id.product_tmpl_id.single_manufacturing == True:
|
|
||||||
first_production = self.env['mrp.production'].search(
|
|
||||||
[('origin', '=', production.origin), ('product_id', '=', production.product_id.id)], limit=1,
|
|
||||||
order='id asc')
|
|
||||||
production.purchase_order_count = len(
|
|
||||||
first_production.procurement_group_id.stock_move_ids.created_purchase_line_id.order_id |
|
|
||||||
first_production.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id)
|
|
||||||
else:
|
|
||||||
production.purchase_order_count = len(
|
|
||||||
production.procurement_group_id.stock_move_ids.created_purchase_line_id.order_id |
|
|
||||||
production.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id)
|
|
||||||
|
|
||||||
@api.depends('procurement_group_id', 'procurement_group_id.stock_move_ids.group_id')
|
|
||||||
def _compute_picking_ids(self):
|
|
||||||
for order in self:
|
|
||||||
if order.product_id.product_tmpl_id.single_manufacturing == True:
|
|
||||||
first_order = self.env['mrp.production'].search(
|
|
||||||
[('origin', '=', order.origin), ('product_id', '=', order.product_id.id)], limit=1, order='id asc')
|
|
||||||
order.picking_ids = self.env['stock.picking'].search([
|
|
||||||
('group_id', '!=', False), ('state', '!=', 'cancel'),
|
|
||||||
'|', # 表示“或”的开始
|
|
||||||
('group_id', '=', order.procurement_group_id.id),
|
|
||||||
('related_group_ids', '=', order.procurement_group_id.id)
|
|
||||||
])
|
|
||||||
order.delivery_count = len(first_order.picking_ids)
|
|
||||||
else:
|
|
||||||
order.picking_ids = self.env['stock.picking'].search([
|
|
||||||
('group_id', '!=', False),('state', '!=', 'cancel'),
|
|
||||||
'|', # 表示“或”的开始
|
|
||||||
('group_id', '=', order.procurement_group_id.id),
|
|
||||||
('related_group_ids', '=', order.procurement_group_id.id)
|
|
||||||
])
|
|
||||||
order.delivery_count = len(order.picking_ids)
|
|
||||||
|
|
||||||
def action_view_purchase_orders(self):
|
|
||||||
self.ensure_one()
|
|
||||||
if self.is_remanufacture:
|
|
||||||
production = self
|
|
||||||
elif self.product_id.product_tmpl_id.single_manufacturing == True:
|
|
||||||
production = self.env['mrp.production'].search(
|
|
||||||
[('origin', '=', self.origin), ('product_id', '=', self.product_id.id)], limit=1, order='id asc')
|
|
||||||
else:
|
|
||||||
production = self
|
|
||||||
purchase_order_ids = (
|
|
||||||
production.procurement_group_id.stock_move_ids.created_purchase_line_id.order_id | production.procurement_group_id.stock_move_ids.move_orig_ids.purchase_line_id.order_id).ids
|
|
||||||
action = {
|
|
||||||
'res_model': 'purchase.order',
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
}
|
|
||||||
if len(purchase_order_ids) == 1:
|
|
||||||
action.update({
|
|
||||||
'view_mode': 'form',
|
|
||||||
'res_id': purchase_order_ids[0],
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
action.update({
|
|
||||||
'name': _("Purchase Order generated from %s", self.name),
|
|
||||||
'domain': [('id', 'in', purchase_order_ids)],
|
|
||||||
'view_mode': 'tree,form',
|
|
||||||
})
|
|
||||||
return action
|
|
||||||
|
|
||||||
|
|
||||||
class sf_detection_result(models.Model):
|
class sf_detection_result(models.Model):
|
||||||
_name = 'sf.detection.result'
|
_name = 'sf.detection.result'
|
||||||
@@ -1650,6 +1201,10 @@ class sf_detection_result(models.Model):
|
|||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
'res_id': self.id,
|
'res_id': self.id,
|
||||||
'views': [(self.env.ref('sf_manufacturing.sf_test_report_form').id, 'form')],
|
'views': [(self.env.ref('sf_manufacturing.sf_test_report_form').id, 'form')],
|
||||||
|
# 'view_mode': 'form',
|
||||||
|
# 'context': {
|
||||||
|
# 'default_id': self.id
|
||||||
|
# },
|
||||||
'target': 'new'
|
'target': 'new'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,25 +7,21 @@ class ResMrpRoutingWorkcenter(models.Model):
|
|||||||
_inherit = 'mrp.routing.workcenter'
|
_inherit = 'mrp.routing.workcenter'
|
||||||
|
|
||||||
routing_type = fields.Selection([
|
routing_type = fields.Selection([
|
||||||
|
# ('获取CNC加工程序', '获取CNC加工程序'),
|
||||||
('装夹预调', '装夹预调'),
|
('装夹预调', '装夹预调'),
|
||||||
|
# ('前置三元定位检测', '前置三元定位检测'),
|
||||||
('CNC加工', 'CNC加工'),
|
('CNC加工', 'CNC加工'),
|
||||||
|
# ('后置三元质量检测', '后置三元质量检测'),
|
||||||
('解除装夹', '解除装夹'),
|
('解除装夹', '解除装夹'),
|
||||||
('切割', '切割'),
|
('切割', '切割'),
|
||||||
('表面工艺', '表面工艺'),
|
('表面工艺', '表面工艺')
|
||||||
('线切割', '线切割'),
|
|
||||||
('人工线下加工', '人工线下加工')
|
|
||||||
], string="工序类型")
|
], string="工序类型")
|
||||||
routing_tag = fields.Selection([
|
|
||||||
('standard', '标准'),
|
|
||||||
('special', '特殊')
|
|
||||||
], string="标签")
|
|
||||||
is_repeat = fields.Boolean('重复', default=False)
|
is_repeat = fields.Boolean('重复', default=False)
|
||||||
workcenter_id = fields.Many2one('mrp.workcenter', required=False)
|
workcenter_id = fields.Many2one('mrp.workcenter', required=False)
|
||||||
workcenter_ids = fields.Many2many('mrp.workcenter', 'rel_workcenter_route', required=True)
|
workcenter_ids = fields.Many2many('mrp.workcenter', 'rel_workcenter_route', required=True)
|
||||||
bom_id = fields.Many2one('mrp.bom', required=False)
|
bom_id = fields.Many2one('mrp.bom', required=False)
|
||||||
surface_technics_id = fields.Many2one('sf.production.process', string="表面工艺")
|
surface_technics_id = fields.Many2one('sf.production.process', string="表面工艺")
|
||||||
reserved_duration = fields.Float('预留时长', default=30, tracking=True)
|
reserved_duration = fields.Float('预留时长', default=30, tracking=True)
|
||||||
|
|
||||||
def get_no(self):
|
def get_no(self):
|
||||||
international_standards = self.search(
|
international_standards = self.search(
|
||||||
[('code', '!=', ''), ('active', 'in', [True, False])],
|
[('code', '!=', ''), ('active', 'in', [True, False])],
|
||||||
@@ -82,22 +78,3 @@ class ResMrpRoutingWorkcenter(models.Model):
|
|||||||
else:
|
else:
|
||||||
workcenter_id = workcenter_ids[0]
|
workcenter_id = workcenter_ids[0]
|
||||||
return workcenter_id
|
return workcenter_id
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
|
|
||||||
if self._context.get('production_id'):
|
|
||||||
route_ids = []
|
|
||||||
technology_design = self.env['sf.technology.design'].search(
|
|
||||||
[('production_id', '=', self._context.get('production_id'))])
|
|
||||||
for t in technology_design.filtered(lambda a: a.routing_tag == 'special'):
|
|
||||||
if not t.process_parameters_id:
|
|
||||||
route_ids.append(t.route_id.surface_technics_id.id)
|
|
||||||
domain = [('id', 'not in', route_ids), ('routing_tag', '=', 'special')]
|
|
||||||
return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
|
|
||||||
if self._context.get('is_duplicate') and self._context.get('model_name'):
|
|
||||||
# 查询出已经选择的工序
|
|
||||||
model_type = self.env[self._context.get('model_name')].search_read([],['route_workcenter_id'])
|
|
||||||
route_workcenter_ids = [item['route_workcenter_id'][0] if item['route_workcenter_id'] else False for item in model_type]
|
|
||||||
domain = args + [('id', 'not in', route_workcenter_ids)]
|
|
||||||
return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
|
|
||||||
return super()._name_search(name, args, operator, limit, name_get_uid)
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -16,12 +16,6 @@ from OCC.Extend.DataExchange import write_stl_file
|
|||||||
class ResProductMo(models.Model):
|
class ResProductMo(models.Model):
|
||||||
_inherit = 'product.template'
|
_inherit = 'product.template'
|
||||||
|
|
||||||
def _get_machining_precision(self):
|
|
||||||
machinings = self.env['sf.machining.accuracy'].sudo().search([])
|
|
||||||
|
|
||||||
list = [(m.sync_id, m.name) for m in machinings]
|
|
||||||
return list
|
|
||||||
|
|
||||||
model_file = fields.Binary('模型文件')
|
model_file = fields.Binary('模型文件')
|
||||||
categ_type = fields.Selection(string='产品的类别', related='categ_id.type', store=True)
|
categ_type = fields.Selection(string='产品的类别', related='categ_id.type', store=True)
|
||||||
model_name = fields.Char('模型名称')
|
model_name = fields.Char('模型名称')
|
||||||
@@ -29,7 +23,12 @@ class ResProductMo(models.Model):
|
|||||||
model_width = fields.Float('模型宽(mm)', digits=(16, 3))
|
model_width = fields.Float('模型宽(mm)', digits=(16, 3))
|
||||||
model_height = fields.Float('模型高(mm)', digits=(16, 3))
|
model_height = fields.Float('模型高(mm)', digits=(16, 3))
|
||||||
model_volume = fields.Float('模型体积(m³)')
|
model_volume = fields.Float('模型体积(m³)')
|
||||||
model_machining_precision = fields.Selection(selection=_get_machining_precision, string='加工精度')
|
model_machining_precision = fields.Selection([
|
||||||
|
('0.10', '±0.10mm'),
|
||||||
|
('0.05', '±0.05mm'),
|
||||||
|
('0.03', '±0.03mm'),
|
||||||
|
('0.02', '±0.02mm'),
|
||||||
|
('0.01', '±0.01mm')], string='加工精度')
|
||||||
model_processing_panel = fields.Char('模型加工面板')
|
model_processing_panel = fields.Char('模型加工面板')
|
||||||
model_remark = fields.Char('模型备注说明')
|
model_remark = fields.Char('模型备注说明')
|
||||||
length = fields.Float('长(mm)', digits=(16, 3))
|
length = fields.Float('长(mm)', digits=(16, 3))
|
||||||
@@ -141,11 +140,11 @@ class ResProductMo(models.Model):
|
|||||||
cutting_tool_coarse_medium_fine = fields.Selection(related='cutting_tool_model_id.integral_coarse_medium_fine', string='粗/中/精')
|
cutting_tool_coarse_medium_fine = fields.Selection(related='cutting_tool_model_id.integral_coarse_medium_fine', string='粗/中/精')
|
||||||
# cutting_tool_model_id.integral_coarse_medium_fine
|
# cutting_tool_model_id.integral_coarse_medium_fine
|
||||||
# cutting_tool_run_out_accuracy_max = fields.Float('端跳精度max', digits=(6, 1))
|
# cutting_tool_run_out_accuracy_max = fields.Float('端跳精度max', digits=(6, 1))
|
||||||
cutting_tool_run_out_accuracy_max = fields.Char(related='cutting_tool_model_id.integral_run_out_accuracy_max', string='端跳精度max')
|
cutting_tool_run_out_accuracy_max = fields.Char(related='cutting_tool_model_id.integral_run_out_accuracy_max', string='端跳精度max', digits=(6, 1))
|
||||||
# cutting_tool_model_id.integral_run_out_accuracy_max
|
# cutting_tool_model_id.integral_run_out_accuracy_max
|
||||||
# cutting_tool_run_out_accuracy_min = fields.Float('端跳精度min', digits=(6, 1))
|
# cutting_tool_run_out_accuracy_min = fields.Float('端跳精度min', digits=(6, 1))
|
||||||
cutting_tool_run_out_accuracy_min = fields.Char(related='cutting_tool_model_id.integral_run_out_accuracy_min',
|
cutting_tool_run_out_accuracy_min = fields.Char(related='cutting_tool_model_id.integral_run_out_accuracy_min',
|
||||||
string='端跳精度min')
|
string='端跳精度min', digits=(6, 1))
|
||||||
# cutting_tool_model_id.integral_run_out_accuracy_min
|
# cutting_tool_model_id.integral_run_out_accuracy_min
|
||||||
# cutting_tool_blade_tip_working_size = fields.Char('刀尖倒角度(°)', size=20)
|
# cutting_tool_blade_tip_working_size = fields.Char('刀尖倒角度(°)', size=20)
|
||||||
cutting_tool_blade_tip_working_size = fields.Char(related='specification_id.blade_tip_working_size',
|
cutting_tool_blade_tip_working_size = fields.Char(related='specification_id.blade_tip_working_size',
|
||||||
@@ -774,10 +773,10 @@ class ResProductMo(models.Model):
|
|||||||
|
|
||||||
# bfm下单
|
# bfm下单
|
||||||
manual_quotation = fields.Boolean('人工编程', default=False, readonly=True)
|
manual_quotation = fields.Boolean('人工编程', default=False, readonly=True)
|
||||||
|
part_number = fields.Char(string='零件图号', readonly=True)
|
||||||
machining_drawings = fields.Binary('2D加工图纸', readonly=True)
|
machining_drawings = fields.Binary('2D加工图纸', readonly=True)
|
||||||
quality_standard = fields.Binary('质检标准', readonly=True)
|
quality_standard = fields.Binary('质检标准', readonly=True)
|
||||||
part_name = fields.Char(string='零件名称', readonly=True)
|
|
||||||
part_number = fields.Char(string='零件图号', readonly=True)
|
|
||||||
@api.constrains('tool_length')
|
@api.constrains('tool_length')
|
||||||
def _check_tool_length_size(self):
|
def _check_tool_length_size(self):
|
||||||
if self.tool_length > 1000000:
|
if self.tool_length > 1000000:
|
||||||
@@ -838,34 +837,22 @@ class ResProductMo(models.Model):
|
|||||||
else:
|
else:
|
||||||
return self.env.ref('sf_dlm.product_uom_cubic_millimeter')
|
return self.env.ref('sf_dlm.product_uom_cubic_millimeter')
|
||||||
|
|
||||||
def attachment_update(self, name, res_id, res_field, mimetype):
|
|
||||||
attachment_info = self.env['ir.attachment'].sudo().search(
|
|
||||||
[('res_id', '=', res_id), ('res_field', '=', res_field)], limit=1)
|
|
||||||
attachment_info.write({'name': name, 'mimetype': mimetype})
|
|
||||||
|
|
||||||
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品
|
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品
|
||||||
def product_create(self, product_id, item, order_id, order_number, i):
|
def product_create(self, product_id, item, order_id, order_number, i):
|
||||||
copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
|
copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
|
||||||
copy_product_id.product_tmpl_id.active = True
|
copy_product_id.product_tmpl_id.active = True
|
||||||
model_type = self.env['sf.model.type'].search([], limit=1)
|
model_type = self.env['sf.model.type'].search([], limit=1)
|
||||||
attachment = self.attachment_create(item['model_name'], item['model_data'])
|
attachment = self.attachment_create(item['model_name'], item['model_data'])
|
||||||
# 获取坯料冗余配置
|
|
||||||
if not item.get('embryo_redundancy'):
|
|
||||||
embryo_redundancy_id = model_type.embryo_tolerance_id
|
|
||||||
else:
|
|
||||||
embryo_redundancy_id = item.get('embryo_redundancy')
|
|
||||||
if not embryo_redundancy_id:
|
|
||||||
raise UserError('请先配置模型类型内的坯料冗余')
|
|
||||||
vals = {
|
vals = {
|
||||||
'name': '%s-%s-%s' % ('P', order_id.name, i),
|
'name': '%s-%s-%s' % ('P', order_id.name, i),
|
||||||
'model_long': self.format_float(item['model_long'] + embryo_redundancy_id.long),
|
'model_long': item['model_long'] + model_type.embryo_tolerance,
|
||||||
'model_width': self.format_float(item['model_width'] + embryo_redundancy_id.width),
|
'model_width': item['model_width'] + model_type.embryo_tolerance,
|
||||||
'model_height': self.format_float(item['model_height'] + embryo_redundancy_id.height),
|
'model_height': item['model_height'] + model_type.embryo_tolerance,
|
||||||
'model_volume': self.format_float((item['model_long'] + embryo_redundancy_id.long) * (
|
'model_volume': (item['model_long'] + model_type.embryo_tolerance) * (
|
||||||
item['model_width'] + embryo_redundancy_id.width) * (
|
item['model_width'] + model_type.embryo_tolerance) * (
|
||||||
item['model_height'] + embryo_redundancy_id.height)),
|
item['model_height'] + model_type.embryo_tolerance),
|
||||||
'product_model_type_id': model_type.id,
|
'product_model_type_id': model_type.id,
|
||||||
'model_processing_panel': item['processing_panel_detail'],
|
# 'model_processing_panel': 'R',
|
||||||
'model_machining_precision': item['model_machining_precision'],
|
'model_machining_precision': item['model_machining_precision'],
|
||||||
'model_code': item['barcode'],
|
'model_code': item['barcode'],
|
||||||
'length': item['model_long'],
|
'length': item['model_long'],
|
||||||
@@ -873,8 +860,8 @@ class ResProductMo(models.Model):
|
|||||||
'height': item['model_height'],
|
'height': item['model_height'],
|
||||||
'volume': item['model_long'] * item['model_width'] * item['model_height'],
|
'volume': item['model_long'] * item['model_width'] * item['model_height'],
|
||||||
'model_file': '' if not item['model_file'] else base64.b64decode(item['model_file']),
|
'model_file': '' if not item['model_file'] else base64.b64decode(item['model_file']),
|
||||||
'model_name': attachment.name if attachment else None,
|
'model_name': attachment.name,
|
||||||
'upload_model_file': [(6, 0, [attachment.id])] if attachment else None,
|
'upload_model_file': [(6, 0, [attachment.id])],
|
||||||
'list_price': item['price'],
|
'list_price': item['price'],
|
||||||
'materials_id': self.env['sf.production.materials'].search(
|
'materials_id': self.env['sf.production.materials'].search(
|
||||||
[('materials_no', '=', item['texture_code'])]).id,
|
[('materials_no', '=', item['texture_code'])]).id,
|
||||||
@@ -888,10 +875,8 @@ class ResProductMo(models.Model):
|
|||||||
'manual_quotation': item['manual_quotation'] or False,
|
'manual_quotation': item['manual_quotation'] or False,
|
||||||
'part_number': item.get('part_number') or '',
|
'part_number': item.get('part_number') or '',
|
||||||
'active': True,
|
'active': True,
|
||||||
'machining_drawings': '' if not item['machining_drawings'] else base64.b64decode(
|
'machining_drawings': '' if not item['machining_drawings'] else base64.b64decode(item['machining_drawings']),
|
||||||
item['machining_drawings']),
|
'quality_standard': '' if not item['quality_standard'] else base64.b64decode(item['quality_standard']),
|
||||||
'quality_standard': '' if not item['quality_standard'] else base64.b64decode(item['quality_standard']),
|
|
||||||
'part_name': item.get('part_name') or '',
|
|
||||||
}
|
}
|
||||||
tax_id = self.env['account.tax'].sudo().search(
|
tax_id = self.env['account.tax'].sudo().search(
|
||||||
[('type_tax_use', '=', 'sale'), ('amount', '=', item.get('tax')), ('price_include', '=', 'True')])
|
[('type_tax_use', '=', 'sale'), ('amount', '=', item.get('tax')), ('price_include', '=', 'True')])
|
||||||
@@ -899,28 +884,8 @@ class ResProductMo(models.Model):
|
|||||||
vals.update({'taxes_id': [(6, 0, [int(tax_id)])]})
|
vals.update({'taxes_id': [(6, 0, [int(tax_id)])]})
|
||||||
copy_product_id.sudo().write(vals)
|
copy_product_id.sudo().write(vals)
|
||||||
product_id.product_tmpl_id.active = False
|
product_id.product_tmpl_id.active = False
|
||||||
if item['machining_drawings'] and item['machining_drawings_name'] and item['machining_drawings_mimetype']:
|
|
||||||
self.attachment_update(item['machining_drawings_name'], copy_product_id.product_tmpl_id.id,
|
|
||||||
'machining_drawings', item['machining_drawings_mimetype'])
|
|
||||||
if item['quality_standard'] and item['quality_standard_name'] and item['quality_standard_mimetype']:
|
|
||||||
self.attachment_update(item['quality_standard_name'], copy_product_id.product_tmpl_id.id,
|
|
||||||
'quality_standard', item['quality_standard_mimetype'])
|
|
||||||
return copy_product_id
|
return copy_product_id
|
||||||
|
|
||||||
def format_float(self, value):
|
|
||||||
# 将浮点数转换为字符串
|
|
||||||
value_str = str(value)
|
|
||||||
# 检查小数点的位置
|
|
||||||
if '.' in value_str:
|
|
||||||
# 获取小数部分
|
|
||||||
decimal_part = value_str.split('.')[1]
|
|
||||||
# 判断小数位数是否超过2位
|
|
||||||
if len(decimal_part) > 2:
|
|
||||||
# 超过2位则保留2位小数
|
|
||||||
return "{:.2f}".format(value)
|
|
||||||
# 否则保持原来的位数
|
|
||||||
return float(value_str)
|
|
||||||
|
|
||||||
def _get_ids(self, param):
|
def _get_ids(self, param):
|
||||||
type_ids = []
|
type_ids = []
|
||||||
if not param:
|
if not param:
|
||||||
@@ -937,8 +902,6 @@ class ResProductMo(models.Model):
|
|||||||
return [(6, 0, process_parameters_ids)]
|
return [(6, 0, process_parameters_ids)]
|
||||||
|
|
||||||
def attachment_create(self, name, data):
|
def attachment_create(self, name, data):
|
||||||
if not data:
|
|
||||||
return None
|
|
||||||
attachment = self.env['ir.attachment'].create({
|
attachment = self.env['ir.attachment'].create({
|
||||||
'datas': base64.b64decode(data),
|
'datas': base64.b64decode(data),
|
||||||
'type': 'binary',
|
'type': 'binary',
|
||||||
@@ -956,40 +919,31 @@ class ResProductMo(models.Model):
|
|||||||
# if surface_technology:
|
# if surface_technology:
|
||||||
# no_bom_copy_product_id.route_ids |= surface_technology
|
# no_bom_copy_product_id.route_ids |= surface_technology
|
||||||
no_bom_copy_product_id.product_tmpl_id.active = True
|
no_bom_copy_product_id.product_tmpl_id.active = True
|
||||||
logging.info('no_bom_copy_product_id[is_manual_processing]:%s' % no_bom_copy_product_id.is_manual_processing)
|
|
||||||
materials_id = self.env['sf.production.materials'].search(
|
materials_id = self.env['sf.production.materials'].search(
|
||||||
[('materials_no', '=', item['texture_code'])])
|
[('materials_no', '=', item['texture_code'])])
|
||||||
materials_type_id = self.env['sf.materials.model'].search(
|
materials_type_id = self.env['sf.materials.model'].search(
|
||||||
[('materials_no', '=', item['texture_type_code'])])
|
[('materials_no', '=', item['texture_type_code'])])
|
||||||
model_type = self.env['sf.model.type'].search([], limit=1)
|
model_type = self.env['sf.model.type'].search([], limit=1)
|
||||||
supplier = self.env['mrp.bom'].get_supplier(materials_type_id)
|
supplier = self.env['mrp.bom'].get_supplier(materials_type_id)
|
||||||
# 获取坯料冗余配置
|
|
||||||
if not item.get('embryo_redundancy_id'):
|
|
||||||
embryo_redundancy_id = model_type.embryo_tolerance_id
|
|
||||||
else:
|
|
||||||
embryo_redundancy_id = item.get('embryo_redundancy_id')
|
|
||||||
if not embryo_redundancy_id:
|
|
||||||
raise UserError('请先配置模型类型内的坯料冗余')
|
|
||||||
logging.info('no_bom_copy_product_supplier-vals:%s' % supplier)
|
logging.info('no_bom_copy_product_supplier-vals:%s' % supplier)
|
||||||
vals = {
|
vals = {
|
||||||
'name': '%s-%s-%s [%s %s-%s * %s * %s]' % ('R',
|
'name': '%s-%s-%s [%s %s-%s * %s * %s]' % ('R',
|
||||||
order_id.name, i, materials_id.name, materials_type_id.name,
|
order_id.name, i, materials_id.name, materials_type_id.name,
|
||||||
item['model_long'] + embryo_redundancy_id.long,
|
item['model_long'] + model_type.embryo_tolerance,
|
||||||
item['model_width'] + embryo_redundancy_id.width,
|
item['model_width'] + model_type.embryo_tolerance,
|
||||||
item['model_height'] + embryo_redundancy_id.height),
|
item['model_height'] + model_type.embryo_tolerance),
|
||||||
'length': item['model_long'] + embryo_redundancy_id.long,
|
'length': item['model_long'] + model_type.embryo_tolerance,
|
||||||
'width': item['model_width'] + embryo_redundancy_id.width,
|
'width': item['model_width'] + model_type.embryo_tolerance,
|
||||||
'height': item['model_height'] + embryo_redundancy_id.height,
|
'height': item['model_height'] + model_type.embryo_tolerance,
|
||||||
'volume': (item['model_long'] + embryo_redundancy_id.long) * (
|
'volume': (item['model_long'] + model_type.embryo_tolerance) * (
|
||||||
item['model_width'] + embryo_redundancy_id.width) * (
|
item['model_width'] + model_type.embryo_tolerance) * (
|
||||||
item['model_height'] + embryo_redundancy_id.height),
|
item['model_height'] + model_type.embryo_tolerance),
|
||||||
'embryo_model_type_id': model_type.id,
|
'embryo_model_type_id': model_type.id,
|
||||||
'list_price': item['price'],
|
'list_price': item['price'],
|
||||||
'materials_id': materials_id.id,
|
'materials_id': materials_id.id,
|
||||||
'materials_type_id': materials_type_id.id,
|
'materials_type_id': materials_type_id.id,
|
||||||
'single_manufacturing': product_id.single_manufacturing,
|
|
||||||
'is_bfm': True,
|
'is_bfm': True,
|
||||||
'active': True,
|
'active': True
|
||||||
}
|
}
|
||||||
# 外协和采购生成的坯料需要根据材料型号绑定供应商
|
# 外协和采购生成的坯料需要根据材料型号绑定供应商
|
||||||
if route_type == 'subcontract' or route_type == 'purchase':
|
if route_type == 'subcontract' or route_type == 'purchase':
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
# -*- 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
|
|
||||||
class PurchaseOrderLine(models.Model):
|
|
||||||
_inherit = 'purchase.order.line'
|
|
||||||
part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True)
|
|
||||||
related_product = fields.Many2one('product.product',compute='_compute_related_product', string='关联产品',help='经此产品工艺加工成的成品')
|
|
||||||
@api.depends('order_id.origin')
|
|
||||||
def _compute_related_product(self):
|
|
||||||
for record in self:
|
|
||||||
if record.product_id.detailed_type:
|
|
||||||
production_id = self.env['mrp.production'].search([('name', '=', record.order_id.origin)])
|
|
||||||
record.related_product = production_id.product_id if production_id else False
|
|
||||||
else:
|
|
||||||
record.related_product = False
|
|
||||||
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
from datetime import datetime
|
|
||||||
from odoo import models
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import base64
|
|
||||||
import hashlib
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class QuickEasyOrder(models.Model):
|
|
||||||
_inherit = 'quick.easy.order'
|
|
||||||
|
|
||||||
def distribute_to_factory(self, obj):
|
|
||||||
"""
|
|
||||||
多供货方式,重写派单到工厂
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
_logger.info('---------派单到工厂-------')
|
|
||||||
res = {'bfm_process_order_list': []}
|
|
||||||
for item in obj:
|
|
||||||
attachment = item.upload_model_file[0]
|
|
||||||
base64_data = base64.b64encode(attachment.datas)
|
|
||||||
base64_datas = base64_data.decode('utf-8')
|
|
||||||
barcode = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest()
|
|
||||||
# logging.info('model_file-size: %s' % len(item.model_file))
|
|
||||||
res['bfm_process_order_list'].append({
|
|
||||||
'model_long': item.model_length,
|
|
||||||
'model_width': item.model_width,
|
|
||||||
'model_height': item.model_height,
|
|
||||||
'model_volume': item.model_volume,
|
|
||||||
'model_machining_precision': item.machining_precision,
|
|
||||||
'model_name': attachment.name,
|
|
||||||
'model_data': base64_datas,
|
|
||||||
'model_file': base64.b64encode(item.model_file).decode('utf-8'),
|
|
||||||
'texture_code': item.material_id.materials_no,
|
|
||||||
'texture_type_code': item.material_model_id.materials_no,
|
|
||||||
# 'surface_process_code': self.env['jikimo.surface.process']._json_surface_process_code(item),
|
|
||||||
'process_parameters_code': self.env[
|
|
||||||
'sf.production.process.parameter']._json_production_process_item_code(
|
|
||||||
item),
|
|
||||||
'price': item.price,
|
|
||||||
'number': item.quantity,
|
|
||||||
'total_amount': item.price,
|
|
||||||
'remark': '',
|
|
||||||
'manual_quotation': True,
|
|
||||||
'barcode': barcode,
|
|
||||||
'part_number': item.part_drawing_number,
|
|
||||||
'machining_drawings_name': '',
|
|
||||||
'quality_standard_name': '',
|
|
||||||
'machining_drawings_mimetype': '',
|
|
||||||
'quality_standard_mimetype': '',
|
|
||||||
'machining_drawings': item.machining_drawings,
|
|
||||||
'quality_standard': '',
|
|
||||||
'part_name': '',
|
|
||||||
})
|
|
||||||
company_id = self.env.ref('base.main_company').sudo()
|
|
||||||
product_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_default').sudo().with_context(active_test=False).product_variant_id
|
|
||||||
# user_id = request.env.ref('base.user_admin').sudo()
|
|
||||||
order_id = self.env['sale.order'].sale_order_create(company_id, 'XXXXX', 'XXXXX', 'XXXXX',
|
|
||||||
str(datetime.now()), '现结', '支付宝', state='draft')
|
|
||||||
order_id.default_code = obj.name
|
|
||||||
i = 1
|
|
||||||
for item in res['bfm_process_order_list']:
|
|
||||||
product = self.env['product.template'].sudo().product_create(product_id, item, order_id,
|
|
||||||
obj.name, i)
|
|
||||||
order_id.with_user(self.env.ref("base.user_admin")).sale_order_create_line(product, item)
|
|
||||||
return order_id
|
|
||||||
except Exception as e:
|
|
||||||
return UserError('工厂创建销售订单和产品失败,请联系管理员')
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
import logging
|
|
||||||
import json
|
|
||||||
from odoo import models, fields, api
|
|
||||||
from odoo.exceptions import UserError
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class SaleOrder(models.Model):
|
|
||||||
_inherit = 'sale.order'
|
|
||||||
|
|
||||||
state = fields.Selection([
|
|
||||||
('draft', "报价"),
|
|
||||||
('sent', "报价已发送"),
|
|
||||||
('supply method', "供货方式待确认"),
|
|
||||||
('sale', "销售订单"),
|
|
||||||
('processing', "加工中"),
|
|
||||||
('physical_distribution', "物流中"),
|
|
||||||
('delivered', "已交付"),
|
|
||||||
('done', "已锁定"),
|
|
||||||
('cancel', "已取消"),
|
|
||||||
])
|
|
||||||
|
|
||||||
def confirm_to_supply_method(self):
|
|
||||||
self.state = 'supply method'
|
|
||||||
|
|
||||||
def action_confirm(self):
|
|
||||||
# 判断是否所有产品都选择了供货方式
|
|
||||||
filter_line = self.order_line.filtered(lambda line: not line.supply_method)
|
|
||||||
if filter_line:
|
|
||||||
raise UserError('当前订单内(%s)产品未选择路线,请选择后重试' % ','.join(filter_line.mapped('product_id.name')))
|
|
||||||
|
|
||||||
for line in self.order_line:
|
|
||||||
bom_type = ''
|
|
||||||
# 根据供货方式修改成品模板
|
|
||||||
if line.supply_method == 'automation':
|
|
||||||
bom_type = 'normal'
|
|
||||||
product_template_id = self.env.ref('sf_dlm.product_template_sf').sudo().product_tmpl_id
|
|
||||||
elif line.supply_method == 'outsourcing':
|
|
||||||
bom_type = 'subcontract'
|
|
||||||
product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_outsourcing').sudo()
|
|
||||||
elif line.supply_method == 'purchase':
|
|
||||||
product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_purchase').sudo()
|
|
||||||
elif line.supply_method == 'manual':
|
|
||||||
bom_type = 'normal'
|
|
||||||
product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_manual_processing').sudo()
|
|
||||||
|
|
||||||
# 复制成品模板上的属性
|
|
||||||
line.product_id.product_tmpl_id.copy_template(product_template_id)
|
|
||||||
# 将模板上的single_manufacturing属性复制到成品上
|
|
||||||
line.product_id.single_manufacturing = product_template_id.single_manufacturing
|
|
||||||
|
|
||||||
order_id = self
|
|
||||||
product = line.product_id
|
|
||||||
# 拼接方法需要的item结构
|
|
||||||
item = {
|
|
||||||
'texture_code': product.materials_id.materials_no,
|
|
||||||
'texture_type_code': product.materials_type_id.materials_no,
|
|
||||||
'model_long': product.length,
|
|
||||||
'model_width': product.width,
|
|
||||||
'model_height': product.height,
|
|
||||||
'price': product.list_price,
|
|
||||||
'embryo_redundancy_id': line.embryo_redundancy_id,
|
|
||||||
}
|
|
||||||
# 获取成品名结尾-n的n
|
|
||||||
product_seria = int(product.name.split('-')[-1])
|
|
||||||
# 成品供货方式为采购则不生成bom
|
|
||||||
if line.supply_method != 'purchase':
|
|
||||||
bom_data = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).get_bom(product)
|
|
||||||
_logger.info('bom_data:%s' % bom_data)
|
|
||||||
if bom_data:
|
|
||||||
bom = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).bom_create(product, 'normal', False)
|
|
||||||
bom.with_user(self.env.ref("base.user_admin")).bom_create_line_has(bom_data)
|
|
||||||
else:
|
|
||||||
# 当成品上带有客供料选项时,生成坯料时选择“客供料”路线
|
|
||||||
if line.embryo_redundancy_id:
|
|
||||||
# 将成品模板的内容复制到成品上
|
|
||||||
customer_provided_embryo = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_embryo_customer_provided').sudo()
|
|
||||||
# 创建坯料,客供料的批量不需要创建bom
|
|
||||||
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,
|
|
||||||
order_id, 'material_customer_provided', product_seria, product)
|
|
||||||
# 成品配置bom
|
|
||||||
product_bom_material_customer_provided = self.env['mrp.bom'].with_user(
|
|
||||||
self.env.ref("base.user_admin")).bom_create(
|
|
||||||
product, bom_type, 'product')
|
|
||||||
product_bom_material_customer_provided.with_user(self.env.ref("base.user_admin")).bom_create_line_has(
|
|
||||||
material_customer_provided_embryo)
|
|
||||||
elif line.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')
|
|
||||||
product_bom_self_machining.with_user(self.env.ref("base.user_admin")).bom_create_line_has(
|
|
||||||
self_machining_embryo)
|
|
||||||
elif line.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,
|
|
||||||
order_id,
|
|
||||||
'subcontract',
|
|
||||||
product_seria, product)
|
|
||||||
if outsource_embryo == -3:
|
|
||||||
raise UserError('该订单模型的材料型号暂未设置获取方式和供应商,请先配置再进行分配')
|
|
||||||
# 创建坯料的bom
|
|
||||||
outsource_bom = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).bom_create(
|
|
||||||
outsource_embryo,
|
|
||||||
'subcontract', True)
|
|
||||||
# 创建坯料的bom的组件
|
|
||||||
outsource_bom_line = outsource_bom.with_user(
|
|
||||||
self.env.ref("base.user_admin")).bom_create_line(outsource_embryo)
|
|
||||||
if not outsource_bom_line:
|
|
||||||
raise UserError('该订单模型的材料型号暂未有原材料,请先配置再进行分配')
|
|
||||||
# 产品配置bom
|
|
||||||
product_bom_outsource = self.env['mrp.bom'].with_user(
|
|
||||||
self.env.ref("base.user_admin")).bom_create(product, bom_type, 'product')
|
|
||||||
product_bom_outsource.with_user(self.env.ref("base.user_admin")).bom_create_line_has(
|
|
||||||
outsource_embryo)
|
|
||||||
elif line.product_id.materials_type_id.gain_way == '采购':
|
|
||||||
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 == -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')
|
|
||||||
product_bom_purchase.with_user(self.env.ref("base.user_admin")).bom_create_line_has(
|
|
||||||
purchase_embryo)
|
|
||||||
result = super(SaleOrder, self).action_confirm()
|
|
||||||
self.merge_picking()
|
|
||||||
return result
|
|
||||||
|
|
||||||
def merge_picking(self):
|
|
||||||
"""
|
|
||||||
合并多个stock.picking为一个新的stock.picking。
|
|
||||||
:param picking_ids: 需要合并的stock.picking记录ID列表
|
|
||||||
:return: 合并后的新的stock.picking对象
|
|
||||||
"""
|
|
||||||
picking_idss = self.env['stock.picking'].search([('retrospect_ref', 'ilike','%'+ self.name +'%')])
|
|
||||||
for pick in picking_idss:
|
|
||||||
print('qfwowio',pick)
|
|
||||||
picking_ids = self.env['stock.picking'].search([('retrospect_ref', '=', self.default_code)])
|
|
||||||
if not picking_ids:
|
|
||||||
return
|
|
||||||
# 获取需要合并的 stock.picking 记录
|
|
||||||
# 创建一个新的 stock.picking 作为合并结果
|
|
||||||
group = self.env['procurement.group'].create({
|
|
||||||
'name': self.name,
|
|
||||||
'partner_id': self.partner_id.id,
|
|
||||||
})
|
|
||||||
new_picking = self.env['stock.picking'].create({
|
|
||||||
'partner_id': picking_ids[0].partner_id.id,
|
|
||||||
'location_id': picking_ids[0].location_id.id,
|
|
||||||
'location_dest_id': picking_ids[0].location_dest_id.id,
|
|
||||||
'move_ids': False,
|
|
||||||
'sale_id': self.id,
|
|
||||||
'picking_type_id': picking_ids[0].picking_type_id.id,
|
|
||||||
'origin': '合并自: ' + ','.join([p.origin for p in picking_ids]),
|
|
||||||
'retrospect_ref':self.default_code,
|
|
||||||
'person_of_delivery':picking_ids[0].person_of_delivery,
|
|
||||||
'telephone_of_delivery': picking_ids[0].telephone_of_delivery,
|
|
||||||
'address_of_delivery': picking_ids[0].address_of_delivery,
|
|
||||||
'group_id':picking_ids[0].group_id.id
|
|
||||||
})
|
|
||||||
# 合并所有 move_lines
|
|
||||||
for picking in picking_ids:
|
|
||||||
for move in picking.move_ids:
|
|
||||||
# 复制 move_lines 到新的 picking
|
|
||||||
new_move_vals = move.copy_data()[0]
|
|
||||||
new_move_vals['picking_id']=new_picking.id
|
|
||||||
self.env['stock.move'].create(new_move_vals)
|
|
||||||
for pick in picking_idss:
|
|
||||||
print('qfwowio',pick)
|
|
||||||
# 处理合并后的配送单状态
|
|
||||||
new_picking.action_confirm() # 确认新的配送单
|
|
||||||
for pick in picking_idss:
|
|
||||||
print('qfwowio',pick)
|
|
||||||
new_picking.action_assign() # 分配新的配送单
|
|
||||||
|
|
||||||
# 删除原有的配送单
|
|
||||||
picking_ids.write({'state': 'cancel'}) # 将原配送单状态更改为取消
|
|
||||||
|
|
||||||
return new_picking
|
|
||||||
class SaleOrderLine(models.Model):
|
|
||||||
_inherit = 'sale.order.line'
|
|
||||||
part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True)
|
|
||||||
# 供货方式
|
|
||||||
supply_method = fields.Selection([
|
|
||||||
('automation', "自动化产线加工"),
|
|
||||||
('manual', "人工线下加工"),
|
|
||||||
('purchase', "外购"),
|
|
||||||
('outsourcing', "委外加工"),
|
|
||||||
], string='供货方式')
|
|
||||||
|
|
||||||
def write(self, vals):
|
|
||||||
if 'supply_method' in vals:
|
|
||||||
for line in self:
|
|
||||||
if vals['supply_method'] == 'automation' and line.manual_quotation:
|
|
||||||
raise UserError('当前(%s)产品为人工编程产品,不能选择自动化产线加工' % ','.join(line.mapped('product_id.name')))
|
|
||||||
return super(SaleOrderLine, self).write(vals)
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
import logging
|
|
||||||
from odoo import fields, models, api
|
|
||||||
from odoo.exceptions import UserError
|
|
||||||
|
|
||||||
|
|
||||||
class SfProductionProcessParameter(models.Model):
|
|
||||||
_inherit = 'sf.production.process.parameter'
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
|
|
||||||
if self._context.get('route_id'):
|
|
||||||
parameter = []
|
|
||||||
routing = self.env['mrp.routing.workcenter'].search([('id', '=', self._context.get('route_id'))])
|
|
||||||
technology_design = self.env['sf.technology.design'].search(
|
|
||||||
[('production_id', '=', self._context.get('production_id')), ('routing_tag', '=', 'special'),
|
|
||||||
('route_id', '=', self._context.get('route_id'))])
|
|
||||||
for t in technology_design:
|
|
||||||
if t.process_parameters_id:
|
|
||||||
parameter.append(t.process_parameters_id.id)
|
|
||||||
domain = [('process_id', '=', routing.surface_technics_id.id), ('id', 'not in', parameter)]
|
|
||||||
return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
|
|
||||||
return super()._name_search(name, args, operator, limit, name_get_uid)
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from collections import Counter
|
|
||||||
|
|
||||||
from odoo import fields, models, api, _
|
|
||||||
from odoo.exceptions import ValidationError
|
|
||||||
|
|
||||||
|
|
||||||
class sf_technology_design(models.Model):
|
|
||||||
_name = 'sf.technology.design'
|
|
||||||
_description = "工艺设计"
|
|
||||||
group_uniq_id = fields.Integer('同一制造订单唯一id',default=0)
|
|
||||||
sequence = fields.Integer('序号')
|
|
||||||
route_id = fields.Many2one('mrp.routing.workcenter', '工序')
|
|
||||||
process_parameters_id = fields.Many2one('sf.production.process.parameter', string='表面工艺参数')
|
|
||||||
panel = fields.Char('加工面')
|
|
||||||
routing_tag = fields.Selection(related='route_id.routing_tag', string='标签', store=True)
|
|
||||||
time_cycle_manual = fields.Float(related='route_id.time_cycle_manual', string='预计时长')
|
|
||||||
production_id = fields.Many2one('mrp.production')
|
|
||||||
is_auto = fields.Boolean('是否自动生成', default=False)
|
|
||||||
active = fields.Boolean('有效', default=True)
|
|
||||||
|
|
||||||
# @api.depends('production_id')
|
|
||||||
# def _compute_group_uniq_id(self):
|
|
||||||
# for record in self:
|
|
||||||
|
|
||||||
|
|
||||||
def json_technology_design_str(self, k, route, i, process_parameter):
|
|
||||||
workorders_values_str = [0, '', {
|
|
||||||
'route_id': route.id if route.routing_type in ['表面工艺'] else route.route_workcenter_id.id,
|
|
||||||
'panel': k,
|
|
||||||
'process_parameters_id': False if route.routing_type != '表面工艺' else self.env[
|
|
||||||
'sf.production.process.parameter'].search(
|
|
||||||
[('id', '=', process_parameter.id)]).id,
|
|
||||||
'sequence': i,
|
|
||||||
'is_auto': True}]
|
|
||||||
return workorders_values_str
|
|
||||||
|
|
||||||
def write(self, vals):
|
|
||||||
print('qwfojkqwfkio')
|
|
||||||
return super(sf_technology_design, self).write(vals)
|
|
||||||
def unlink_technology_design(self):
|
|
||||||
self.active = False
|
|
||||||
|
|
||||||
|
|
||||||
@api.model_create_multi
|
|
||||||
def create(self, vals_list):
|
|
||||||
for vals in vals_list:
|
|
||||||
if not vals.get('route_id'):
|
|
||||||
raise ValidationError(_("工序不能为空"))
|
|
||||||
result = super(sf_technology_design, self).create(vals_list)
|
|
||||||
for res in result:
|
|
||||||
record = self.search([('production_id', '=', res.production_id.id), ('active', 'in', [True, False])], order='group_uniq_id desc', limit=1)
|
|
||||||
res.group_uniq_id=record.group_uniq_id + 1
|
|
||||||
return result
|
|
||||||
def get_duplicates_with_inactive(self,technology_designs):
|
|
||||||
# 统计每个 'sequence' 出现的次数
|
|
||||||
sequence_count = Counter(technology_design.sequence for technology_design in technology_designs)
|
|
||||||
|
|
||||||
# 筛选出 'sequence' 重复且 'active' 为 False 的元素
|
|
||||||
result = [
|
|
||||||
technology_design for technology_design in technology_designs
|
|
||||||
if sequence_count[technology_design.sequence] > 1 and technology_design.active is False
|
|
||||||
]
|
|
||||||
|
|
||||||
return result
|
|
||||||
# def rearrange_numbering(self,self_technology_designs):
|
|
||||||
# inactive_designs = self.get_duplicates_with_inactive(self_technology_designs)
|
|
||||||
# if inactive_designs:
|
|
||||||
# max_design = max(self_technology_designs, key=lambda x: x.sequence)
|
|
||||||
# max_sequence = max_design.sequence if max_design else 0
|
|
||||||
# for designs in inactive_designs:
|
|
||||||
# max_sequence += 1
|
|
||||||
# designs.sequence = max_sequence
|
|
||||||
# self_technology_designs.sorted(key=lambda techology_design:techology_design.sequence)
|
|
||||||
# return self_technology_designs
|
|
||||||
|
|
||||||
def get_technology_design(self):
|
|
||||||
return {
|
|
||||||
'sequence':self.sequence,
|
|
||||||
'route_id': self.route_id.id,
|
|
||||||
'process_parameters_id': self.process_parameters_id.id,
|
|
||||||
'panel': self.panel,
|
|
||||||
'routing_tag': self.routing_tag,
|
|
||||||
'time_cycle_manual': self.time_cycle_manual,
|
|
||||||
'is_auto': self.is_auto,
|
|
||||||
'active': self.active,
|
|
||||||
'group_uniq_id':self.group_uniq_id,
|
|
||||||
}
|
|
||||||
def sync_technology_designs(self,production_technology_designs, self_technology_designs):
|
|
||||||
production_id = production_technology_designs[0].production_id.id
|
|
||||||
self_technology_design_dict = {item.group_uniq_id:item for item in self_technology_designs}
|
|
||||||
production_technology_designs_dict = {item.group_uniq_id:item for item in production_technology_designs}
|
|
||||||
for technology_design in production_technology_designs:
|
|
||||||
if not self_technology_design_dict.get(technology_design.group_uniq_id):
|
|
||||||
technology_design.write({'production_id': False})
|
|
||||||
else:
|
|
||||||
technology_design.write(self_technology_design_dict.get(technology_design.group_uniq_id).get_technology_design())
|
|
||||||
for technology_design in self_technology_designs:
|
|
||||||
if not production_technology_designs_dict.get(technology_design.group_uniq_id):
|
|
||||||
technology_design = technology_design.get_technology_design()
|
|
||||||
technology_design.update({'production_id': production_id})
|
|
||||||
technology_design.pop('group_uniq_id')
|
|
||||||
self.env['sf.technology.design'].create(technology_design)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def unified_procedure_multiple_work_orders(self,self_technology_designs,production_item):
|
|
||||||
technology_designs = self.env['sf.technology.design'].sudo().search(
|
|
||||||
[('production_id', '=', production_item.id), ('active', 'in', [True, False])])
|
|
||||||
self.sync_technology_designs(self_technology_designs=self_technology_designs,production_technology_designs=technology_designs)
|
|
||||||
@@ -182,11 +182,6 @@ class StockRule(models.Model):
|
|||||||
moves._action_confirm()
|
moves._action_confirm()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def attachment_update(self, name, res_id, res_field):
|
|
||||||
attachment_info = self.env['ir.attachment'].sudo().search(
|
|
||||||
[('res_id', '=', res_id), ('res_field', '=', res_field)], limit=1)
|
|
||||||
attachment_info.write({'name': name})
|
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _run_manufacture(self, procurements):
|
def _run_manufacture(self, procurements):
|
||||||
productions_values_by_company = defaultdict(list)
|
productions_values_by_company = defaultdict(list)
|
||||||
@@ -208,15 +203,6 @@ class StockRule(models.Model):
|
|||||||
'''创建制造订单'''
|
'''创建制造订单'''
|
||||||
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
|
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
|
||||||
productions_values)
|
productions_values)
|
||||||
# 将这一批制造订单的采购组根据成品设置为不同的采购组
|
|
||||||
product_group_id = {}
|
|
||||||
for index, production in enumerate(productions):
|
|
||||||
if production.product_id.id not in product_group_id.keys():
|
|
||||||
product_group_id[production.product_id.id] = production.procurement_group_id.id
|
|
||||||
else:
|
|
||||||
productions_values[index].update({'name': production.name})
|
|
||||||
procurement_group_vals = production._prepare_procurement_group_vals(productions_values[index])
|
|
||||||
production.procurement_group_id = self.env["procurement.group"].create(procurement_group_vals).id
|
|
||||||
|
|
||||||
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
|
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
|
||||||
# self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
# self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
||||||
@@ -281,26 +267,27 @@ class StockRule(models.Model):
|
|||||||
workorder_duration += workorder.duration_expected
|
workorder_duration += workorder.duration_expected
|
||||||
|
|
||||||
sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)])
|
sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)])
|
||||||
# 如果订单为空,则获取来源制造订单的销售单
|
# 根据销售订单号查询快速订单
|
||||||
if not sale_order:
|
quick_easy_order = self.env['quick.easy.order'].sudo().search([('sale_order_id', '=', sale_order.id)])
|
||||||
mrp_production = self.env['mrp.production'].sudo().search([('name', '=', production.origin)],
|
if quick_easy_order:
|
||||||
limit=1)
|
production.write({'part_number': quick_easy_order.part_drawing_number,
|
||||||
if mrp_production:
|
'part_drawing': quick_easy_order.machining_drawings})
|
||||||
sale_order = self.env['sale.order'].sudo().search([('name', '=', mrp_production.origin)])
|
|
||||||
else:
|
else:
|
||||||
mrp_production = production
|
production.write({'part_number': production.product_id.part_number,
|
||||||
# if sale_order:
|
'part_drawing': production.product_id.machining_drawings,
|
||||||
# sale_order.write({'schedule_status': 'to schedule'})
|
'quality_standard': production.product_id.quality_standard})
|
||||||
self.env['sf.production.plan'].sudo().with_company(company_id).create({
|
if sale_order:
|
||||||
'name': production.name,
|
# sale_order.write({'schedule_status': 'to schedule'})
|
||||||
'order_deadline': sale_order.deadline_of_delivery,
|
self.env['sf.production.plan'].sudo().with_company(company_id).create({
|
||||||
'production_id': production.id,
|
'name': production.name,
|
||||||
'date_planned_start': production.date_planned_start,
|
'order_deadline': sale_order.deadline_of_delivery,
|
||||||
'origin': mrp_production.origin,
|
'production_id': production.id,
|
||||||
'product_qty': production.product_qty,
|
'date_planned_start': production.date_planned_start,
|
||||||
'product_id': production.product_id.id,
|
'origin': production.origin,
|
||||||
'state': 'draft',
|
'product_qty': production.product_qty,
|
||||||
})
|
'product_id': production.product_id.id,
|
||||||
|
'state': 'draft',
|
||||||
|
})
|
||||||
all_production = productions
|
all_production = productions
|
||||||
grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)}
|
grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)}
|
||||||
# 初始化一个字典来存储每个product_id对应的生产订单名称列表
|
# 初始化一个字典来存储每个product_id对应的生产订单名称列表
|
||||||
@@ -310,86 +297,78 @@ class StockRule(models.Model):
|
|||||||
# 为同一个product_id创建一个生产订单名称列表
|
# 为同一个product_id创建一个生产订单名称列表
|
||||||
product_id_to_production_names[product_id] = [production.name for production in all_production]
|
product_id_to_production_names[product_id] = [production.name for production in all_production]
|
||||||
for production_item in productions:
|
for production_item in productions:
|
||||||
technology_design_values = []
|
|
||||||
production_programming = self.env['mrp.production'].search(
|
production_programming = self.env['mrp.production'].search(
|
||||||
[('product_id.id', '=', production_item.product_id.id),
|
[('product_id.id', '=', production_item.product_id.id),
|
||||||
('origin', '=', production_item.origin)],
|
('origin', '=', production_item.origin)],
|
||||||
limit=1, order='id asc')
|
limit=1, order='id asc')
|
||||||
if production_item.product_id.id in product_id_to_production_names:
|
if production_item.product_id.id in product_id_to_production_names:
|
||||||
# 同一个产品多个制造订单对应一个编程单和模型库
|
if not production_programming.programming_no:
|
||||||
# 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
|
if production_item.product_id.model_process_parameters_ids:
|
||||||
if not production_item.programming_no and production_item.production_type == '自动化产线加工':
|
is_purchase = False
|
||||||
|
sorted_process_parameters = sorted(production_item.product_id.model_process_parameters_ids,
|
||||||
|
key=lambda w: w.id)
|
||||||
|
|
||||||
|
consecutive_process_parameters = []
|
||||||
|
m = 0
|
||||||
|
for i in range(len(sorted_process_parameters) - 1):
|
||||||
|
if m == 0:
|
||||||
|
is_purchase = False
|
||||||
|
if self.env['product.template']._get_process_parameters_product(
|
||||||
|
sorted_process_parameters[i]).partner_id == self.env[
|
||||||
|
'product.template']._get_process_parameters_product(sorted_process_parameters[
|
||||||
|
i + 1]).partner_id and \
|
||||||
|
sorted_process_parameters[i].gain_way == '外协':
|
||||||
|
if sorted_process_parameters[i] not in consecutive_process_parameters:
|
||||||
|
consecutive_process_parameters.append(sorted_process_parameters[i])
|
||||||
|
consecutive_process_parameters.append(sorted_process_parameters[i + 1])
|
||||||
|
m += 1
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if m == len(consecutive_process_parameters) - 1 and m != 0:
|
||||||
|
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||||
|
production_item,
|
||||||
|
product_id_to_production_names)
|
||||||
|
if sorted_process_parameters[i] in consecutive_process_parameters:
|
||||||
|
is_purchase = True
|
||||||
|
consecutive_process_parameters = []
|
||||||
|
m = 0
|
||||||
|
# 当前面的连续外协采购单生成再生成当前外协采购单
|
||||||
|
if is_purchase is False:
|
||||||
|
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||||
|
production_item,
|
||||||
|
product_id_to_production_names)
|
||||||
|
if m == len(consecutive_process_parameters) - 1 and m != 0:
|
||||||
|
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||||
|
production_item,
|
||||||
|
product_id_to_production_names)
|
||||||
|
if sorted_process_parameters[i] in consecutive_process_parameters:
|
||||||
|
is_purchase = True
|
||||||
|
consecutive_process_parameters = []
|
||||||
|
m = 0
|
||||||
|
if m == len(consecutive_process_parameters) - 1 and m != 0:
|
||||||
|
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||||
|
production_item,
|
||||||
|
product_id_to_production_names)
|
||||||
|
if is_purchase is False and m == 0:
|
||||||
|
if len(sorted_process_parameters) == 1:
|
||||||
|
self.env['purchase.order'].get_purchase_order(sorted_process_parameters,
|
||||||
|
production_item,
|
||||||
|
product_id_to_production_names)
|
||||||
|
else:
|
||||||
|
self.env['purchase.order'].get_purchase_order(sorted_process_parameters[i],
|
||||||
|
production_item,
|
||||||
|
product_id_to_production_names)
|
||||||
|
# # 同一个产品多个制造订单对应一个编程单和模型库
|
||||||
|
# # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
|
||||||
|
if not production_item.programming_no:
|
||||||
if not production_programming.programming_no:
|
if not production_programming.programming_no:
|
||||||
production_item.fetchCNC(
|
production_item.fetchCNC(
|
||||||
', '.join(product_id_to_production_names[production_item.product_id.id]))
|
', '.join(product_id_to_production_names[production_item.product_id.id]))
|
||||||
else:
|
else:
|
||||||
production_item.write({'programming_no': production_programming.programming_no,
|
production_item.write({'programming_no': production_programming.programming_no,
|
||||||
'programming_state': '编程中'})
|
'programming_state': '编程中'})
|
||||||
i = 0
|
return True
|
||||||
if production_item.product_id.categ_id.type == '成品':
|
|
||||||
# 根据加工面板的面数及成品工序模板生成工序设计
|
|
||||||
if production_item.production_type == '自动化产线加工':
|
|
||||||
model = 'sf.product.model.type.routing.sort'
|
|
||||||
domain = [
|
|
||||||
('product_model_type_id', '=', production_item.product_id.product_model_type_id.id)]
|
|
||||||
else:
|
|
||||||
model = 'sf.manual.product.model.type.routing.sort'
|
|
||||||
domain = [('manual_product_model_type_id', '=',
|
|
||||||
production_item.product_id.product_model_type_id.id)]
|
|
||||||
product_routing_workcenter = self.env[model].search(domain, order='sequence asc')
|
|
||||||
if production_item.production_type == '自动化产线加工':
|
|
||||||
for k in (production_item.product_id.model_processing_panel.split(',')):
|
|
||||||
for route in product_routing_workcenter:
|
|
||||||
i += 1
|
|
||||||
technology_design_values.append(
|
|
||||||
self.env['sf.technology.design'].json_technology_design_str(k, route, i, False))
|
|
||||||
else:
|
|
||||||
for route in product_routing_workcenter:
|
|
||||||
i += 1
|
|
||||||
technology_design_values.append(
|
|
||||||
self.env['sf.technology.design'].json_technology_design_str(False, route, i, False))
|
|
||||||
elif production_item.product_id.categ_id.type == '坯料':
|
|
||||||
embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search(
|
|
||||||
[('embryo_model_type_id', '=', production_item.product_id.embryo_model_type_id.id)],
|
|
||||||
order='sequence asc'
|
|
||||||
)
|
|
||||||
for route_embryo in embryo_routing_workcenter:
|
|
||||||
i += 1
|
|
||||||
technology_design_values.append(
|
|
||||||
self.env['sf.technology.design'].json_technology_design_str(False, route_embryo, i,
|
|
||||||
False))
|
|
||||||
surface_technics_arr = []
|
|
||||||
route_workcenter_arr = []
|
|
||||||
for item in production_item.product_id.product_model_type_id.surface_technics_routing_tmpl_ids:
|
|
||||||
if item.route_workcenter_id.surface_technics_id.id:
|
|
||||||
for process_param in production_item.product_id.model_process_parameters_ids:
|
|
||||||
if item.route_workcenter_id.surface_technics_id == process_param.process_id:
|
|
||||||
surface_technics_arr.append(
|
|
||||||
item.route_workcenter_id.surface_technics_id.id)
|
|
||||||
route_workcenter_arr.append(item.route_workcenter_id.id)
|
|
||||||
if surface_technics_arr:
|
|
||||||
production_process = self.env['sf.production.process'].search(
|
|
||||||
[('id', 'in', surface_technics_arr)],
|
|
||||||
order='sequence asc'
|
|
||||||
)
|
|
||||||
for p in production_process:
|
|
||||||
logging.info('production_process:%s' % p.name)
|
|
||||||
process_parameter = production_item.product_id.model_process_parameters_ids.filtered(
|
|
||||||
lambda pm: pm.process_id.id == p.id)
|
|
||||||
if process_parameter:
|
|
||||||
i += 1
|
|
||||||
route_production_process = self.env[
|
|
||||||
'mrp.routing.workcenter'].search(
|
|
||||||
[('surface_technics_id', '=', p.id),
|
|
||||||
('id', 'in', route_workcenter_arr)])
|
|
||||||
technology_design_values.append(
|
|
||||||
self.env['sf.technology.design'].json_technology_design_str(False,
|
|
||||||
route_production_process,
|
|
||||||
i,
|
|
||||||
process_parameter))
|
|
||||||
production_item.technology_design_ids = technology_design_values
|
|
||||||
productions.write({'state': 'technology_to_confirmed'})
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class ProductionLot(models.Model):
|
class ProductionLot(models.Model):
|
||||||
@@ -423,8 +402,6 @@ class ProductionLot(models.Model):
|
|||||||
"""Generate `lot_names` from a string."""
|
"""Generate `lot_names` from a string."""
|
||||||
if first_lot.__contains__(display_name):
|
if first_lot.__contains__(display_name):
|
||||||
first_lot = first_lot[(len(display_name) + 1):]
|
first_lot = first_lot[(len(display_name) + 1):]
|
||||||
else:
|
|
||||||
first_lot = first_lot[-3:]
|
|
||||||
|
|
||||||
# We look if the first lot contains at least one digit.
|
# We look if the first lot contains at least one digit.
|
||||||
caught_initial_number = regex_findall(r"\d+", first_lot)
|
caught_initial_number = regex_findall(r"\d+", first_lot)
|
||||||
@@ -479,14 +456,6 @@ class ProductionLot(models.Model):
|
|||||||
if product.categ_id.name == '刀具':
|
if product.categ_id.name == '刀具':
|
||||||
return self.env['stock.lot'].get_tool_generate_lot_names1(company, product)
|
return self.env['stock.lot'].get_tool_generate_lot_names1(company, product)
|
||||||
else:
|
else:
|
||||||
# 对last_serial的name进行检测,如果不是以产品名称+数字的形式的就重新搜索
|
|
||||||
if product.name.split('[')[0] not in last_serial.name:
|
|
||||||
last_serial = self.env['stock.lot'].search(
|
|
||||||
[('company_id', '=', company.id), ('product_id', '=', product.id),
|
|
||||||
('name', 'ilike', product.name.split('[')[0])],
|
|
||||||
limit=1, order='name desc')
|
|
||||||
if not last_serial:
|
|
||||||
return "%s-%03d" % (product.name, 1)
|
|
||||||
return self.env['stock.lot'].generate_lot_names1(product.name, last_serial.name, 2)[1]
|
return self.env['stock.lot'].generate_lot_names1(product.name, last_serial.name, 2)[1]
|
||||||
now = datetime.now().strftime("%Y%m%d")
|
now = datetime.now().strftime("%Y%m%d")
|
||||||
if product.cutting_tool_model_id:
|
if product.cutting_tool_model_id:
|
||||||
@@ -583,57 +552,6 @@ class StockPicking(models.Model):
|
|||||||
_inherit = 'stock.picking'
|
_inherit = 'stock.picking'
|
||||||
|
|
||||||
surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数")
|
surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数")
|
||||||
person_of_delivery = fields.Char('收货人', compute='_compute_move_ids', store=True)
|
|
||||||
telephone_of_delivery = fields.Char('电话号码', compute='_compute_move_ids', store=True)
|
|
||||||
address_of_delivery = fields.Char('联系地址', compute='_compute_move_ids', store=True)
|
|
||||||
|
|
||||||
retrospect_ref = fields.Char('平台订单号', compute='_compute_move_ids', store=True)
|
|
||||||
sale_name = fields.Char('销售订单', compute='_compute_move_ids', store=True)
|
|
||||||
picking_type_sequence_code = fields.Char(related='picking_type_id.sequence_code')
|
|
||||||
related_group_ids = fields.Many2many(
|
|
||||||
'procurement.group', string='关联捕获组',
|
|
||||||
readonly=True, compute='_compute_related_group_ids', store=True)
|
|
||||||
@api.depends('origin')
|
|
||||||
def _compute_related_group_ids(self):
|
|
||||||
for record in self:
|
|
||||||
if not record.origin:
|
|
||||||
continue
|
|
||||||
names = record.origin.split(',')
|
|
||||||
related_group_ids = self.env['procurement.group'].search([('name', 'in', names)])
|
|
||||||
record.related_group_ids = [(6, 0, related_group_ids.ids)]
|
|
||||||
|
|
||||||
@api.depends('move_ids', 'move_ids.product_id')
|
|
||||||
def _compute_move_ids(self):
|
|
||||||
for item in self:
|
|
||||||
if item.move_ids:
|
|
||||||
if item.picking_type_id.sequence_code == 'DL':
|
|
||||||
sale_name = item.move_ids[0].product_id.with_context(lang='zh_CN').name.split('-')[1]
|
|
||||||
item.sale_name=sale_name
|
|
||||||
if 'S' in sale_name:
|
|
||||||
sale_id = self.env['sale.order'].sudo().search([('name', '=', sale_name)])
|
|
||||||
item.person_of_delivery = sale_id.person_of_delivery
|
|
||||||
item.telephone_of_delivery = sale_id.telephone_of_delivery
|
|
||||||
item.address_of_delivery = sale_id.address_of_delivery
|
|
||||||
else:
|
|
||||||
raise ValidationError('坯料名称格式错误,正确格式为[R-S???-?]!!!')
|
|
||||||
move_ids = []
|
|
||||||
for move_id in item.move_ids:
|
|
||||||
move_ids.append(move_id.product_id.id)
|
|
||||||
boms = self.env['mrp.bom'].sudo().search([('bom_line_ids.product_id', 'in', move_ids)])
|
|
||||||
if boms:
|
|
||||||
codes_list = []
|
|
||||||
for bom in boms:
|
|
||||||
if bom.product_tmpl_id.default_code:
|
|
||||||
code_list = bom.product_tmpl_id.default_code.split('-')
|
|
||||||
if len(code_list) >= 4:
|
|
||||||
code = '-'.join(code_list[:4])
|
|
||||||
if code not in codes_list:
|
|
||||||
codes_list.append(code)
|
|
||||||
else:
|
|
||||||
raise ValidationError('坯料成品的内部参考值格式错误')
|
|
||||||
item.retrospect_ref = ','.join(codes_list)
|
|
||||||
elif item.picking_type_id.sequence_code in ['INT', 'PC']:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# 设置外协出入单的名称
|
# 设置外协出入单的名称
|
||||||
def _get_name_Res(self, rescode):
|
def _get_name_Res(self, rescode):
|
||||||
@@ -647,89 +565,84 @@ class StockPicking(models.Model):
|
|||||||
return '%s%s' % (rescode, num)
|
return '%s%s' % (rescode, num)
|
||||||
|
|
||||||
def button_validate(self):
|
def button_validate(self):
|
||||||
|
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.origin)])
|
||||||
|
# if self.id == move_out.picking_id.id:
|
||||||
|
# if move_out.move_line_ids.workorder_id.state not in ['progress']:
|
||||||
|
# raise UserError(
|
||||||
|
# _('该出库单里源单据内的单号为%s的工单还未开始,不能进行验证操作!' % move_out.move_line_ids.workorder_id.name))
|
||||||
|
# 入库单验证
|
||||||
|
move_in = self.env['stock.move'].search(
|
||||||
|
[('location_dest_id', '=', self.env['stock.location'].search(
|
||||||
|
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
|
||||||
|
('location_id', '=', self.env['stock.location'].search(
|
||||||
|
[('barcode', 'ilike', 'VL-SPOC')]).id),
|
||||||
|
('origin', '=', self.origin), ('picking_id', '=', self.id)])
|
||||||
|
if self.location_id == move_in.location_id and self.location_dest_id == move_in.location_dest_id:
|
||||||
|
if move_out.origin == move_in.origin:
|
||||||
|
move_in.write({'production_id': False})
|
||||||
|
if move_out.picking_id.state != 'done':
|
||||||
|
raise UserError(
|
||||||
|
_('该入库单对应的单号为%s的出库单还未完成,不能进行验证操作!' % move_out.picking_id.name))
|
||||||
res = super().button_validate()
|
res = super().button_validate()
|
||||||
picking_type_in = self.env.ref('sf_manufacturing.outcontract_picking_in').id
|
if res is True:
|
||||||
if res is True and self.picking_type_id.id == picking_type_in:
|
if self.id == move_out.picking_id.id:
|
||||||
# 如果是最后一张外协入库单,则设置库存位置的预留数量
|
# if move_out.move_line_ids.workorder_id.state == 'progress':
|
||||||
move_in = self.move_ids
|
move_in = self.env['stock.move'].search(
|
||||||
if move_in:
|
[('location_dest_id', '=', self.env['stock.location'].search(
|
||||||
workorder = move_in.subcontract_workorder_id
|
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
|
||||||
workorders = workorder.production_id.workorder_ids
|
('location_id', '=', self.env['stock.location'].search(
|
||||||
subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True).sorted('sequence')
|
[('barcode', 'ilike', 'VL-SPOC')]).id),
|
||||||
if workorder == subcontract_workorders[-1]:
|
('origin', '=', self.origin)])
|
||||||
self.env['stock.quant']._update_reserved_quantity(
|
production = self.env['mrp.production'].search([('name', '=', self.origin)])
|
||||||
move_in.product_id, move_in.location_dest_id, move_in.product_uom_qty,
|
if move_in.state != 'done':
|
||||||
lot_id=move_in.move_line_ids.lot_id,
|
move_in.write({'state': 'assigned'})
|
||||||
package_id=False, owner_id=False, strict=False
|
self.env['stock.move.line'].create(move_in.get_move_line(production, None))
|
||||||
)
|
|
||||||
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
|
return res
|
||||||
|
|
||||||
# 创建 外协出库入单
|
# 创建 外协出库入单
|
||||||
def create_outcontract_picking(self, workorders, item, sorted_workorders):
|
def create_outcontract_picking(self, sorted_workorders_arr, item):
|
||||||
for workorder in workorders:
|
m = 0
|
||||||
if workorder.move_subcontract_workorder_ids:
|
for sorted_workorders in sorted_workorders_arr:
|
||||||
workorder.move_subcontract_workorder_ids.write({'state': 'waiting'})
|
# pick_ids = []
|
||||||
workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'waiting'})
|
if m == 0:
|
||||||
else:
|
outcontract_stock_move = self.env['stock.move'].search(
|
||||||
# 创建一个新的补货组
|
[('workorder_id', '=', sorted_workorders.id), ('production_id', '=', item.id)])
|
||||||
procurement_group_id = self.env['procurement.group'].create({
|
if not outcontract_stock_move:
|
||||||
'name': workorder.name,
|
new_picking = True
|
||||||
'partner_id': self.partner_id.id,
|
location_id = self.env['stock.location'].search(
|
||||||
})
|
[('barcode', 'ilike', 'VL-SPOC')]).id,
|
||||||
move_dest_id = False
|
location_dest_id = self.env['stock.location'].search(
|
||||||
# 如果当前工单是是制造订单的最后一个工艺外协工单
|
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id,
|
||||||
if workorder == next((workorder for workorder in reversed(item.workorder_ids) if workorder.is_subcontract), None):
|
outcontract_picking_type_in = self.env.ref(
|
||||||
move_dest_id = item.move_raw_ids[0].id
|
'sf_manufacturing.outcontract_picking_in').id,
|
||||||
else:
|
outcontract_picking_type_out = self.env.ref(
|
||||||
# 从sorted_workorders中找到上一工单的move
|
'sf_manufacturing.outcontract_picking_out').id,
|
||||||
if len(sorted_workorders) > 1:
|
moves_out = self.env['stock.move'].sudo().create(
|
||||||
move_dest_id = sorted_workorders[sorted_workorders.index(workorder)+1].move_subcontract_workorder_ids[1].id
|
self.env['stock.move']._get_stock_move_values_Res(item, location_dest_id, location_id,
|
||||||
new_picking = True
|
outcontract_picking_type_out))
|
||||||
outcontract_picking_type_in = self.env.ref(
|
picking_out = self.create(
|
||||||
'sf_manufacturing.outcontract_picking_in').id,
|
moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/'))
|
||||||
outcontract_picking_type_out = self.env.ref(
|
# pick_ids.append(picking_out.id)
|
||||||
'sf_manufacturing.outcontract_picking_out').id,
|
moves_out.write(
|
||||||
moves_in = self.env['stock.move'].sudo().create(
|
{'picking_id': picking_out.id, 'state': 'waiting', 'workorder_id': sorted_workorders.id})
|
||||||
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_in,
|
moves_out._assign_picking_post_process(new=new_picking)
|
||||||
procurement_group_id.id, move_dest_id))
|
moves_in = self.env['stock.move'].sudo().create(
|
||||||
picking_in = self.create(
|
self.env['stock.move']._get_stock_move_values_Res(item, location_id, location_dest_id,
|
||||||
moves_in._get_new_picking_values_Res(item, workorder, 'WH/OCIN/'))
|
outcontract_picking_type_in))
|
||||||
# pick_ids.append(picking_in.id)
|
picking_in = self.create(
|
||||||
moves_in.write(
|
moves_in._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCIN/'))
|
||||||
{'picking_id': picking_in.id, 'state': 'waiting'})
|
# pick_ids.append(picking_in.id)
|
||||||
moves_in._assign_picking_post_process(new=new_picking)
|
moves_in.write(
|
||||||
moves_out = self.env['stock.move'].sudo().create(
|
{'picking_id': picking_in.id, 'state': 'waiting', 'workorder_id': sorted_workorders.id})
|
||||||
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_out,
|
moves_in._assign_picking_post_process(new=new_picking)
|
||||||
procurement_group_id.id, moves_in.id))
|
m += 1
|
||||||
workorder.write({'move_subcontract_workorder_ids': [(6, 0, [moves_in.id, moves_out.id])]})
|
# sorted_workorders.write({'picking_ids': [(6, 0, pick_ids)]})
|
||||||
picking_out = self.create(
|
|
||||||
moves_out._get_new_picking_values_Res(item, workorder, 'WH/OCOUT/'))
|
|
||||||
# pick_ids.append(picking_out.id)
|
|
||||||
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()
|
|
||||||
for picking in self:
|
|
||||||
# 外协出库单根据工单状态,采购单状态来确定
|
|
||||||
picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_out').id
|
|
||||||
if picking.picking_type_id.id == picking_type_id:
|
|
||||||
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']:
|
|
||||||
picking.state = 'waiting'
|
|
||||||
|
|
||||||
|
|
||||||
class ReStockMove(models.Model):
|
class ReStockMove(models.Model):
|
||||||
@@ -739,21 +652,17 @@ class ReStockMove(models.Model):
|
|||||||
materiel_width = fields.Float(string='物料宽度', digits=(16, 4))
|
materiel_width = fields.Float(string='物料宽度', digits=(16, 4))
|
||||||
materiel_height = fields.Float(string='物料高度', digits=(16, 4))
|
materiel_height = fields.Float(string='物料高度', digits=(16, 4))
|
||||||
|
|
||||||
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, location_src_id, location_dest_id, picking_type_id):
|
||||||
route_id = self.env.ref('sf_manufacturing.route_surface_technology_outsourcing').id
|
route = self.env['stock.route'].sudo().search([('name', '=', '表面工艺外协')])
|
||||||
stock_rule = self.env['stock.rule'].sudo().search(
|
|
||||||
[('route_id', '=', route_id), ('picking_type_id', '=', picking_type_id)])
|
|
||||||
move_values = {
|
move_values = {
|
||||||
'name': '推',
|
'name': '推',
|
||||||
'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': 1.0,
|
||||||
'location_id': stock_rule.location_src_id.id,
|
'location_id': location_src_id,
|
||||||
'location_dest_id': stock_rule.location_dest_id.id,
|
'location_dest_id': location_dest_id,
|
||||||
'origin': item.name,
|
'origin': item.name,
|
||||||
'group_id': group_id,
|
|
||||||
'move_dest_ids': [(6, 0, [move_dest_ids])] if move_dest_ids else False,
|
|
||||||
# 'route_ids': False if not route else [(4, route.id)],
|
# 'route_ids': False if not route else [(4, route.id)],
|
||||||
'date_deadline': datetime.now(),
|
'date_deadline': datetime.now(),
|
||||||
'picking_type_id': picking_type_id,
|
'picking_type_id': picking_type_id,
|
||||||
@@ -777,7 +686,7 @@ class ReStockMove(models.Model):
|
|||||||
'picking_type_id': picking_type_id,
|
'picking_type_id': picking_type_id,
|
||||||
'location_id': self.mapped('location_id').id,
|
'location_id': self.mapped('location_id').id,
|
||||||
'location_dest_id': self.mapped('location_dest_id').id,
|
'location_dest_id': self.mapped('location_dest_id').id,
|
||||||
'state': 'waiting',
|
'state': 'confirmed',
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_move_line(self, production_id, sorted_workorders):
|
def get_move_line(self, production_id, sorted_workorders):
|
||||||
@@ -790,7 +699,7 @@ class ReStockMove(models.Model):
|
|||||||
'picking_id': self.picking_id.id,
|
'picking_id': self.picking_id.id,
|
||||||
'reserved_uom_qty': 1.0,
|
'reserved_uom_qty': 1.0,
|
||||||
'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.company_id.id,
|
||||||
# 'workorder_id': '' if not sorted_workorders else sorted_workorders.id,
|
# 'workorder_id': '' if not sorted_workorders else sorted_workorders.id,
|
||||||
# 'production_id': '' if not sorted_workorders else sorted_workorders.production_id.id,
|
# 'production_id': '' if not sorted_workorders else sorted_workorders.production_id.id,
|
||||||
'state': 'assigned',
|
'state': 'assigned',
|
||||||
@@ -834,8 +743,6 @@ class ReStockMove(models.Model):
|
|||||||
self.next_serial = self._get_tool_next_serial(self.company_id, self.product_id, self.origin)
|
self.next_serial = self._get_tool_next_serial(self.company_id, self.product_id, self.origin)
|
||||||
else:
|
else:
|
||||||
self.next_serial = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id)
|
self.next_serial = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id)
|
||||||
if self.picking_type_id.sequence_code == 'DL' and not self.move_line_nosuggest_ids:
|
|
||||||
self.action_assign_serial_show_details()
|
|
||||||
elif self.product_id.tracking == "lot":
|
elif self.product_id.tracking == "lot":
|
||||||
self._put_tool_lot(self.company_id, self.product_id, self.origin)
|
self._put_tool_lot(self.company_id, self.product_id, self.origin)
|
||||||
|
|
||||||
@@ -988,42 +895,6 @@ class ReStockMove(models.Model):
|
|||||||
qty_by_location[loc.id] += 1
|
qty_by_location[loc.id] += 1
|
||||||
return move_lines_commands
|
return move_lines_commands
|
||||||
|
|
||||||
def _merge_moves_fields(self):
|
|
||||||
"""
|
|
||||||
合并制造订单的完成move单据
|
|
||||||
"""
|
|
||||||
res = super(ReStockMove, self)._merge_moves_fields()
|
|
||||||
if self[0].origin and self.picking_type_id.name in ['生产发料', '内部调拨', '生产入库', '客供料入库']:
|
|
||||||
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'))
|
|
||||||
return res
|
|
||||||
|
|
||||||
def _get_new_picking_values(self):
|
|
||||||
"""
|
|
||||||
创建调拨单时,在此新增或修改调拨单的数据
|
|
||||||
"""
|
|
||||||
res = super(ReStockMove, self)._get_new_picking_values()
|
|
||||||
## 制造订单报废生成的新制造订单不走合并
|
|
||||||
production_remanufacture = None
|
|
||||||
if 'origin' in res:
|
|
||||||
if self.picking_type_id.name in ['生产发料', '内部调拨']:
|
|
||||||
production_remanufacture = self.env['mrp.production'].search(
|
|
||||||
[('name', '=', res['origin']), ('is_remanufacture', '=', True)])
|
|
||||||
if not production_remanufacture:
|
|
||||||
if self[0].origin and self.picking_type_id.name in ['生产发料', '内部调拨']:
|
|
||||||
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)])
|
|
||||||
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')
|
|
||||||
|
|
||||||
|
|
||||||
class ReStockQuant(models.Model):
|
class ReStockQuant(models.Model):
|
||||||
_inherit = 'stock.quant'
|
_inherit = 'stock.quant'
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
<data noupdate="1">
|
<data>
|
||||||
<record id="group_show_button" model="res.groups">
|
|
||||||
<field name="name">演示模式</field>
|
|
||||||
<field name="category_id" ref="base.module_category_hidden"/>
|
|
||||||
</record>
|
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ access_sf_model_type_group_sale_director,sf_model_type_group_sale_director,model
|
|||||||
access_sf_model_type_group_purchase_director,sf_model_type_group_purchase_director,model_sf_model_type,sf_base.group_purchase_director,1,0,0,0
|
access_sf_model_type_group_purchase_director,sf_model_type_group_purchase_director,model_sf_model_type,sf_base.group_purchase_director,1,0,0,0
|
||||||
access_sf_model_type_group_plan_director,sf_model_type_group_plan_director,model_sf_model_type,sf_base.group_plan_director,1,0,0,0
|
access_sf_model_type_group_plan_director,sf_model_type_group_plan_director,model_sf_model_type,sf_base.group_plan_director,1,0,0,0
|
||||||
access_sf_product_model_type_routing_sort_group_sf_mrp_user,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
|
access_sf_product_model_type_routing_sort_group_sf_mrp_user,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
|
||||||
access_sf_product_model_type_routing_sort_manager,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
|
access_sf_product_model_type_routing_sort_manager,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,0
|
||||||
access_sf_embryo_model_type_routing_sort_group_sf_mrp_user,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
|
access_sf_embryo_model_type_routing_sort_group_sf_mrp_user,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
|
||||||
access_sf_embryo_model_type_routing_sort_manager,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
|
access_sf_embryo_model_type_routing_sort_manager,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,0
|
||||||
access_sf_surface_technics_model_type_routing_sort,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
|
access_sf_surface_technics_model_type_routing_sort,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
|
||||||
access_sf_surface_technics_model_type_routing_sort_manager,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
|
access_sf_surface_technics_model_type_routing_sort_manager,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,0
|
||||||
access_sf_production_line_group_sf_mrp_user,sf.production.line,model_sf_production_line,sf_base.group_sf_mrp_user,1,1,1,0
|
access_sf_production_line_group_sf_mrp_user,sf.production.line,model_sf_production_line,sf_base.group_sf_mrp_user,1,1,1,0
|
||||||
access_sf_production_line_manager,sf.production.line,model_sf_production_line,sf_base.group_sf_mrp_manager,1,1,1,0
|
access_sf_production_line_manager,sf.production.line,model_sf_production_line,sf_base.group_sf_mrp_manager,1,1,1,0
|
||||||
access_maintenance_equipment_tool_group_sf_mrp_user,maintenance_equipment_tool,model_maintenance_equipment_tool,sf_base.group_sf_mrp_user,1,0,0,0
|
access_maintenance_equipment_tool_group_sf_mrp_user,maintenance_equipment_tool,model_maintenance_equipment_tool,sf_base.group_sf_mrp_user,1,0,0,0
|
||||||
@@ -52,7 +52,6 @@ access_mrp_routing_workcenter_manager_group_sf_mrp_user,mrp.routing.workcenter.m
|
|||||||
access_mrp_bom_manager_group_sf_mrp_user,mrp.bom.manager,mrp.model_mrp_bom,sf_base.group_sf_mrp_user,1,1,1,0
|
access_mrp_bom_manager_group_sf_mrp_user,mrp.bom.manager,mrp.model_mrp_bom,sf_base.group_sf_mrp_user,1,1,1,0
|
||||||
access_mrp_bom_line_manager_group_sf_mrp_user,mrp.bom.line.manager,mrp.model_mrp_bom_line,sf_base.group_sf_mrp_user,1,1,1,0
|
access_mrp_bom_line_manager_group_sf_mrp_user,mrp.bom.line.manager,mrp.model_mrp_bom_line,sf_base.group_sf_mrp_user,1,1,1,0
|
||||||
access_mrp_bom_line_group_plan_director,mrp_bom_line_group_plan_director,mrp.model_mrp_bom_line,sf_base.group_plan_director,1,1,1,0
|
access_mrp_bom_line_group_plan_director,mrp_bom_line_group_plan_director,mrp.model_mrp_bom_line,sf_base.group_plan_director,1,1,1,0
|
||||||
access_mrp_bom_line_group_sf_stock_user,mrp_bom_line_group_sf_stock_user,mrp.model_mrp_bom_line,sf_base.group_sf_stock_user,1,1,1,0
|
|
||||||
access_mrp_bom_line_group_sale_director,mrp_bom_line_group_sale_director,mrp.model_mrp_bom_line,sf_base.group_sale_director,1,1,1,0
|
access_mrp_bom_line_group_sale_director,mrp_bom_line_group_sale_director,mrp.model_mrp_bom_line,sf_base.group_sale_director,1,1,1,0
|
||||||
access_mrp_bom_line_group_sale_salemanager,mrp_bom_line_group_sale_salemanager,mrp.model_mrp_bom_line,sf_base.group_sale_salemanager,1,0,1,0
|
access_mrp_bom_line_group_sale_salemanager,mrp_bom_line_group_sale_salemanager,mrp.model_mrp_bom_line,sf_base.group_sale_salemanager,1,0,1,0
|
||||||
access_mrp_bom_line_group_purchase_director,mrp_bom_line_group_purchase_director,mrp.model_mrp_bom_line,sf_base.group_purchase_director,1,1,1,0
|
access_mrp_bom_line_group_purchase_director,mrp_bom_line_group_purchase_director,mrp.model_mrp_bom_line,sf_base.group_purchase_director,1,1,1,0
|
||||||
@@ -117,7 +116,7 @@ access_mrp_production_group_quality,mrp_production,model_mrp_production,sf_base.
|
|||||||
access_mrp_production_group_quality_director,mrp_production,model_mrp_production,sf_base.group_quality_director,1,1,0,0
|
access_mrp_production_group_quality_director,mrp_production,model_mrp_production,sf_base.group_quality_director,1,1,0,0
|
||||||
access_mrp_workorder_group_quality,mrp_workorder,model_mrp_workorder,sf_base.group_quality,1,1,0,0
|
access_mrp_workorder_group_quality,mrp_workorder,model_mrp_workorder,sf_base.group_quality,1,1,0,0
|
||||||
access_mrp_workorder_group_quality_director,mrp_workorder,model_mrp_workorder,sf_base.group_quality_director,1,1,0,0
|
access_mrp_workorder_group_quality_director,mrp_workorder,model_mrp_workorder,sf_base.group_quality_director,1,1,0,0
|
||||||
access_mrp_workorder,mrp_workorder,model_mrp_workorder,sf_base.group_plan_dispatch,1,1,1,0
|
access_mrp_workorder,mrp_workorder,model_mrp_workorder,sf_base.group_plan_dispatch,1,1,0,0
|
||||||
access_sf_production_line_group_plan_dispatch,sf.production.line,model_sf_production_line,sf_base.group_plan_dispatch,1,0,0,0
|
access_sf_production_line_group_plan_dispatch,sf.production.line,model_sf_production_line,sf_base.group_plan_dispatch,1,0,0,0
|
||||||
access_sf_production_line_group_plan_director,sf.production.line,model_sf_production_line,sf_base.group_plan_director,1,1,1,0
|
access_sf_production_line_group_plan_director,sf.production.line,model_sf_production_line,sf_base.group_plan_director,1,1,1,0
|
||||||
access_sf_production_line,sf.production.line,model_sf_production_line,sf_maintenance.sf_group_equipment_user,1,1,1,0
|
access_sf_production_line,sf.production.line,model_sf_production_line,sf_maintenance.sf_group_equipment_user,1,1,1,0
|
||||||
@@ -166,21 +165,7 @@ access_sf_agv_scheduling_group_sf_order_user,sf_agv_scheduling_group_sf_order_us
|
|||||||
access_sf_agv_scheduling_group_sf_mrp_manager,sf_agv_scheduling_group_sf_mrp_manager,model_sf_agv_scheduling,sf_base.group_sf_mrp_manager,1,1,1,0
|
access_sf_agv_scheduling_group_sf_mrp_manager,sf_agv_scheduling_group_sf_mrp_manager,model_sf_agv_scheduling,sf_base.group_sf_mrp_manager,1,1,1,0
|
||||||
access_sf_agv_scheduling_group_sf_equipment_user,sf_agv_scheduling_group_sf_equipment_user,model_sf_agv_scheduling,sf_base.group_sf_equipment_user,1,1,1,0
|
access_sf_agv_scheduling_group_sf_equipment_user,sf_agv_scheduling_group_sf_equipment_user,model_sf_agv_scheduling,sf_base.group_sf_equipment_user,1,1,1,0
|
||||||
|
|
||||||
access_sf_technology_design_group_plan_dispatch,sf_technology_design_group_plan_dispatch,model_sf_technology_design,sf_base.group_plan_dispatch,1,1,1,0
|
|
||||||
access_sf_technology_design_group_sf_mrp_manager,sf_technology_design_group_sf_mrp_manager,model_sf_technology_design,sf_base.group_sf_mrp_manager,1,0,0,0
|
|
||||||
access_sf_technology_design_group_production_engineer,sf_technology_design_group_production_engineer,model_sf_technology_design,sf_base.group_production_engineer,1,1,1,0
|
|
||||||
access_sf_technology_design_group_sf_equipment_user,sf_technology_design_group_sf_equipment_user,model_sf_technology_design,sf_base.group_sf_equipment_user,1,0,0,0
|
|
||||||
access_sf_technology_design_group_sf_order_user,sf_technology_design_group_sf_order_user,model_sf_technology_design,sf_base.group_sf_order_user,1,0,0,0
|
|
||||||
access_sf_production_technology_wizard_group_plan_dispatch,sf_production_technology_wizard_group_plan_dispatch,model_sf_production_technology_wizard,sf_base.group_plan_dispatch,1,1,1,0
|
|
||||||
access_sf_production_technology_wizard_group_sf_mrp_manager,sf_production_technology_wizard_group_sf_mrp_manager,model_sf_production_technology_wizard,sf_base.group_sf_mrp_manager,1,0,0,0
|
|
||||||
access_sf_production_technology_wizard_group_production_engineer,sf_production_technology_wizard_group_production_engineer,model_sf_production_technology_wizard,sf_base.group_production_engineer,1,1,1,0
|
|
||||||
access_sf_production_technology_re_adjust_wizard_group_plan_dispatch,sf_production_technology_re_adjust_wizard_group_plan_dispatch,model_sf_production_technology_re_adjust_wizard,sf_base.group_plan_dispatch,1,1,1,0
|
|
||||||
access_sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,model_sf_production_technology_re_adjust_wizard,sf_base.group_sf_mrp_manager,1,1,1,0
|
|
||||||
access_sf_production_technology_re_adjust_wizard_group_production_engineer,sf_production_technology_re_adjust_wizard_group_production_engineer,model_sf_production_technology_re_adjust_wizard,sf_base.group_production_engineer,1,1,1,0
|
|
||||||
|
|
||||||
access_sf_manual_product_model_type_routing_sort_group_sf_mrp_user,sf_manual_product_model_type_routing_sort,model_sf_manual_product_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
|
|
||||||
access_sf_manual_product_model_type_routing_sort_manager,sf_manual_product_model_type_routing_sort,model_sf_manual_product_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
|
|
||||||
access_sf_manual_product_model_type_routing_sort_group_plan_dispatch,sf_manual_product_model_type_routing_sort_group_plan_dispatch,model_sf_manual_product_model_type_routing_sort,sf_base.group_plan_dispatch,1,0,0,0
|
|
||||||
access_sf_detection_result_manager,sf_detection_result_manager,model_sf_detection_result,,1,1,1,1
|
|
||||||
|
|
||||||
access_mrp_workorder_batch_replan_wizard_group_plan_dispatch,mrp_workorder_batch_replan_wizard_group_plan_dispatch,model_mrp_workorder_batch_replan_wizard,sf_base.group_plan_dispatch,1,1,1,0
|
|
||||||
|
|
||||||
|
|||||||
|
@@ -1,50 +0,0 @@
|
|||||||
odoo.define('sf_manufacturing.agv_scheduling_button_confirm', function (require) {
|
|
||||||
const core = require('web.core');
|
|
||||||
const ajax = require('web.ajax');
|
|
||||||
const Dialog = require('web.Dialog');
|
|
||||||
var rpc = require('web.rpc');
|
|
||||||
var _t = core._t;
|
|
||||||
|
|
||||||
async function agv_scheduling_cancel_confirm(parent, {params}) {
|
|
||||||
const dialog = new Dialog(parent, {
|
|
||||||
title: "确认",
|
|
||||||
$content: $('<div>').append("工件正在配送中,确定取消"),
|
|
||||||
buttons: [
|
|
||||||
{ text: "确认", classes: 'btn-primary', close: true, click: () => dispatchConfirmed(parent, params) },
|
|
||||||
{ text: "取消", close: true },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
dialog.open();
|
|
||||||
|
|
||||||
|
|
||||||
async function dispatchConfirmed(parent, params) {
|
|
||||||
rpc.query({
|
|
||||||
model: 'sf.agv.scheduling',
|
|
||||||
method: 'button_cancel',
|
|
||||||
args: [params.agv_scheduling_id],
|
|
||||||
kwargs: {
|
|
||||||
context: params.context,
|
|
||||||
}
|
|
||||||
}).then(res => {
|
|
||||||
parent.services.action.doAction({
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'display_notification',
|
|
||||||
'target': 'new',
|
|
||||||
'params': {
|
|
||||||
'message': '取消成功!',
|
|
||||||
'type': 'success',
|
|
||||||
'sticky': false,
|
|
||||||
'next': {'type': 'ir.actions.act_window_close'},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
parent.services.action.doAction({
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'reload',
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
core.action_registry.add('agv_scheduling_cancel_confirm', agv_scheduling_cancel_confirm);
|
|
||||||
return agv_scheduling_cancel_confirm;
|
|
||||||
});
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
odoo.define('sf_manufacturing.agv_scheduling_resend_confirm', function (require) {
|
|
||||||
const core = require('web.core');
|
|
||||||
const ajax = require('web.ajax');
|
|
||||||
const Dialog = require('web.Dialog');
|
|
||||||
var rpc = require('web.rpc');
|
|
||||||
var _t = core._t;
|
|
||||||
|
|
||||||
async function agv_scheduling_resend_confirm(parent, {params}) {
|
|
||||||
const dialog = new Dialog(parent, {
|
|
||||||
title: "确认",
|
|
||||||
$content: $('<div>').append("工件正在配送中,确定重新下发"),
|
|
||||||
buttons: [
|
|
||||||
{ text: "确认", classes: 'btn-primary', close: true, click: () => dispatchConfirmed(parent, params) },
|
|
||||||
{ text: "取消", close: true },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
dialog.open();
|
|
||||||
|
|
||||||
|
|
||||||
async function dispatchConfirmed(parent, params) {
|
|
||||||
rpc.query({
|
|
||||||
model: 'sf.agv.scheduling',
|
|
||||||
method: 'button_resend',
|
|
||||||
args: [params.agv_scheduling_id],
|
|
||||||
kwargs: {
|
|
||||||
context: params.context,
|
|
||||||
}
|
|
||||||
}).then(res => {
|
|
||||||
parent.services.action.doAction({
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'display_notification',
|
|
||||||
'target': 'new',
|
|
||||||
'params': {
|
|
||||||
'message': '重新下发成功!',
|
|
||||||
'type': 'success',
|
|
||||||
'sticky': false,
|
|
||||||
'next': {'type': 'ir.actions.act_window_close'},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
parent.services.action.doAction({
|
|
||||||
'type': 'ir.actions.client',
|
|
||||||
'tag': 'reload',
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
core.action_registry.add('agv_scheduling_resend_confirm', agv_scheduling_resend_confirm );
|
|
||||||
return agv_scheduling_resend_confirm;
|
|
||||||
});
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
/** @odoo-module **/
|
|
||||||
import { registry } from '@web/core/registry';
|
|
||||||
import { Component } from '@odoo/owl';
|
|
||||||
|
|
||||||
class QRCodeWidget extends Component {
|
|
||||||
// 初始化组件
|
|
||||||
setup() {
|
|
||||||
console.log('QRCodeWidget setup');
|
|
||||||
this.qrCodeValue = ''; // 初始化为空字符串,用于存储条码
|
|
||||||
this.inputBuffer = ''; // 存储临时输入的字符
|
|
||||||
this.inputTimer = null; // 定时器
|
|
||||||
|
|
||||||
// 显式绑定上下文
|
|
||||||
this.onGlobalKeyDown = this.onGlobalKeyDown.bind(this);
|
|
||||||
window.addEventListener('keydown', this.onGlobalKeyDown);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清理事件监听器,防止内存泄漏
|
|
||||||
willUnmount() {
|
|
||||||
window.removeEventListener('keydown', this.onGlobalKeyDown);
|
|
||||||
if (this.inputTimer) {
|
|
||||||
clearTimeout(this.inputTimer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 全局键盘事件监听器
|
|
||||||
onGlobalKeyDown(event) {
|
|
||||||
|
|
||||||
// 如果是Tab键,表示扫码输入结束
|
|
||||||
if (event.key === 'Tab' || event.key === 'Enter') {
|
|
||||||
this.qrCodeValue = this.inputBuffer; // 完整条码赋值
|
|
||||||
console.log('完整条码:', this.qrCodeValue);
|
|
||||||
this.onQRCodeChange(this.qrCodeValue); // 调用父组件的 onQRCodeChange 方法
|
|
||||||
this.inputBuffer = ''; // 清空临时缓冲区
|
|
||||||
event.preventDefault(); // 阻止Tab键的默认行为
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 只处理可打印字符
|
|
||||||
if (event.key.length === 1) {
|
|
||||||
this.inputBuffer += event.key; // 添加到缓冲区
|
|
||||||
// console.log('当前缓冲区:', this.inputBuffer);
|
|
||||||
|
|
||||||
// 清除之前的定时器,重新开始计时
|
|
||||||
if (this.inputTimer) {
|
|
||||||
clearTimeout(this.inputTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 启动一个定时器,如果500ms内没有新的输入,则认为条码输入完成
|
|
||||||
this.inputTimer = setTimeout(() => {
|
|
||||||
this.qrCodeValue = this.inputBuffer;
|
|
||||||
// console.log('定时器触发,完整条码:', this.qrCodeValue);
|
|
||||||
this.inputBuffer = ''; // 清空缓冲区
|
|
||||||
}, 500); // 可以根据需要调整时间
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理二维码输入变更
|
|
||||||
async onQRCodeChange(qrCodeValue) {
|
|
||||||
console.log('onQRCodeChange二维码输入变更', qrCodeValue); // 检查二维码的输入是否被捕获
|
|
||||||
|
|
||||||
if (qrCodeValue) {
|
|
||||||
// console.log('二维码输入变更');
|
|
||||||
try {
|
|
||||||
// 发起 RPC 请求
|
|
||||||
const result = await this.env.services.rpc('/web/dataset/call_kw', {
|
|
||||||
model: 'mrp.workorder',
|
|
||||||
method: 'search_read',
|
|
||||||
args: [
|
|
||||||
[['rfid_code', '=', qrCodeValue]], // 查询条件
|
|
||||||
['id'] // 返回的字段
|
|
||||||
],
|
|
||||||
kwargs: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.length > 0) {
|
|
||||||
console.log('该二维码对应的工单存在!');
|
|
||||||
} else {
|
|
||||||
console.log('未找到对应的工单。');
|
|
||||||
|
|
||||||
const routingTypeField = document.querySelector('[name="routing_type"]');
|
|
||||||
if (routingTypeField) {
|
|
||||||
let fieldValue = routingTypeField.querySelector('span').getAttribute('raw-value');
|
|
||||||
console.log('Routing Type Value:', fieldValue);
|
|
||||||
// 清理多余的引号
|
|
||||||
fieldValue = fieldValue ? fieldValue.replace(/["]+/g, '') : null;
|
|
||||||
console.log(fieldValue);
|
|
||||||
|
|
||||||
if (fieldValue && fieldValue === '装夹预调') {
|
|
||||||
// console.log('routing_type 为装夹预调');
|
|
||||||
|
|
||||||
// 检查 RFID 值
|
|
||||||
if (!qrCodeValue || qrCodeValue.length <= 3) return;
|
|
||||||
|
|
||||||
// 查找 name="button_start" 按钮并触发点击事件
|
|
||||||
const startButton = document.querySelector('[name="button_start"]');
|
|
||||||
if (startButton) {
|
|
||||||
startButton.click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('查询工单时出错:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 返回模板名称
|
|
||||||
static template = 'sf_manufacturing.QRCodeWidgetTemplate';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将自定义字段注册到字段注册表
|
|
||||||
registry.category('fields').add('qrcode_widget', QRCodeWidget);
|
|
||||||
@@ -22,7 +22,8 @@ odoo.define('sf_manufacturing.action_dispatch_confirm', function (require) {
|
|||||||
rpc.query({
|
rpc.query({
|
||||||
model: 'sf.workpiece.delivery.wizard',
|
model: 'sf.workpiece.delivery.wizard',
|
||||||
method: 'confirm',
|
method: 'confirm',
|
||||||
args: [params.active_id],
|
args: [params.active_id]
|
||||||
|
,
|
||||||
kwargs: {
|
kwargs: {
|
||||||
context: params.context,
|
context: params.context,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<templates>
|
|
||||||
<t t-name="sf_manufacturing.QRCodeWidgetTemplate" owl="1">
|
|
||||||
<!-- <div> -->
|
|
||||||
<!-- <input type="text" t-att-value="props.value" placeholder="Scan QR code here" /> -->
|
|
||||||
<!-- </div> -->
|
|
||||||
<div t-esc="props.value">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</t>
|
|
||||||
</templates>
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user