diff --git a/jikimo_frontend/static/src/js/custom_form_status_indicator.js b/jikimo_frontend/static/src/js/custom_form_status_indicator.js
index 306142d4..912c8efa 100644
--- a/jikimo_frontend/static/src/js/custom_form_status_indicator.js
+++ b/jikimo_frontend/static/src/js/custom_form_status_indicator.js
@@ -5,7 +5,7 @@ import {patch} from '@web/core/utils/patch';
import {_t} from "@web/core/l10n/translation";
import {FormStatusIndicator} from "@web/views/form/form_status_indicator/form_status_indicator";
import {ListRenderer} from "@web/views/list/list_renderer";
-import {StatusBarField} from "@web/views/fields/statusbar/statusbar_field";
+// import {StatusBarField} from "@web/views/fields/statusbar/statusbar_field";
import {Field} from "@web/views/fields/field";
@@ -153,34 +153,34 @@ patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', {
// 根据进度条设置水印
-const statusbar_params = {
- '已完工': 'bg-primary',
- '完成': 'bg-primary',
- '采购订单': 'bg-primary',
- '作废': 'bg-danger',
- '封存(报废)': 'bg-danger',
-}
-patch(StatusBarField.prototype, 'jikimo_frontend.StatusBarField', {
- setup() {
- owl.onMounted(this.ribbons);
- return this._super(...arguments);
- },
- ribbons() {
- try {
- const dom = $('.o_form_sheet.position-relative')
- const status = statusbar_params[this.currentName]
- if(status && dom.length) {
- dom.prepend(`
`)
- }
- } catch (e) {
- console.log(e)
- }
- }
-})
+// const statusbar_params = {
+// '已完工': 'bg-primary',
+// '完成': 'bg-primary',
+// '采购订单': 'bg-primary',
+// '作废': 'bg-danger',
+// '封存(报废)': 'bg-danger',
+// }
+// patch(StatusBarField.prototype, 'jikimo_frontend.StatusBarField', {
+// setup() {
+// owl.onMounted(this.ribbons);
+// return this._super(...arguments);
+// },
+// ribbons() {
+// try {
+// const dom = $('.o_form_sheet.position-relative')
+// const status = statusbar_params[this.currentName]
+// if(status && dom.length) {
+// dom.prepend(``)
+// }
+// } catch (e) {
+// console.log(e)
+// }
+// }
+// })
$(function () {
document.addEventListener('click', function () {
diff --git a/jikimo_frontend/static/src/scss/custom_style.scss b/jikimo_frontend/static/src/scss/custom_style.scss
index 0b6fb8bb..cbd1bb4d 100644
--- a/jikimo_frontend/static/src/scss/custom_style.scss
+++ b/jikimo_frontend/static/src/scss/custom_style.scss
@@ -530,4 +530,11 @@ div:has(.o_required_modifier) > label::before {
// 修复表格内容覆盖表头bug
.o_list_renderer .o_list_table tbody th {
position: unset;
-}
\ No newline at end of file
+}
+
+// 修改表格下拉框会被表格下面数据框覆盖的bug
+.tab-pane .o_field_widget {
+ position: relative;
+ z-index: 1;
+}
+
diff --git a/jikimo_system_order/__init__.py b/jikimo_system_order/__init__.py
new file mode 100644
index 00000000..bbc55806
--- /dev/null
+++ b/jikimo_system_order/__init__.py
@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*-
+
+from . import controllers
+from . import models
+from . import wizard
diff --git a/jikimo_system_order/__manifest__.py b/jikimo_system_order/__manifest__.py
new file mode 100644
index 00000000..7f85ed57
--- /dev/null
+++ b/jikimo_system_order/__manifest__.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': "jikimo_system_order",
+
+ 'summary': """
+ 系统工单""",
+
+ 'description': """
+ 用于处理针对系统的工作任务;
+ 员工可以通过系统工单发起申请,由维护人员处理以后,填写处理结果。
+ """,
+
+ 'author': "机企猫",
+ 'website': "http://www.jikimo.com",
+
+ # Categories can be used to filter modules in modules listing
+ # Check https://github.com/odoo/odoo/blob/master/odoo/addons/base/module/module_data.xml
+ # for the full list
+ 'category': 'Uncategorized',
+ 'version': '0.1',
+
+ # any module necessary for this one to work correctly
+ 'depends': ['base','mail'],
+
+ # always loaded
+ 'data': [
+ 'security/account_security.xml',
+ 'security/ir.model.access.csv',
+ 'wizard/order_wizard.xml',
+ 'views/notice_user_config.xml',
+ 'views/yizuo_system_order_view.xml',
+ 'views/work_order_number.xml',
+ 'views/res_config_settings_views.xml',
+ ],
+ # only loaded in demonstration mode
+ 'demo': [
+ 'demo/demo.xml',
+ ],
+}
\ No newline at end of file
diff --git a/jikimo_system_order/controllers/__init__.py b/jikimo_system_order/controllers/__init__.py
new file mode 100644
index 00000000..457bae27
--- /dev/null
+++ b/jikimo_system_order/controllers/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import controllers
\ No newline at end of file
diff --git a/jikimo_system_order/controllers/controllers.py b/jikimo_system_order/controllers/controllers.py
new file mode 100644
index 00000000..cfcad7d0
--- /dev/null
+++ b/jikimo_system_order/controllers/controllers.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from odoo import http
+
+# class TopSystemOrder(http.Controller):
+# @http.route('/jikimo_system_order/jikimo_system_order/', auth='public')
+# def index(self, **kw):
+# return "Hello, world"
+
+# @http.route('/jikimo_system_order/jikimo_system_order/objects/', auth='public')
+# def list(self, **kw):
+# return http.request.render('jikimo_system_order.listing', {
+# 'root': '/jikimo_system_order/jikimo_system_order',
+# 'objects': http.request.env['jikimo_system_order.jikimo_system_order'].search([]),
+# })
+
+# @http.route('/jikimo_system_order/jikimo_system_order/objects//', auth='public')
+# def object(self, obj, **kw):
+# return http.request.render('jikimo_system_order.object', {
+# 'object': obj
+# })
\ No newline at end of file
diff --git a/jikimo_system_order/demo/demo.xml b/jikimo_system_order/demo/demo.xml
new file mode 100644
index 00000000..b167f9be
--- /dev/null
+++ b/jikimo_system_order/demo/demo.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jikimo_system_order/models/__init__.py b/jikimo_system_order/models/__init__.py
new file mode 100644
index 00000000..87b51a43
--- /dev/null
+++ b/jikimo_system_order/models/__init__.py
@@ -0,0 +1,7 @@
+# -*- coding: utf-8 -*-
+
+from . import constant
+from . import order_classify
+from . import system_work_order
+from . import work_order_template
+from . import res_config_setting
diff --git a/jikimo_system_order/models/constant.py b/jikimo_system_order/models/constant.py
new file mode 100644
index 00000000..414371b9
--- /dev/null
+++ b/jikimo_system_order/models/constant.py
@@ -0,0 +1,7 @@
+# -*- coding: utf-8 -*-
+
+# 工单状态
+STATE_SELECTION = [('draft', u'草稿'), ('unconfirmed', u'待确认'), ('pending', u'待处理'),
+ ('processed', u'已处理待评分'), ('completed', u'已完成'), ('closed', u'已关闭')]
+
+GRADE = [('1', '1非常不满意'), ('2', '2不满意'), ('3', '3一般'), ('4', '4满意'), ('5', '5非常满意')]
diff --git a/jikimo_system_order/models/order_classify.py b/jikimo_system_order/models/order_classify.py
new file mode 100644
index 00000000..d143487d
--- /dev/null
+++ b/jikimo_system_order/models/order_classify.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api
+from odoo.exceptions import ValidationError
+
+
+class OrderClassify(models.Model):
+ _name = 'order.classify'
+ _order = 'sequence, name'
+
+
+ @api.constrains('name')
+ def check_base_name(self):
+ """类型名称唯一"""
+ name_obj = self.env['order.classify'].search([('name', '=', self.name)])
+ if len(name_obj) >= 2:
+ raise ValidationError(u'该类型已存在')
+
+ # 名称
+ name = fields.Char(string=u'名称', size=20)
+ # 排序
+ sequence = fields.Integer(default=10)
+ # 是否有效
+ state = fields.Boolean(default=True, string='是否有效')
+
diff --git a/jikimo_system_order/models/res_config_setting.py b/jikimo_system_order/models/res_config_setting.py
new file mode 100644
index 00000000..44a9a1d7
--- /dev/null
+++ b/jikimo_system_order/models/res_config_setting.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+import logging
+from odoo import api, fields, models, _
+
+_logger = logging.getLogger(__name__)
+
+
+class ResModelWeConfigSettings(models.TransientModel):
+ _inherit = 'res.config.settings'
+
+ lost_agent_id = fields.Char('企微通知应用ID')
+
+ @api.model
+ def get_values(self):
+ """
+ 重载获取参数的方法,参数都存在系统参数中
+ :return:
+ """
+ values = super(ResModelWeConfigSettings, self).get_values()
+ config = self.env['ir.config_parameter'].sudo()
+ lost_agent_id = config.get_param('lost_agent_id', default='')
+ values.update(
+ lost_agent_id=lost_agent_id,
+ )
+ return values
+
+ def set_values(self):
+ super(ResModelWeConfigSettings, self).set_values()
+ ir_config = self.env['ir.config_parameter'].sudo()
+ ir_config.set_param("lost_agent_id", self.lost_agent_id or "")
+
diff --git a/jikimo_system_order/models/system_work_order.py b/jikimo_system_order/models/system_work_order.py
new file mode 100644
index 00000000..1a7bff5e
--- /dev/null
+++ b/jikimo_system_order/models/system_work_order.py
@@ -0,0 +1,183 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api
+from odoo.exceptions import ValidationError
+from odoo import exceptions
+from .constant import STATE_SELECTION, GRADE
+import datetime
+import logging
+
+
+class SystemWorkOrder(models.Model):
+ _name = 'system.work.order'
+ _inherit = ['mail.thread', 'mail.activity.mixin']
+ _order = 'date desc'
+ _description = u'系统工单'
+ _rec_name = 'order_number'
+
+ def get_is_technicist(self):
+ self._cr.execute(
+ "select u.id from res_users u left join res_groups_users_rel r on r.uid = u.id where r.gid in (select g.id from res_groups g where g.name = '技术员权限') and u.id ='%s'",
+ (self.env.user.id,))
+ hr = self._cr.dictfetchall()
+ if len(hr) > 0:
+ return True
+ else:
+ return False
+
+ # def get_user_department_id(self):
+ # """根据用户id系统员工id"""
+ # employee = self.env['hr.employee'].sudo().search([('user_id', '=', self.env.uid)], limit=1)
+ # if employee:
+ # if len(employee) > 0:
+ # if not employee.department_id:
+ # raise exceptions.Warning(u'您当前使用的用户没有所属部门')
+ # return employee.department_id
+ # else:
+ # return False
+ # else:
+ # raise exceptions.Warning(u'您当前使用的用户没有关联员工')
+
+ @api.onchange('order_template_id')
+ def get_title(self):
+ """选择模板自动填充"""
+ if self.order_template_id:
+ self.title = self.order_template_id.title_template
+ self.text = self.order_template_id.text_template
+
+ # 工单编号
+ order_number = fields.Char(string=u'工单编号', default='/')
+ # 紧急程度
+ urgency_degree = fields.Selection([('0', u'0星'), ('1', u'一星'), ('2', u'二星'), ('3', u'三星'), ('4', u'四星'),
+ ('5', u'五星')], string=u'紧急程度', help='五星为最紧急!', default='5')
+ # 工单分类(可以配置,并调整优先级)
+ order_type = fields.Many2one('order.classify', string=u'工单分类', domain=[('state', '=', True)])
+ # 发起人所属公司(res.company)
+ initiator_company_id = fields.Many2one('res.company', string=u'发起人所属公司', default=lambda self: self.env.user.company_id)
+ # 发起人部门(hr.department)
+ # initiator_department_id = fields.Many2one('hr.department', string=u'发起人部门', default=get_user_department_id)
+ # 发起人(hr.employee)
+ initiator_id = fields.Many2one('res.users', string=u'发起人', default=lambda self: self.env.user)
+ # 发起时间
+ date = fields.Datetime(string=u'发起时间', default=lambda self: fields.datetime.now())
+ # 确认人
+ confirm_id = fields.Many2one('res.users', string=u'确认人')
+ # 确认日期
+ confirmation_date = fields.Datetime(string=u'确认时间')
+ # 模板
+ order_template_id = fields.Many2one('work.order.template', string=u'模板', domain=[('state', '=', True)])
+ # 标题
+ title = fields.Char(string=u'标题')
+ # 正文
+ text = fields.Html(string=u'正文')
+ # 状态[草稿\待确认\待处理\已处理\已关闭]
+ state = fields.Selection(STATE_SELECTION, default='draft', string=u'状态')
+ # 关闭原因
+ close_cause = fields.Text(string=u'关闭问题原因')
+ # 关闭时间
+ close_time = fields.Datetime(string=u'关闭问题时间')
+ # 关闭人
+ close_user_id = fields.Many2one('res.users', string=u'关闭人')
+ # 解决人
+ solve_people_id = fields.Many2one('res.users', string=u'解决人')
+ # 用户实际问题
+ users_problem = fields.Text(string=u'用户实际问题')
+ # 最终解决方案
+ solution = fields.Text(string=u'最终解决方案')
+ # 判断是否为技术人员
+ # is_technicist = fields.Boolean(string=u'是否为技术人员', default=get_is_technicist)
+ # 打分
+ grade = fields.Selection(GRADE, string=u'评分')
+ # 评价按钮的显示
+ is_display = fields.Boolean('控制显示评价按钮', compute='compute_is_display')
+
+ def compute_is_display(self):
+ for item in self:
+ if item.state == 'processed' and self.env.user.id == item.initiator_id.id:
+ item.is_display = True
+ else:
+ item.is_display = False
+
+ @api.onchange('order_type')
+ def _onchange_order_type(self):
+ self.order_template_id = None
+ self.title = None
+ self.text = None
+
+ @api.model
+ def create(self, vals):
+ # 创建编号
+ if vals.get('order_number', '/') == '/':
+ vals['order_number'] = self.env['ir.sequence'].get('system.work.order') or '/'
+ return super(SystemWorkOrder, self).create(vals)
+
+ def do_draft(self, order=None):
+ """状态草稿"""
+ bill = self
+ if order:
+ bill = order
+ if bill.state == 'unconfirmed':
+ state_remark = u'待确认 --> 草稿'
+ # bill.message_post(u'操作人:%s,操作时间:%s,状态变更过程:%s' % (self.env.user.name,
+ # (datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S'), state_remark))
+ bill.state = 'draft'
+
+ def do_unconfirmed(self):
+ """状态待确认"""
+ if self.state == 'draft':
+ state_remark = u'草稿 --> 待确认'
+ # self.message_post(u'操作人:%s,操作时间:%s,状态变更过程:%s' % (
+ # self.env.user.name,
+ # (datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S'), state_remark))
+ self.state = 'unconfirmed'
+ # 获取通知人
+ objs = self.env['system.order.notice'].search([])
+ user_ids = objs.notice_user_ids.filtered(lambda item: item.we_employee_id not in ['', False])
+ we_employee_ids = user_ids.mapped('we_employee_id')
+ lost_agent_id = self.env['ir.config_parameter'].sudo().get_param('lost_agent_id')
+ wechat = self.env['we.config'].sudo().get_wechat(agent_id=lost_agent_id)
+ # agent_id, user_ids, content
+ content = """您有一张工单待处理:**工单标题:{2}**
+ >创建人:{1}
+ >提交时间:{3}
+ >紧急程度:{0}星
+ 请查看工单消息,并及时处理!
+ """.format(self.urgency_degree,
+ self.initiator_id.name, self.title, (self.date + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M'))
+ for we_employee_id in we_employee_ids:
+ try:
+ wechat.message.send_markdown(agent_id=lost_agent_id, user_ids=we_employee_id, content=content)
+ except Exception as e:
+ logging.error('工单处理发送消息异常%s' % str(e))
+
+ return True
+
+ def do_pending(self):
+ """状态待处理"""
+ if self.state == 'unconfirmed':
+ state_remark = u'待确认 --> 待处理'
+ # self.message_post(u'操作人:%s,操作时间:%s,状态变更过程:%s' % (
+ # self.env.user.name,
+ # (datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S'), state_remark))
+ self.state = 'pending'
+ self.confirm_id = self.env.user
+ self.confirmation_date = fields.datetime.now()
+ return True
+
+ def urned_off(self):
+ """状态关闭"""
+ if self.close_cause:
+ self.state = 'closed'
+ self.close_time = fields.datetime.now()
+ else:
+ raise ValidationError(u'请注明关闭原因')
+ return True
+
+ def unlink(self):
+ for item in self:
+ if item.state != "draft":
+ raise ValidationError(u'只能删除状态为【草稿】的工单。')
+ elif item.env.uid != item.initiator_id.id:
+ raise ValidationError(u'非本人不能删除')
+ else:
+ super(SystemWorkOrder, item).unlink()
diff --git a/jikimo_system_order/models/work_order_template.py b/jikimo_system_order/models/work_order_template.py
new file mode 100644
index 00000000..f50fd42d
--- /dev/null
+++ b/jikimo_system_order/models/work_order_template.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api
+
+
+class WorkOrderTemplate(models.Model):
+ _name = 'work.order.template'
+ _order = 'num'
+
+ # 编号
+ num = fields.Char(string=u'编号', default='/')
+ # 名称
+ name = fields.Char(string=u'模板名称', required="1")
+ # 分类
+ work_order_type = fields.Many2one('order.classify', string=u'系统工单分类', domain=[('state', '=', True)])
+ # 模板标题
+ title_template = fields.Char(string=u'模板标题')
+ # 模板正文
+ text_template = fields.Html(string=u'模板正文')
+ # 模板说明
+ template_explain = fields.Text(string=u'模板说明')
+ # 是否有效
+ state = fields.Boolean(default=True, string=u'是否有效')
+
+ @api.model
+ def create(self, vals):
+ # 创建编号
+ if vals.get('num', '/') == '/':
+ vals['num'] = self.env['ir.sequence'].get('work.order.template') or '/'
+ return super(WorkOrderTemplate, self).create(vals)
+
+
+class SystemOrderNotice(models.Model):
+ _name = 'system.order.notice'
+ _description = '工单处理人设置'
+
+ notice_user_ids = fields.Many2many('res.users', string='工单处理人')
+
diff --git a/jikimo_system_order/security/account_security.xml b/jikimo_system_order/security/account_security.xml
new file mode 100644
index 00000000..8356964e
--- /dev/null
+++ b/jikimo_system_order/security/account_security.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+ 运维权限
+
+
+
+ 用户访问工单信息
+
+
+ [('initiator_id', '=', user.id)]
+
+
+
+ 运维访问工单信息
+
+
+ [(1, '=', 1)]
+
+
+
+
diff --git a/jikimo_system_order/security/ir.model.access.csv b/jikimo_system_order/security/ir.model.access.csv
new file mode 100644
index 00000000..5c76352d
--- /dev/null
+++ b/jikimo_system_order/security/ir.model.access.csv
@@ -0,0 +1,16 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+
+inside_system_order_classify_r,jikimo_system_order.order_classify,model_order_classify,,1,1,1,1
+inside_system_work_order_rc,jikimo_system_order.system_work_order,model_system_work_order,,1,1,1,1
+inside_work_order_template_r,jikimo_system_order.work_order_template,model_work_order_template,,1,1,1,1
+
+inside_system_order_classify_rwc,jikimo_system_order.order_classify,model_order_classify,group_operations_permissions_rwc,1,1,1,0
+inside_system_work_order_rwc,jikimo_system_order.system_work_order,model_system_work_order,group_operations_permissions_rwc,1,1,1,0
+inside_work_order_template_rwc,jikimo_system_order.work_order_template,model_work_order_template,group_operations_permissions_rwc,1,1,1,0
+
+order_close_wizard_group_user,jikimo_system_order.order_close_wizard,model_order_close_wizard,base.group_user,1,1,1,1
+order_other_wizard_group_user,jikimo_system_order.order_other_wizard,model_order_other_wizard,base.group_user,1,1,1,1
+order_technician_wizard_group_user,jikimo_system_order.order_technician_wizard,model_order_technician_wizard,base.group_user,1,1,1,1
+system_work_order_wizard_group_user,jikimo_system_order.system_work_order_wizard,model_system_work_order_wizard,base.group_user,1,1,1,1
+
+system_order_notice_group_user,jikimo_system_order.system_order_notice,model_system_order_notice,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/jikimo_system_order/static/description/icon.png b/jikimo_system_order/static/description/icon.png
new file mode 100644
index 00000000..24aa8fc8
Binary files /dev/null and b/jikimo_system_order/static/description/icon.png differ
diff --git a/jikimo_system_order/views/notice_user_config.xml b/jikimo_system_order/views/notice_user_config.xml
new file mode 100644
index 00000000..353afb96
--- /dev/null
+++ b/jikimo_system_order/views/notice_user_config.xml
@@ -0,0 +1,58 @@
+
+
+
+ # ---------- 工单通知处理人设置 ------------
+
+
+ tree.system.order.notice
+ system.order.notice
+
+
+
+
+
+
+
+
+
+ search.system.order.notice
+ system.order.notice
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 工单处理人
+ system.order.notice
+ tree
+ []
+ {}
+
+
+ [工单处理人] 还没有哦!点左上角的[创建]按钮,沙发归你了!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jikimo_system_order/views/res_config_settings_views.xml b/jikimo_system_order/views/res_config_settings_views.xml
new file mode 100644
index 00000000..40cdc443
--- /dev/null
+++ b/jikimo_system_order/views/res_config_settings_views.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ res.config.settings.we.view.form.inherit.bpm
+ res.config.settings
+
+
+
+
+
+
+
+
+
diff --git a/jikimo_system_order/views/work_order_number.xml b/jikimo_system_order/views/work_order_number.xml
new file mode 100644
index 00000000..63f0d5a3
--- /dev/null
+++ b/jikimo_system_order/views/work_order_number.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+ seq_work_order
+
+ system.work.order
+ SO%(year)s%(month)s%(day)s
+ 1
+
+
+
+
+ seq_order_template
+
+ work.order.template
+ TL
+ 1
+
+
+
\ No newline at end of file
diff --git a/jikimo_system_order/views/yizuo_system_order_view.xml b/jikimo_system_order/views/yizuo_system_order_view.xml
new file mode 100644
index 00000000..006a085d
--- /dev/null
+++ b/jikimo_system_order/views/yizuo_system_order_view.xml
@@ -0,0 +1,243 @@
+
+
+
+
+
+
+ 工单信息
+ system.work.order
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 新建系统工单
+ system.work.order
+
+
+
+
+
+
+
+ 搜索工单
+ system.work.order
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 工单图表
+ system.work.order
+
+
+
+
+
+
+
+
+
+
+
+ 工单
+ system.work.order
+ tree,form,search,graph,pivot
+
+
+
+
+ 工单模板信息
+ work.order.template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 新建系统工单模板
+ work.order.template
+
+
+
+
+
+
+
+ 工单模板
+ work.order.template
+ tree,form
+
+
+
+
+ 工单分类信息
+ order.classify
+
+
+
+
+
+
+
+
+
+
+
+ 新建系统分类信息
+ order.classify
+
+
+
+
+
+
+
+ 工单分类
+ order.classify
+ tree,form
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jikimo_system_order/wizard/__init__.py b/jikimo_system_order/wizard/__init__.py
new file mode 100644
index 00000000..8cf586ce
--- /dev/null
+++ b/jikimo_system_order/wizard/__init__.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+
+from . import order_other_wizard
+from . import order_technician_wizard
+from . import order_close_wizard
+from . import system_work_order_wizard
diff --git a/jikimo_system_order/wizard/order_close_wizard.py b/jikimo_system_order/wizard/order_close_wizard.py
new file mode 100644
index 00000000..ca10ae7c
--- /dev/null
+++ b/jikimo_system_order/wizard/order_close_wizard.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api
+from odoo.addons.jikimo_system_order.models.constant import STATE_SELECTION
+from odoo.exceptions import ValidationError
+import datetime, logging
+
+
+class OrderCloseWizard(models.TransientModel):
+ _name = 'order.close.wizard'
+
+
+ def get_context(self):
+ if self._context.get('active_id'):
+ obj = self.env['system.work.order'].browse(self._context.get('active_id'))
+ if obj.initiator_id.id != self.env.user.id:
+ raise ValidationError(u'非本人无法操作')
+ return obj
+
+ order_id = fields.Many2one('system.work.order', string=u'工单ID',
+ default=lambda self: self.get_context().id)
+ # 关闭原因
+ close_cause = fields.Text(string=u'关闭问题原因', default=lambda self: self.get_context().close_cause)
+ # 关闭时间
+ close_time = fields.Datetime(string=u'关闭问题时间', default=fields.datetime.now())
+ # 状态
+ state = fields.Selection(STATE_SELECTION, default='closed', string=u'状态')
+ # 关闭人
+ close_user_id = fields.Many2one('res.users', string=u'关闭人', default=lambda self: self.env.user)
+
+
+ def sure(self):
+ self.order_id.close_cause = self.close_cause
+ self.order_id.close_time = self.close_time
+ if self.order_id.state == 'unconfirmed':
+ state_remark = u'待确认 --> 已关闭'
+ if self.order_id.state == 'pending':
+ state_remark = u'待处理 --> 已关闭'
+ if self.order_id.state == 'processed':
+ state_remark = u'已处理待评分 --> 已关闭'
+ # self.order_id.message_post(u'操作人:%s,操作时间:%s,状态变更过程:%s' % (
+ # self.env.user.name,
+ # (datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S'), state_remark))
+ self.order_id.state = self.state
+ self.order_id.close_user_id = self.close_user_id
+ we_employee_ids = []
+ if self.order_id.initiator_id.we_employee_id:
+ we_employee_ids.append(self.order_id.initiator_id.we_employee_id)
+ lost_agent_id = self.env['ir.config_parameter'].sudo().get_param('lost_agent_id')
+ wechat = self.env['we.config'].sudo().get_wechat(agent_id=lost_agent_id)
+ # agent_id, user_ids, content
+ content = """您提交的工单-**工单标题:{0}**-**已关闭**
+ >提交时间:{1}
+ >处理时间:{2}
+ >处理人:{3}
+ 如有问题,请联系系统管理员!
+ """.format(self.order_id.title,
+ (self.order_id.date + datetime.timedelta(hours=8)).strftime(
+ '%Y-%m-%d %H:%M'), (datetime.datetime.now() + datetime.timedelta(
+ hours=8)).strftime('%Y-%m-%d %H:%M'), self.env.user.name or '')
+ # wechat.message.send_markdown(agent_id=lost_agent_id, user_ids=we_employee_ids, content=content)
+ for we_employee_id in we_employee_ids:
+ try:
+ wechat.message.send_markdown(agent_id=lost_agent_id, user_ids=we_employee_id, content=content)
+ except Exception as e:
+ logging.error('工单关闭发送消息异常%s' % str(e))
+ return {}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jikimo_system_order/wizard/order_other_wizard.py b/jikimo_system_order/wizard/order_other_wizard.py
new file mode 100644
index 00000000..3f6c8710
--- /dev/null
+++ b/jikimo_system_order/wizard/order_other_wizard.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api
+from odoo.exceptions import ValidationError
+from odoo.addons.jikimo_system_order.models.constant import STATE_SELECTION, GRADE
+import datetime
+
+
+class OrderOtherWizard(models.TransientModel):
+ _name = 'order.other.wizard'
+
+
+ def get_context(self):
+ if self._context.get('active_id'):
+ obj = self.env['system.work.order'].browse(self._context.get('active_id'))
+ if obj.initiator_id.id != self.env.user.id:
+ raise ValidationError(u'非本人无法操作')
+ return obj
+
+ order_id = fields.Many2one('system.work.order', string=u'工单ID',
+ default=lambda self: self.get_context().id)
+ # 关闭时间
+ close_time = fields.Datetime(string=u'关闭时间', default=fields.datetime.now())
+ # 状态
+ state = fields.Selection(STATE_SELECTION, default='completed', string=u'状态')
+ # 打分
+ grade = fields.Selection(GRADE, string=u'评分')
+ # 关闭人
+ close_user_id = fields.Many2one('res.users', string=u'关闭人', default=lambda self: self.env.user)
+
+
+ def sure(self):
+ self.order_id.close_time = self.close_time
+ self.order_id.grade = self.grade
+ if self.order_id.state == 'processed':
+ state_remark = u'已处理待评分 --> 已完成'
+ # self.order_id.message_post(u'操作人:%s,操作时间:%s,状态变更过程:%s' % (
+ # self.env.user.name,
+ # (datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S'), state_remark))
+ self.order_id.state = self.state
+ self.order_id.close_user_id = self.close_user_id
+ return {}
diff --git a/jikimo_system_order/wizard/order_technician_wizard.py b/jikimo_system_order/wizard/order_technician_wizard.py
new file mode 100644
index 00000000..78458038
--- /dev/null
+++ b/jikimo_system_order/wizard/order_technician_wizard.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api
+from odoo.addons.jikimo_system_order.models.constant import STATE_SELECTION
+import datetime
+import logging
+
+
+class OrderTechnicianWizard(models.TransientModel):
+ _name = 'order.technician.wizard'
+
+ order_id = fields.Many2one('system.work.order', string=u'工单ID',
+ default=lambda self: self.env.context.get('active_id'))
+ # 解决人
+ solve_people_id = fields.Many2one('res.users', string=u'解决人', default=lambda self: self.env.user)
+ # 用户实际问题
+ users_problem = fields.Text(string=u'用户实际问题')
+ # 最终解决方案
+ solution = fields.Text(string=u'最终解决方案')
+ # 状态
+ state = fields.Selection(STATE_SELECTION, default='processed', string=u'状态')
+
+ def sure(self):
+ self.order_id.solve_people_id = self.solve_people_id
+ self.order_id.users_problem = self.users_problem
+ self.order_id.solution = self.solution
+ if self.order_id.state == 'pending':
+ state_remark = u'待处理 --> 已处理待评分'
+ # self.order_id.message_post(u'操作人:%s,操作时间:%s,状态变更过程:%s' % (
+ # self.env.user.name,
+ # (datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S'), state_remark))
+ self.order_id.state = self.state
+ # 获取通知人
+ # objs = self.env['system.order.notice'].search([])
+ # user_ids = objs.notice_user_ids.filtered(lambda item: item.we_employee_id not in ['', False])
+ # we_employee_ids = user_ids.mapped('we_employee_id')
+ we_employee_ids = []
+ if self.order_id.initiator_id.we_employee_id:
+ we_employee_ids.append(self.order_id.initiator_id.we_employee_id)
+ print(we_employee_ids)
+ lost_agent_id = self.env['ir.config_parameter'].sudo().get_param('lost_agent_id')
+ wechat = self.env['we.config'].sudo().get_wechat(agent_id=lost_agent_id)
+ # agent_id, user_ids, content
+ content = """您提交的工单-**工单标题:{0}**-**已处理**
+ >提交时间:{1}
+ >处理反馈:{4}
+ >处理时间:{2}
+ >处理人:{3}
+ 如有问题,请联系系统管理员!
+ """.format(self.order_id.title,
+ (self.order_id.date + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M'), (datetime.datetime.now() + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M'), self.env.user.name or '', self.solution or '')
+ # wechat.message.send_markdown(agent_id=lost_agent_id, user_ids=we_employee_ids, content=content)
+ for we_employee_id in we_employee_ids:
+ try:
+ wechat.message.send_markdown(agent_id=lost_agent_id, user_ids=we_employee_id, content=content)
+ except Exception as e:
+ logging.error('工单处理发送消息异常%s' % str(e))
+
+ return {}
diff --git a/jikimo_system_order/wizard/order_wizard.xml b/jikimo_system_order/wizard/order_wizard.xml
new file mode 100644
index 00000000..64c13ccd
--- /dev/null
+++ b/jikimo_system_order/wizard/order_wizard.xml
@@ -0,0 +1,122 @@
+
+
+
+
+
+ 技术员向导
+ order.technician.wizard
+
+
+
+
+
+
+ 技术员编辑
+ ir.actions.act_window
+ order.technician.wizard
+ form
+
+ {'display_default_code':False}
+ new
+
+
+
+
+
+
+ 其它向导
+ order.other.wizard
+
+
+
+
+
+
+ 其它编辑
+ ir.actions.act_window
+ order.other.wizard
+ form
+
+ {'display_default_code':False}
+ new
+
+
+
+
+ 关闭向导
+ order.close.wizard
+
+
+
+
+
+
+ 关闭工单
+ ir.actions.act_window
+ order.close.wizard
+ form
+
+ {'display_default_code':False}
+ new
+
+
+
+ system_work_order_wizard_view
+ system.work.order.wizard
+
+
+
+
+
+
+ 二次确认
+ ir.actions.act_window
+ system.work.order.wizard
+ form
+ new
+
+
+
diff --git a/jikimo_system_order/wizard/system_work_order_wizard.py b/jikimo_system_order/wizard/system_work_order_wizard.py
new file mode 100644
index 00000000..8c8f95dc
--- /dev/null
+++ b/jikimo_system_order/wizard/system_work_order_wizard.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# @Time : 2017/12/12 9:46
+# @Author : GuoXiang
+# @Site :
+# @File : system_work_order_wizard.py
+# @Software: PyCharm
+# @Desc :
+# @license : Copyright©2018 www.dasmaster.com All Rights Reserved.
+# @Contact : xg1230205321@163.com
+from odoo import models, api, fields
+from odoo.exceptions import ValidationError
+
+
+class SystemWorkOrderWizard(models.TransientModel):
+ _name = "system.work.order.wizard"
+ _description = u"追回确认"
+
+
+ def _get_explain(self):
+ if self._context.get('object_id'):
+ obj = self.env['system.work.order'].browse(self._context.get('object_id'))
+ if obj.initiator_id.id != self.env.user.id:
+ raise ValidationError(u'非本人无法操作')
+ if self._context.get('explain'):
+ return self._context["explain"]
+
+ explain = fields.Char(default=_get_explain)
+
+
+ def sure(self):
+ """
+ 确认
+ :return:
+ """
+ if self._context.get('object_id') and self._context.get('object_name') and self._context.get(
+ 'explain') and self._context.get('function_name'):
+ work_sheet_obj = self.env[self._context["object_name"]].search([('id', '=', int(self._context["object_id"]))])
+ class_name = self._context.get('object_name') # 获得对象类名
+ method_name = self._context.get('function_name') # 获得对象的方法
+ obj_function = getattr(self.env[class_name], method_name)
+ obj_function(work_sheet_obj)
diff --git a/sf_base/models/common.py b/sf_base/models/common.py
index 6fd7d814..888f3eaf 100644
--- a/sf_base/models/common.py
+++ b/sf_base/models/common.py
@@ -61,12 +61,10 @@ class MrsMaterialModel(models.Model):
supplier_ids = fields.One2many('sf.supplier.sort', 'materials_model_id', string='供应商')
active = fields.Boolean('有效', default=True)
- @api.onchange('gain_way')
- def _check_gain_way(self):
- if not self.gain_way:
- raise UserError("请选择获取方式")
- if self.gain_way in ['外协', '采购']:
- if not self.supplier_ids:
+ @api.constrains("gain_way")
+ def _check_supplier_ids(self):
+ for item in self:
+ if item.gain_way in ('外协', '采购') and not item.supplier_ids:
raise UserError("请添加供应商")
diff --git a/sf_base/views/common_view.xml b/sf_base/views/common_view.xml
index 74e916a8..a7cbcf9e 100644
--- a/sf_base/views/common_view.xml
+++ b/sf_base/views/common_view.xml
@@ -251,7 +251,7 @@
-
+
@@ -270,9 +270,9 @@
-
+
-
+
diff --git a/sf_bf_connect/models/jd_eclp.py b/sf_bf_connect/models/jd_eclp.py
index 7879938e..ec14f7e1 100644
--- a/sf_bf_connect/models/jd_eclp.py
+++ b/sf_bf_connect/models/jd_eclp.py
@@ -161,6 +161,9 @@ class JdEclp(models.Model):
url2 = config['bfm_url'] + '/api/get/jd/no'
response = requests.post(url2, json=json2, data=None)
# _logger.info('调用成功2', response.json()['result']['wbNo'])
+ tem_ret = response.json().get('result')
+ if not tem_ret:
+ raise ValidationError('京东物流返回异常,请联系管理员')
self.carrier_tracking_ref = response.json()['result'].get('wbNo')
if not self.carrier_tracking_ref:
raise ValidationError('物流下单未成功,请联系管理员')
diff --git a/sf_dlm_management/data/stock_data.xml b/sf_dlm_management/data/stock_data.xml
index 3d2c4527..be2a36e0 100644
--- a/sf_dlm_management/data/stock_data.xml
+++ b/sf_dlm_management/data/stock_data.xml
@@ -22,6 +22,16 @@
+
+ 拆解
+
+ internal
+ DJCJ
+ true
+ true
+
+
+
刀具组装入库
diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py
index 22341405..79542016 100644
--- a/sf_manufacturing/models/mrp_production.py
+++ b/sf_manufacturing/models/mrp_production.py
@@ -124,12 +124,17 @@ class MrpProduction(models.Model):
if (
production.state == 'to_close' or production.state == 'progress') and production.schedule_state == '未排':
production.state = 'confirmed'
+ elif production.state == 'pending_cam' and production.schedule_state == '未排':
+ production.state = 'confirmed'
elif production.state == 'to_close' and production.schedule_state == '已排':
production.state = 'pending_cam'
if production.state == 'progress':
if all(wo_state not in ('progress', 'done') for wo_state in production.workorder_ids.mapped('state')):
production.state = 'pending_cam'
+ if production.state == 'pending_cam':
+ if all(wo_state in 'done' for wo_state in production.workorder_ids.mapped('state')):
+ production.state = 'done'
def action_check(self):
"""
@@ -699,7 +704,7 @@ class MrpProduction(models.Model):
logging.info('qty_produced:%s' % production.qty_produced)
production.write({
'date_finished': fields.Datetime.now(),
- 'product_qty': production.product_qty if production.qty_produced < 1.0 else production.qty_produced,
+ 'product_qty': production.qty_produced,
'priority': '0',
'is_locked': True,
'state': 'done',
diff --git a/sf_manufacturing/models/mrp_workcenter.py b/sf_manufacturing/models/mrp_workcenter.py
index 7d70ae5e..64cf2d8d 100644
--- a/sf_manufacturing/models/mrp_workcenter.py
+++ b/sf_manufacturing/models/mrp_workcenter.py
@@ -5,24 +5,49 @@ from odoo.addons.resource.models.resource import Intervals
class ResWorkcenter(models.Model):
- _inherit = "mrp.workcenter"
+ _name = "mrp.workcenter"
+ _inherit = ['mrp.workcenter', 'mail.thread']
# 生产线显示
production_line_show = fields.Char(string='生产线名称')
- equipment_id = fields.Many2one(
- 'maintenance.equipment', string="设备",
- )
+ equipment_id = fields.Many2one('maintenance.equipment', string="设备", tracking=True)
production_line_id = fields.Many2one('sf.production.line', string='生产线',
related='equipment_id.production_line_id', store=True)
-
is_process_outsourcing = fields.Boolean('工艺外协')
- users_ids = fields.Many2many("res.users", 'users_workcenter')
+ users_ids = fields.Many2many("res.users", 'users_workcenter', tracking=True)
+ def write(self, vals):
+ if 'users_ids' in vals:
+ old_users = self.users_ids
+ res = super(ResWorkcenter, self).write(vals)
+ new_users = self.users_ids
+ added_users = new_users - old_users
+ removed_users = old_users - new_users
+ if added_users or removed_users:
+ message = "增加 → %s ; 移除 → %s (可操作用户)" % (
+ # ','.join(added_users.mapped('name')), ','.join(removed_users.mapped('name')))
+ added_users.mapped('name'), removed_users.mapped('name'))
+ self.message_post(body=message)
+ return res
+ return super(ResWorkcenter, self).write(vals)
+ name = fields.Char('Work Center', related='resource_id.name', store=True, readonly=False, tracking=True)
+ time_efficiency = fields.Float('Time Efficiency', related='resource_id.time_efficiency', default=100, store=True,
+ readonly=False, tracking=True)
+ default_capacity = fields.Float(
+ 'Capacity', default=1.0,
+ help="Default number of pieces (in product UoM) that can be produced in parallel (at the same time) at this work center. For example: the capacity is 5 and you need to produce 10 units, then the operation time listed on the BOM will be multiplied by two. However, note that both time before and after production will only be counted once.",
+ tracking=True)
+ oee_target = fields.Float(
+ string='OEE Target', help="Overall Effective Efficiency Target in percentage", default=90, tracking=True)
+
+ time_start = fields.Float('Setup Time', tracking=True)
+ time_stop = fields.Float('Cleanup Time', tracking=True)
+ costs_hour = fields.Float(string='Cost per hour', help='Hourly processing cost.', default=0.0, tracking=True)
equipment_status = fields.Selection(
- [("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"),("空闲", "空闲"),("封存(报废)", "封存(报废)")],
+ [("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"), ("封存(报废)", "封存(报废)")],
string="设备状态", related='equipment_id.state')
# @api.depends('equipment_id')
diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py
index 731650af..0e10af72 100644
--- a/sf_manufacturing/models/mrp_workorder.py
+++ b/sf_manufacturing/models/mrp_workorder.py
@@ -165,7 +165,8 @@ class ResMrpWorkOrder(models.Model):
保存名称
"""
for record in self:
- record.save_name = record.production_id.name.replace('/', '_')
+ tem_name = record.production_id.name.replace('/', '_')
+ record.save_name = tem_name + '_' + record.processing_panel
schedule_state = fields.Selection(related='production_id.schedule_state', store=True)
# 工件装夹信息
@@ -1039,7 +1040,7 @@ class ResMrpWorkOrder(models.Model):
move_raw_id.quantity_done = move_raw_id.product_uom_qty
record.process_state = '已完工'
record.production_id.process_state = '已完工'
- if record.routing_type in ['解除装夹', '表面工艺']:
+ if record.routing_type in ['表面工艺']:
raw_move = self.env['stock.move'].sudo().search(
[('origin', '=', record.production_id.name),
('procure_method', 'in', ['make_to_order', 'make_to_stock']),
@@ -1115,6 +1116,16 @@ class ResMrpWorkOrder(models.Model):
# logging.info('button_send_program_again error:%s' % e)
# raise UserError("重新下发nc程序失败,请联系管理员")
+ def print_method(self):
+ """
+ 解除装夹处调用关联制造订单的关联序列号的打印方法
+ """
+ if self.production_id:
+ if self.production_id.lot_producing_id:
+ self.production_id.lot_producing_id.print_single_method()
+ else:
+ raise UserError("无关联制造订单或关联序列号,无法打印。请检查!")
+
class CNCprocessing(models.Model):
_name = 'sf.cnc.processing'
diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py
index 9234060f..a1543b8f 100644
--- a/sf_manufacturing/models/stock.py
+++ b/sf_manufacturing/models/stock.py
@@ -204,7 +204,8 @@ class StockRule(models.Model):
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
productions_values)
- 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())
'''
创建工单
@@ -404,6 +405,7 @@ class ProductionLot(models.Model):
def print_single_method(self):
+ print('self.name========== %s' % self.name)
self.ensure_one()
qr_code_data = self.qr_code_image
if not qr_code_data:
diff --git a/sf_manufacturing/views/mrp_workcenter_views.xml b/sf_manufacturing/views/mrp_workcenter_views.xml
index 9aad2a99..ad433bf6 100644
--- a/sf_manufacturing/views/mrp_workcenter_views.xml
+++ b/sf_manufacturing/views/mrp_workcenter_views.xml
@@ -24,6 +24,20 @@
+
+ custom.model.form.view.inherit
+ mrp.workcenter
+
+
+
+
+
+
+
+
+
+
+
mrp.workcenter.view.kanban.inherit.mrp.workorder
mrp.workcenter
diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml
index 2a6c37b4..68bb9154 100644
--- a/sf_manufacturing/views/mrp_workorder_view.xml
+++ b/sf_manufacturing/views/mrp_workorder_view.xml
@@ -160,9 +160,19 @@
+<<<<<<< HEAD
+=======
+
+
+
+
+
+
+>>>>>>> 6a2ff72dce60612aeb6c6f2e1851081840f46322
diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py
index f47f8c8d..f3969dfe 100644
--- a/sf_sale/models/sale_order.py
+++ b/sf_sale/models/sale_order.py
@@ -151,6 +151,7 @@ class ResaleOrderLine(models.Model):
# # without modifying the related product_id when updated.
# domain=[('sale_ok', '=', True), ('categ_type', '=', '成品')])
check_status = fields.Selection(related='order_id.check_status')
+ remark = fields.Char('备注')
@api.depends('product_template_id')
def _compute_model_glb_file(self):
@@ -256,33 +257,33 @@ class ResPartnerToSale(models.Model):
# if obj:
# raise UserError('该邮箱已存在,请重新输入')
- @api.model
- def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
- if self._context.get('is_customer'):
- if self.env.user.has_group('sf_base.group_sale_director'):
- domain = [('customer_rank', '>', 0)]
- elif self.env.user.has_group('sf_base.group_sale_salemanager'):
- customer = self.env['res.partner'].search(
- [('customer_rank', '>', 0), ('user_id', '=', self.env.user.id)])
- if customer:
- ids = [t.id for t in customer]
- domain = [('id', 'in', ids)]
- else:
- domain = [('id', '=', False)]
- return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
- elif self._context.get('is_supplier') or self.env.user.has_group('sf_base.group_purchase_director'):
- if self.env.user.has_group('sf_base.group_purchase_director'):
- domain = [('supplier_rank', '>', 0)]
- elif self.env.user.has_group('sf_base.group_purchase'):
- supplier = self.env['res.partner'].search(
- [('supplier_rank', '>', 0), ('purchase_user_id', '=', self.env.user.id)])
- if supplier:
- ids = [t.id for t in supplier]
- domain = [('id', 'in', ids)]
- else:
- domain = [('id', '=', False)]
- return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
- return super()._name_search(name, args, operator, limit, name_get_uid)
+ # @api.model
+ # def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
+ # if self._context.get('is_customer'):
+ # if self.env.user.has_group('sf_base.group_sale_director'):
+ # domain = [('customer_rank', '>', 0)]
+ # elif self.env.user.has_group('sf_base.group_sale_salemanager'):
+ # customer = self.env['res.partner'].search(
+ # [('customer_rank', '>', 0), ('user_id', '=', self.env.user.id)])
+ # if customer:
+ # ids = [t.id for t in customer]
+ # domain = [('id', 'in', ids)]
+ # else:
+ # domain = [('id', '=', False)]
+ # return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
+ # elif self._context.get('is_supplier') or self.env.user.has_group('sf_base.group_purchase_director'):
+ # if self.env.user.has_group('sf_base.group_purchase_director'):
+ # domain = [('supplier_rank', '>', 0)]
+ # elif self.env.user.has_group('sf_base.group_purchase'):
+ # supplier = self.env['res.partner'].search(
+ # [('supplier_rank', '>', 0), ('purchase_user_id', '=', self.env.user.id)])
+ # if supplier:
+ # ids = [t.id for t in supplier]
+ # domain = [('id', 'in', ids)]
+ # else:
+ # domain = [('id', '=', False)]
+ # return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
+ # return super()._name_search(name, args, operator, limit, name_get_uid)
@api.onchange('user_id')
def _get_salesman(self):
diff --git a/sf_sale/views/sale_order_view.xml b/sf_sale/views/sale_order_view.xml
index 647cf8ef..7bf352eb 100644
--- a/sf_sale/views/sale_order_view.xml
+++ b/sf_sale/views/sale_order_view.xml
@@ -69,6 +69,9 @@
+
+
+
{'no_create': True}
{'is_sale_order_line': True }
diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py
index 182141cf..b77e6469 100644
--- a/sf_tool_management/models/base.py
+++ b/sf_tool_management/models/base.py
@@ -669,6 +669,20 @@ class FunctionalToolAssembly(models.Model):
:return:
"""
+ picking_num = fields.Integer('调拨单数量', compute='compute_picking_num', store=True)
+
+ @api.depends('assemble_status')
+ def compute_picking_num(self):
+ for item in self:
+ picking_ids = self.env['stock.picking'].sudo().search([('origin', '=', item.assembly_order_code)])
+ item.picking_num = len(picking_ids)
+
+ def open_tool_stock_picking(self):
+ action = self.env.ref('stock.action_picking_tree_all')
+ result = action.read()[0]
+ result['domain'] = [('origin', '=', self.assembly_order_code)]
+ return result
+
@api.model_create_multi
def create(self, vals):
obj = super(FunctionalToolAssembly, self).create(vals)
@@ -758,7 +772,7 @@ class FunctionalToolDismantle(models.Model):
num = "%03d" % m
return 'GNDJ-CJD-%s-%s' % (datetime, num)
- functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True,
+ functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True, tracking=True,
domain=[('functional_tool_status', '!=', '已拆除'),
('current_location', '=', '刀具房')])
tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
@@ -776,8 +790,18 @@ class FunctionalToolDismantle(models.Model):
dismantle_person = fields.Char('拆解人', readonly=True)
image = fields.Binary('图片', readonly=True)
- scrap_id = fields.Char('报废单号', readonly=True)
+ scrap_ids = fields.One2many('stock.scrap', 'functional_tool_dismantle_id', string='报废单号', readonly=True)
grinding_id = fields.Char('磨削单号', readonly=True)
+ picking_id = fields.Many2one('stock.picking', string='刀具物料调拨单')
+ picking_num = fields.Integer('调拨单数量', default=0, compute='compute_picking_num', store=True)
+
+ @api.depends('picking_id')
+ def compute_picking_num(self):
+ for item in self:
+ if item.picking_id:
+ item.picking_num = 1
+ else:
+ item.picking_num = 0
state = fields.Selection([('待拆解', '待拆解'), ('已拆解', '已拆解')], default='待拆解', tracking=True)
active = fields.Boolean('有效', default=True)
@@ -791,7 +815,14 @@ class FunctionalToolDismantle(models.Model):
handle_rfid = fields.Char(string='刀柄Rfid', compute='_compute_functional_tool_num', store=True)
handle_lot_id = fields.Many2one('stock.lot', string='刀柄序列号', compute='_compute_functional_tool_num',
store=True)
- scrap_boolean = fields.Boolean(string='刀柄是否报废', default=False, tracking=True)
+ scrap_boolean = fields.Boolean(string='刀柄是否报废', default=False, tracking=True, compute='compute_scrap_boolean',
+ store=True)
+
+ @api.depends('dismantle_cause')
+ def compute_scrap_boolean(self):
+ for item in self:
+ if item.dismantle_cause not in ['寿命到期报废', '崩刀报废']:
+ item.scrap_boolean = False
# 整体式
integral_product_id = fields.Many2one('product.product', string='整体式刀具',
@@ -933,75 +964,50 @@ class FunctionalToolDismantle(models.Model):
self.rfid, self.functional_tool_id.current_location))
# 目标重复校验
self.location_duplicate_check()
- location = self.env['stock.location'].search([('name', '=', '刀具组装位置')])
- location_dest = self.env['stock.location'].search([('name', '=', '刀具房')])
+ datas = {'scrap': [], 'picking': []}
# =================刀柄是否[报废]拆解=======
- location_dest_scrap_ids = self.env['stock.location'].search([('name', 'in', ('Scrap', '报废'))])
if self.handle_rfid:
lot = self.env['stock.lot'].sudo().search([('rfid', '=', self.handle_rfid)])
if not lot:
- raise ValidationError('Rfid为【%s】的功能刀具序列号不存在!' % self.handle_rfid)
- functional_tool_assembly = self.functional_tool_id.functional_tool_name_id
+ raise ValidationError('Rfid为【%s】的刀柄序列号不存在!' % self.handle_rfid)
if self.scrap_boolean:
# 刀柄报废 入库到Scrap
- lot.create_stock_quant(location, location_dest_scrap_ids[-1], False, code, False, False)
+ datas['scrap'].append({'lot_id': lot})
lot.tool_material_status = '报废'
else:
# 刀柄不报废 入库到刀具房
- lot.create_stock_quant(location, location_dest, False, code, False, False)
+ datas['picking'].append({'lot_id': lot, 'destination': self.env['sf.shelf.location']})
lot.tool_material_status = '可用'
-
# ==============功能刀具[报废]拆解================
if self.dismantle_cause in ['寿命到期报废', '崩刀报废']:
# 除刀柄外物料报废 入库到Scrap
if self.integral_product_id:
- self.integral_product_id.dismantle_stock_moves(False, self.integral_lot_id, location,
- location_dest_scrap_ids[-1], code)
+ datas['scrap'].append({'lot_id': self.integral_lot_id})
elif self.blade_product_id:
- self.blade_product_id.dismantle_stock_moves(False, self.blade_lot_id, location,
- location_dest_scrap_ids[-1], code)
+ datas['scrap'].append({'lot_id': self.blade_lot_id})
if self.bar_product_id:
- self.bar_product_id.dismantle_stock_moves(False, self.bar_lot_id, location,
- location_dest_scrap_ids[-1], code)
+ datas['scrap'].append({'lot_id': self.bar_lot_id})
elif self.pad_product_id:
- self.pad_product_id.dismantle_stock_moves(False, self.pad_lot_id, location,
- location_dest_scrap_ids[-1], code)
+ datas['scrap'].append({'lot_id': self.pad_lot_id})
if self.chuck_product_id:
- self.chuck_product_id.dismantle_stock_moves(False, self.chuck_lot_id, location,
- location_dest_scrap_ids[-1], code)
- # ===========功能刀具[磨削]拆解==============
- # elif self.dismantle_cause in ['刀具需磨削']:
- # location_dest = self.env['stock.location'].search([('name', '=', '磨削房')])
- # # 除刀柄外物料拆解 入库到具体库位
- # if self.integral_product_id:
- # self.integral_product_id.dismantle_stock_moves(False, location, location_dest)
- # elif self.blade_product_id:
- # self.blade_product_id.dismantle_stock_moves(False, location, location_dest)
- # if self.bar_product_id:
- # self.bar_product_id.dismantle_stock_moves(False, location, location_dest)
- # elif self.pad_product_id:
- # self.pad_product_id.dismantle_stock_moves(False, location, location_dest)
- # if self.chuck_product_id:
- # self.chuck_product_id.dismantle_stock_moves(False, location, location_dest)
+ datas['scrap'].append({'lot_id': self.chuck_lot_id})
# ==============功能刀具[更换,磨削]拆解==============
elif self.dismantle_cause in ['更换为其他刀具', '刀具需磨削']:
# 除刀柄外物料拆解 入库到具体货位
if self.integral_freight_id:
- self.integral_product_id.dismantle_stock_moves(self.integral_freight_id, self.integral_lot_id, location,
- location_dest, code)
+ datas['picking'].append({'lot_id': self.integral_lot_id, 'destination': self.integral_freight_id})
elif self.blade_freight_id:
- self.blade_product_id.dismantle_stock_moves(self.blade_freight_id, self.blade_lot_id, location,
- location_dest, code)
+ datas['picking'].append({'lot_id': self.blade_lot_id, 'destination': self.blade_freight_id})
if self.bar_freight_id:
- self.bar_product_id.dismantle_stock_moves(self.bar_freight_id, self.bar_lot_id, location,
- location_dest, code)
+ datas['picking'].append({'lot_id': self.bar_lot_id, 'destination': self.bar_freight_id})
elif self.pad_freight_id:
- self.pad_product_id.dismantle_stock_moves(self.pad_freight_id, self.pad_lot_id, location,
- location_dest, code)
+ datas['picking'].append({'lot_id': self.pad_lot_id, 'destination': self.pad_freight_id})
if self.chuck_freight_id:
- self.chuck_product_id.dismantle_stock_moves(self.chuck_freight_id, self.chuck_lot_id, location,
- location_dest, code)
- # ===============删除功能刀具的Rfid字段的值, 赋值给Rfid(已拆解)字段=====
+ datas['picking'].append({'lot_id': self.chuck_lot_id, 'destination': self.chuck_freight_id})
+ self.create_tool_picking_scrap(datas)
+ # ===============创建功能刀具拆解移动记录=====
+ self.env['stock.move'].create_functional_tool_stock_move(self)
+ # 修改功能刀具数据
self.functional_tool_id.write({
'rfid_dismantle': self.functional_tool_id.rfid,
'rfid': '',
@@ -1009,37 +1015,173 @@ class FunctionalToolDismantle(models.Model):
})
# 修改拆解单的值
self.write({
- 'rfid_dismantle': self.rfid,
'dismantle_data': fields.Datetime.now(),
'dismantle_person': self.env.user.name,
- 'rfid': '',
+ 'rfid': '%s(已拆解)' % self.rfid,
'state': '已拆解'
})
logging.info('【%s】刀具拆解成功!' % self.name)
+ def create_tool_picking_scrap(self, datas):
+ scrap_data = datas['scrap']
+ picking_data = datas['picking']
+ if scrap_data:
+ for data in scrap_data:
+ if data:
+ self.env['stock.scrap'].create_tool_dismantle_stock_scrap(data['lot_id'], self)
+ if picking_data:
+ picking_id = self.env['stock.picking'].create_tool_dismantle_picking(self)
+ self.picking_id = picking_id.id
+ self.env['stock.move'].create_tool_stock_move({'data': picking_data, 'picking_id': picking_id})
+ # 将刀具物料出库库单的状态更改为就绪
+ picking_id.action_confirm()
+ # 修改刀具物料出库移动历史记录
+ self.env['stock.move'].write_tool_stock_move_line({'data': picking_data, 'picking_id': picking_id})
+ # 设置数量,并验证完成
+ picking_id.action_set_quantities_to_reservation()
+ picking_id.button_validate()
-class ProductProduct(models.Model):
- _inherit = 'product.product'
+ def action_open_reference1(self):
+ self.ensure_one()
+ return {
+ 'res_model': self._name,
+ 'type': 'ir.actions.act_window',
+ 'views': [[False, "form"]],
+ 'res_id': self.id,
+ }
- def dismantle_stock_moves(self, shelf_location_id, lot_id, location_id, location_dest_id, code):
- # 创建功能刀具拆解单产品库存移动记录
- stock_move_id = self.env['stock.move'].sudo().create({
- 'name': code,
- 'product_id': self.id,
+ def open_function_tool_stock_move_line(self):
+ action = self.env.ref('sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_act')
+ result = action.read()[0]
+ result['domain'] = [('functional_tool_dismantle_id', '=', self.id), ('qty_done', '>', 0)]
+ return result
+
+ def open_tool_stock_picking(self):
+ action = self.env.ref('stock.action_picking_tree_all')
+ result = action.read()[0]
+ result['domain'] = [('origin', '=', self.code)]
+ return result
+
+
+class StockPicking(models.Model):
+ _inherit = 'stock.picking'
+
+ def create_tool_dismantle_picking(self, obj):
+ """
+ 创建刀具物料入库单
+ """
+ # 获取名称为内部调拨的作业类型
+ picking_type_id = self.env['stock.picking.type'].sudo().search([('name', '=', '内部调拨')])
+ location_id = self.env['stock.location'].search([('name', '=', '刀具组装位置')])
+ location_dest_id = self.env['stock.location'].search([('name', '=', '刀具房')])
+ if not location_id:
+ raise ValidationError('缺少名称为【刀具组装位置】的仓库管理地点')
+ if not location_dest_id:
+ raise ValidationError('缺少名称为【刀具房】的仓库管理地点')
+ # 创建刀具物料出库单
+ picking_id = self.env['stock.picking'].create({
+ 'name': self._get_name_stock1(picking_type_id),
+ 'picking_type_id': picking_type_id.id,
'location_id': location_id.id,
'location_dest_id': location_dest_id.id,
+ 'origin': obj.code
+ })
+
+ return picking_id
+
+
+class StockMove(models.Model):
+ _inherit = 'stock.move'
+
+ def create_tool_stock_move(self, datas):
+ picking_id = datas['picking_id']
+ data = datas['data']
+ stock_move_ids = []
+ for res in data:
+ if res:
+ # 创建库存移动记录
+ stock_move_id = self.env['stock.move'].sudo().create({
+ 'name': picking_id.name,
+ 'picking_id': picking_id.id,
+ 'product_id': res['lot_id'].product_id.id,
+ 'location_id': picking_id.location_id.id,
+ 'location_dest_id': picking_id.location_dest_id.id,
+ 'product_uom_qty': 1.00,
+ 'reserved_availability': 1.00
+ })
+ stock_move_ids.append(stock_move_id)
+ return stock_move_ids
+
+ def write_tool_stock_move_line(self, datas):
+ picking_id = datas['picking_id']
+ data = datas['data']
+ move_line_ids = picking_id.move_line_ids
+ for move_line_id in move_line_ids:
+ for res in data:
+ if move_line_id.lot_id.product_id == res['lot_id'].product_id:
+ move_line_id.write({
+ 'destination_location_id': res.get('destination').id,
+ 'lot_id': res.get('lot_id').id
+ })
+ return True
+
+ def create_functional_tool_stock_move(self, dismantle_id):
+ """
+ 对功能刀具拆解过程的功能刀具进行库存移动,以及创建移动历史
+ """
+ location_dismantle_id = self.env['stock.location'].search([('name', '=', '拆解')])
+ if not location_dismantle_id:
+ raise ValidationError('缺少名称为【拆解】的仓库管理地点')
+ tool_id = dismantle_id.functional_tool_id
+ # 创建库存移动记录
+ stock_move_id = self.env['stock.move'].sudo().create({
+ 'name': dismantle_id.code,
+ 'product_id': tool_id.barcode_id.product_id.id,
+ 'location_id': tool_id.current_location_id.id,
+ 'location_dest_id': location_dismantle_id.id,
'product_uom_qty': 1.00,
'state': 'done'
})
+
# 创建移动历史记录
stock_move_line_id = self.env['stock.move.line'].sudo().create({
- 'product_id': self.id,
- 'lot_id': lot_id.id,
+ 'product_id': tool_id.barcode_id.product_id.id,
+ 'functional_tool_dismantle_id': dismantle_id.id,
+ 'lot_id': tool_id.barcode_id.id,
'move_id': stock_move_id.id,
- 'destination_location_id': shelf_location_id.id if shelf_location_id else False,
- 'install_tool_time': fields.Datetime.now(),
'qty_done': 1.0,
'state': 'done',
+ 'functional_tool_type_id': tool_id.sf_cutting_tool_type_id.id,
+ 'diameter': tool_id.functional_tool_diameter,
+ 'knife_tip_r_angle': tool_id.knife_tip_r_angle,
+ 'code': tool_id.code,
+ 'rfid': tool_id.rfid,
+ 'functional_tool_name': tool_id.name,
+ 'tool_groups_id': tool_id.tool_groups_id.id
})
-
return stock_move_id, stock_move_line_id
+
+
+class CustomStockScrap(models.Model):
+ _inherit = 'stock.scrap'
+
+ functional_tool_dismantle_id = fields.Many2one('sf.functional.tool.dismantle', string="功能刀具拆解单")
+
+ def create_tool_dismantle_stock_scrap(self, lot, dismantle_id):
+ location_id = self.env['stock.location'].search([('name', '=', '刀具组装位置')])
+ scrap_location_id = self.env['stock.location'].search([('name', 'in', ('Scrap', '报废'))])
+ if not location_id:
+ raise ValidationError('缺少名称为【刀具组装位置】的仓库管理地点')
+ if not scrap_location_id:
+ raise ValidationError('缺少名称为【Scrap】或【Scrap】的仓库管理地点')
+ stock_scrap_id = self.create({
+ 'product_id': lot.product_id.id,
+ 'lot_id': lot.id,
+ 'location_id': location_id.id,
+ 'scrap_location_id': scrap_location_id.id,
+ 'functional_tool_dismantle_id': dismantle_id.id,
+ 'origin': dismantle_id.code
+ })
+ # 完成报废单
+ stock_scrap_id.action_validate()
+ return stock_scrap_id
diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py
index 18f0a466..4e791fe5 100644
--- a/sf_tool_management/models/functional_tool.py
+++ b/sf_tool_management/models/functional_tool.py
@@ -252,9 +252,7 @@ class FunctionalCuttingToolEntity(models.Model):
def open_safety_stock(self):
action = self.env.ref('sf_tool_management.sf_real_time_distribution_of_functional_tools_view_act')
result = action.read()[0]
- result['domain'] = [('name', '=', self.name), ('diameter', '=', self.functional_tool_diameter),
- ('knife_tip_r_angle', '=', self.knife_tip_r_angle),
- ('coarse_middle_thin', '=', self.coarse_middle_thin)]
+ result['domain'] = [('id', '=', self.safe_inventory_id.id)]
return result
def tool_inventory_displacement_out(self):
@@ -372,6 +370,7 @@ class StockMoveLine(models.Model):
_order = 'date desc'
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具组装单')
+ functional_tool_dismantle_id = fields.Many2one('sf.functional.tool.dismantle', string='功能刀具拆解单')
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
group_expand='_read_group_functional_tool_type_id')
functional_tool_name = fields.Char('刀具名称')
@@ -392,6 +391,9 @@ class StockMoveLine(models.Model):
if self.functional_tool_name_id:
action = self.functional_tool_name_id.action_open_reference1()
return action
+ if self.functional_tool_dismantle_id:
+ action = self.functional_tool_dismantle_id.action_open_reference1()
+ return action
elif self.move_id:
action = self.move_id.action_open_reference()
if action['res_model'] != 'stock.move':
@@ -409,13 +411,14 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
_inherit = ['mail.thread']
_description = '功能刀具安全库存'
- name = fields.Char('名称', readonly=True, compute='_compute_name', store=True)
+ name = fields.Char('名称', compute='_compute_num', store=True)
functional_name_id = fields.Many2one('sf.tool.inventory', string='功能刀具名称', required=True)
- tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', readonly=False, required=True)
- sf_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=False,
- group_expand='_read_mrs_cutting_tool_type_ids', store=True)
- diameter = fields.Float(string='刀具直径(mm)', readonly=False)
- knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=False)
+ tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_num', store=True)
+ sf_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
+ compute='_compute_num', store=True,
+ group_expand='_read_mrs_cutting_tool_type_ids')
+ diameter = fields.Float(string='刀具直径(mm)', compute='_compute_num', store=True)
+ knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', compute='_compute_num', store=True)
tool_stock_num = fields.Integer(string='刀具房数量', compute='_compute_stock_num', store=True)
side_shelf_num = fields.Integer(string='线边刀库数量', compute='_compute_stock_num', store=True)
on_tool_stock_num = fields.Integer(string='机内刀库数量', compute='_compute_stock_num', store=True)
@@ -460,22 +463,18 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
active = fields.Boolean(string='已归档', default=True)
- @api.onchange('functional_name_id')
- def _onchange_num(self):
+ @api.depends('functional_name_id', 'functional_name_id.diameter', 'functional_name_id.angle',
+ 'functional_name_id.functional_cutting_tool_model_id')
+ def _compute_num(self):
for item in self:
if item.functional_name_id:
item.tool_groups_id = item.functional_name_id.tool_groups_id.id
item.sf_cutting_tool_type_id = item.functional_name_id.functional_cutting_tool_model_id.id
item.diameter = item.functional_name_id.diameter
item.knife_tip_r_angle = item.functional_name_id.angle
-
- @api.depends('functional_name_id')
- def _compute_name(self):
- for obj in self:
- if obj.tool_groups_id:
- obj.name = obj.functional_name_id.name
+ item.name = item.functional_name_id.name
else:
- obj.sudo().name = ''
+ item.sudo().name = ''
@api.constrains('min_stock_num', 'max_stock_num')
def _check_stock_num(self):
@@ -583,4 +582,10 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
for vals in vals_list:
vals['status_create'] = False
records = super(RealTimeDistributionOfFunctionalTools, self).create(vals_list)
+ for item in records:
+ if item:
+ record = self.search([('functional_name_id', '=', item.functional_name_id.id)])
+ if len(record) > 1:
+ raise ValidationError(
+ '功能刀具名称为【%s】的安全库存已经存在,请勿重复创建!!!' % item.functional_name_id.name)
return records
diff --git a/sf_tool_management/models/functional_tool_enroll.py b/sf_tool_management/models/functional_tool_enroll.py
index 9c5b1417..ba3553e1 100644
--- a/sf_tool_management/models/functional_tool_enroll.py
+++ b/sf_tool_management/models/functional_tool_enroll.py
@@ -37,14 +37,10 @@ class ToolDatasync(models.Model):
def _cron_tool_datasync_all(self):
try:
- self.env['stock.lot'].sudo().sync_enroll_tool_material_stock_all()
-
- self.env['stock.lot'].sudo().sync_enroll_fixture_material_stock_all()
-
self.env['sf.tool.material.search'].sudo().sync_enroll_tool_material_all()
-
+ self.env['stock.lot'].sudo().sync_enroll_tool_material_stock_all()
self.env['sf.fixture.material.search'].sudo().sync_enroll_fixture_material_all()
-
+ self.env['stock.lot'].sudo().sync_enroll_fixture_material_stock_all()
self.env['sf.functional.cutting.tool.entity'].sudo().esync_enroll_functional_tool_entity_all()
logging.info("已全部同步完成!!!")
# self.env['sf.functional.tool.warning'].sudo().sync_enroll_functional_tool_warning_all()
@@ -106,7 +102,7 @@ class StockLot(models.Model):
logging.info("没有刀具物料序列号信息")
except Exception as e:
logging.info("刀具物料序列号同步失败:%s" % e)
-
+
class ToolMaterial(models.Model):
_inherit = 'sf.tool.material.search'
@@ -198,7 +194,7 @@ class FunctionalCuttingToolEntity(models.Model):
for item in objs_all:
val = {
'id': item.id,
- 'code': item.code,
+ 'code': False if not item.code else item.code.split('-', 1)[1],
'name': item.name,
'rfid': item.rfid,
'tool_groups_name': item.tool_groups_id.name,
diff --git a/sf_tool_management/views/functional_tool_views.xml b/sf_tool_management/views/functional_tool_views.xml
index 6fde82a0..103583c2 100644
--- a/sf_tool_management/views/functional_tool_views.xml
+++ b/sf_tool_management/views/functional_tool_views.xml
@@ -29,7 +29,6 @@
-
@@ -61,13 +60,9 @@
-
+
@@ -482,18 +477,19 @@
-
-
-
+
+
+
+
diff --git a/sf_tool_management/views/tool_base_views.xml b/sf_tool_management/views/tool_base_views.xml
index 31fe53c9..c180c917 100644
--- a/sf_tool_management/views/tool_base_views.xml
+++ b/sf_tool_management/views/tool_base_views.xml
@@ -407,6 +407,7 @@
+
@@ -476,6 +477,17 @@
+
@@ -711,10 +723,14 @@
-
-
-
-
+
+
+
+
@@ -759,10 +775,25 @@