Compare commits

..

3 Commits

342 changed files with 86353 additions and 33042 deletions

View File

@@ -1,4 +0,0 @@
# -*- coding: utf-8 -*-
from . import controllers
from . import models

View File

@@ -1,35 +0,0 @@
# -*- coding: utf-8 -*-
{
'name': "jikimo_account_process",
'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': ['base', 'account'],
# always loaded
'data': [
# 'security/ir.model.access.csv',
# 'views/views.xml',
# 'views/templates.xml',
],
# only loaded in demonstration mode
'demo': [
# 'demo/demo.xml',
],
}

View File

@@ -1,3 +0,0 @@
# -*- coding: utf-8 -*-
from . import controllers

View File

@@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# from odoo import http
# class JikimoAccountProcess(http.Controller):
# @http.route('/jikimo_account_process/jikimo_account_process', auth='public')
# def index(self, **kw):
# return "Hello, world"
# @http.route('/jikimo_account_process/jikimo_account_process/objects', auth='public')
# def list(self, **kw):
# return http.request.render('jikimo_account_process.listing', {
# 'root': '/jikimo_account_process/jikimo_account_process',
# 'objects': http.request.env['jikimo_account_process.jikimo_account_process'].search([]),
# })
# @http.route('/jikimo_account_process/jikimo_account_process/objects/<model("jikimo_account_process.jikimo_account_process"):obj>', auth='public')
# def object(self, obj, **kw):
# return http.request.render('jikimo_account_process.object', {
# 'object': obj
# })

View File

@@ -1,4 +0,0 @@
# -*- coding: utf-8 -*-
from . import models
from . import account_move

View File

@@ -1,15 +0,0 @@
from odoo import models, fields, api
from odoo.exceptions import ValidationError
class CustomAccountMoveLine(models.Model):
_inherit = 'account.move'
_description = "account move line"
@api.model_create_multi
def create(self, vals):
for val in vals:
val['name'] = self.env['ir.sequence'].next_by_code('account.move') or '/'
# 因为供应商与客户支付创建流程是先创建move line在修改来填充account_payment与move line的关联
return super(CustomAccountMoveLine, self).create(vals)

View File

@@ -1,18 +0,0 @@
# -*- coding: utf-8 -*-
# from odoo import models, fields, api
# class jikimo_account_process(models.Model):
# _name = 'jikimo_account_process.jikimo_account_process'
# _description = 'jikimo_account_process.jikimo_account_process'
# name = fields.Char()
# value = fields.Integer()
# value2 = fields.Float(compute="_value_pc", store=True)
# description = fields.Text()
#
# @api.depends('value')
# def _value_pc(self):
# for record in self:
# record.value2 = float(record.value) / 100

View File

@@ -5,7 +5,7 @@ import {patch} from '@web/core/utils/patch';
import {_t} from "@web/core/l10n/translation"; import {_t} from "@web/core/l10n/translation";
import {FormStatusIndicator} from "@web/views/form/form_status_indicator/form_status_indicator"; import {FormStatusIndicator} from "@web/views/form/form_status_indicator/form_status_indicator";
import {ListRenderer} from "@web/views/list/list_renderer"; 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"; import {Field} from "@web/views/fields/field";
@@ -53,23 +53,6 @@ const tableRequiredList = [
] ]
patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', { patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', {
setup() {
owl.onMounted(() => {
try {
const dom = this.__owl__.bdom.el
const buttonsDom = $(dom).find('.o_form_status_indicator_buttons ')
if (buttonsDom) {
const dom1 = buttonsDom.children('.o_form_button_save')
const dom2 = buttonsDom.children('.o_form_button_cancel')
dom1.append('保存')
dom2.append('取消')
}
} catch (e) {
console.log(e)
}
});
},
// 你可以重写或者添加一些方法和属性 // 你可以重写或者添加一些方法和属性
async _onDiscardChanges() { async _onDiscardChanges() {
// var self = this; // var self = this;
@@ -170,36 +153,47 @@ patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', {
// 根据进度条设置水印 // 根据进度条设置水印
// const statusbar_params = { const statusbar_params = {
// '已完工': 'bg-primary', '已完工': 'bg-primary',
// '完成': 'bg-primary', '完成': 'bg-primary',
// '采购订单': 'bg-primary', '采购订单': 'bg-primary',
// '作废': 'bg-danger', '作废': 'bg-danger',
// '封存(报废)': 'bg-danger', '封存(报废)': 'bg-danger',
// } }
// patch(StatusBarField.prototype, 'jikimo_frontend.StatusBarField', { patch(StatusBarField.prototype, 'jikimo_frontend.StatusBarField', {
// setup() { setup() {
// owl.onMounted(this.ribbons); owl.onMounted(this.ribbons);
// return this._super(...arguments); return this._super(...arguments);
// }, },
// ribbons() { ribbons() {
// try { try {
// const dom = $('.o_form_sheet.position-relative') const dom = $('.o_form_sheet.position-relative')
// const status = statusbar_params[this.currentName] const status = statusbar_params[this.currentName]
// if(status && dom.length) { if(status && dom.length) {
// dom.prepend(`<div class="o_widget o_widget_web_ribbon"> dom.prepend(`<div class="o_widget o_widget_web_ribbon">
// <div class="ribbon ribbon-top-right"> <div class="ribbon ribbon-top-right">
// <span class="bg-opacity-75 ${status}" title="">${this.currentName}</span> <span class="bg-opacity-75 ${status}" title="">${this.currentName}</span>
// </div> </div>
// </div>`) </div>`)
// } }
// } catch (e) { } catch (e) {
// console.log(e) console.log(e)
// } }
// } }
// }) })
$(function () { $(function () {
document.addEventListener('click', function () {
const dom = $('.o_form_status_indicator_buttons ')
if (dom) {
const dom1 = dom.children().eq(0)
const dom2 = dom.children().eq(1)
if (!dom1.text()) {
dom1.append('保存')
dom2.append('取消')
}
}
})
function customRequired() { function customRequired() {
let timer = null let timer = null

View File

@@ -526,9 +526,4 @@ div:has(.o_required_modifier) > label::before {
// 设置表单页面label文本不换行 // 设置表单页面label文本不换行
.o_form_view .o_group .o_wrap_label .o_form_label { .o_form_view .o_group .o_wrap_label .o_form_label {
white-space: nowrap; white-space: nowrap;
} }
// 修复表格内容覆盖表头bug
.o_list_renderer .o_list_table tbody th {
position: unset;
}

View File

@@ -301,27 +301,53 @@ def unlink(self):
# This is used to restrict the access right to unlink a record # This is used to restrict the access right to unlink a record
current_model_id = self.env['ir.model'].sudo().search( current_model_id = self.env['ir.model'].sudo().search(
[('model', '=', self._name)]).id [('model', '=', self._name)]).id
access_right_rec = self.env['access.right'].sudo().search_read( # access_right_rec = self.env['access.right'].sudo().search_read(
[('model_id', '=', current_model_id)], ['model_id', 'is_delete', # [('model_id', '=', current_model_id)], ['model_id', 'is_delete',
'groups_id']) # 'groups_id'])
if access_right_rec and not self.env.is_admin(): # if access_right_rec and not self.env.is_admin():
for rec in access_right_rec: # for rec in access_right_rec:
group_name = self.env['ir.model.data'].sudo().search([ # group_name = self.env['ir.model.data'].sudo().search([
('model', '=', 'res.groups'), # ('model', '=', 'res.groups'),
('res_id', '=', rec['groups_id'][0]) # ('res_id', '=', rec['groups_id'][0])
]).name # ]).name
module_name = self.env['ir.model.data'].sudo().search([ # module_name = self.env['ir.model.data'].sudo().search([
('model', '=', 'res.groups'), # ('model', '=', 'res.groups'),
('res_id', '=', rec['groups_id'][0]) # ('res_id', '=', rec['groups_id'][0])
]).module # ]).module
group = module_name + "." + group_name # group = module_name + "." + group_name
if self.env.user.has_group(group): # if self.env.user.has_group(group):
if rec['is_delete']: # if rec['is_delete']:
raise UserError(_('You are restricted from performing this' # raise UserError(_('You are restricted from performing this'
' operation. Please contact the' # ' operation. Please contact the'
' administrator.')) # ' administrator.'))
# 检查 'access.right' 模型是否存在于环境中
if 'access.right' in self.env:
# current_model_id = self.env['ir.model'].sudo().search([('model', '=', self._name)]).id
access_right_rec = self.env['access.right'].sudo().search_read(
[('model_id', '=', current_model_id)], ['model_id', 'is_delete', 'groups_id']
)
if access_right_rec and not self.env.is_admin():
for rec in access_right_rec:
group_data = self.env['ir.model.data'].sudo().search_read(
[('model', '=', 'res.groups'), ('res_id', '=', rec['groups_id'][0])],
['name', 'module']
)
if group_data:
group_name = group_data[0]['name']
module_name = group_data[0]['module']
group_xml_id = f"{module_name}.{group_name}"
if self.env.user.has_group(group_xml_id) and rec['is_delete']:
raise UserError(
_('You are restricted from performing this operation. Please contact the administrator.'))
else:
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
pass
return True return True
BaseModel._create = _create BaseModel._create = _create
# BaseModel.unlink = unlink BaseModel.unlink = unlink

View File

@@ -1,5 +0,0 @@
# -*- coding: utf-8 -*-
from . import controllers
from . import models
from . import wizard

View File

@@ -1,39 +0,0 @@
# -*- 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',
],
}

View File

@@ -1,3 +0,0 @@
# -*- coding: utf-8 -*-
from . import controllers

View File

@@ -1,20 +0,0 @@
# -*- 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/<model("jikimo_system_order.jikimo_system_order"):obj>/', auth='public')
# def object(self, obj, **kw):
# return http.request.render('jikimo_system_order.object', {
# 'object': obj
# })

View File

@@ -1,30 +0,0 @@
<odoo>
<data>
<!-- -->
<!-- <record id="object0" model="jikimo_system_order.jikimo_system_order"> -->
<!-- <field name="name">Object 0</field> -->
<!-- <field name="value">0</field> -->
<!-- </record> -->
<!-- -->
<!-- <record id="object1" model="jikimo_system_order.jikimo_system_order"> -->
<!-- <field name="name">Object 1</field> -->
<!-- <field name="value">10</field> -->
<!-- </record> -->
<!-- -->
<!-- <record id="object2" model="jikimo_system_order.jikimo_system_order"> -->
<!-- <field name="name">Object 2</field> -->
<!-- <field name="value">20</field> -->
<!-- </record> -->
<!-- -->
<!-- <record id="object3" model="jikimo_system_order.jikimo_system_order"> -->
<!-- <field name="name">Object 3</field> -->
<!-- <field name="value">30</field> -->
<!-- </record> -->
<!-- -->
<!-- <record id="object4" model="jikimo_system_order.jikimo_system_order"> -->
<!-- <field name="name">Object 4</field> -->
<!-- <field name="value">40</field> -->
<!-- </record> -->
<!-- -->
</data>
</odoo>

View File

@@ -1,7 +0,0 @@
# -*- 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

View File

@@ -1,7 +0,0 @@
# -*- 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非常满意')]

View File

@@ -1,25 +0,0 @@
# -*- 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='是否有效')

View File

@@ -1,32 +0,0 @@
# -*- 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 "")

View File

@@ -1,183 +0,0 @@
# -*- 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 = """您有一张工单<font color=\"warning\">待处理</font>:**工单标题:{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()

View File

@@ -1,38 +0,0 @@
# -*- 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='工单处理人')

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="0"> <!-- noupdate表示当模块升级时是否更新本条数据-->
<!--运维权限组-->
<record id="group_operations_permissions_rwc" model="res.groups">
<field name="name">运维权限</field>
</record>
<record id="system_order_user_rule" model="ir.rule">
<field name="name">用户访问工单信息</field>
<field name="model_id" ref="model_system_work_order"/>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
<field name="domain_force">[('initiator_id', '=', user.id)]</field>
</record>
<record id="system_order_group_operations_rule" model="ir.rule">
<field name="name">运维访问工单信息</field>
<field name="model_id" ref="model_system_work_order"/>
<field name="groups" eval="[(4, ref('jikimo_system_order.group_operations_permissions_rwc'))]"/>
<field name="domain_force">[(1, '=', 1)]</field>
</record>
</data>
</odoo>

View File

@@ -1,16 +0,0 @@
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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 inside_system_order_classify_r jikimo_system_order.order_classify model_order_classify 1 1 1 1
3 inside_system_work_order_rc jikimo_system_order.system_work_order model_system_work_order 1 1 1 1
4 inside_work_order_template_r jikimo_system_order.work_order_template model_work_order_template 1 1 1 1
5 inside_system_order_classify_rwc jikimo_system_order.order_classify model_order_classify group_operations_permissions_rwc 1 1 1 0
6 inside_system_work_order_rwc jikimo_system_order.system_work_order model_system_work_order group_operations_permissions_rwc 1 1 1 0
7 inside_work_order_template_rwc jikimo_system_order.work_order_template model_work_order_template group_operations_permissions_rwc 1 1 1 0
8 order_close_wizard_group_user jikimo_system_order.order_close_wizard model_order_close_wizard base.group_user 1 1 1 1
9 order_other_wizard_group_user jikimo_system_order.order_other_wizard model_order_other_wizard base.group_user 1 1 1 1
10 order_technician_wizard_group_user jikimo_system_order.order_technician_wizard model_order_technician_wizard base.group_user 1 1 1 1
11 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
12 system_order_notice_group_user jikimo_system_order.system_order_notice model_system_order_notice base.group_user 1 1 1 1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
# ---------- 工单通知处理人设置 ------------
<record model="ir.ui.view" id="tree_system_order_notice_view">
<field name="name">tree.system.order.notice</field>
<field name="model">system.order.notice</field>
<field name="arch" type="xml">
<tree string="工单处理人设置" editable="top">
<field name="notice_user_ids" widget="many2many_tags" required="1" options="{'no_create': True, 'no_edit': True}"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="search_system_order_notice_view">
<field name="name">search.system.order.notice</field>
<field name="model">system.order.notice</field>
<field name="arch" type="xml">
<search string="工单处理人设置">
<field name="notice_user_ids" string="模糊搜索"
filter_domain="[('notice_user_ids', 'ilike', self)]"/>
<separator></separator>
<field name="notice_user_ids" string="处理人"/>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="action_system_order_notice_view">
<field name="name">工单处理人</field>
<field name="res_model">system.order.notice</field>
<field name="view_mode">tree</field>
<field name="domain">[]</field>
<field name="context">{}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
[工单处理人] 还没有哦!点左上角的[创建]按钮,沙发归你了!
</p>
<p>
</p>
</field>
</record>
</data>
</odoo>

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="res_config_settings_we_view_form_inherit" model="ir.ui.view">
<field name="name">res.config.settings.we.view.form.inherit.bpm</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[hasclass('app_settings_block')]/div[6]" position="after">
<div>
<h2>企微通知应用ID</h2>
<div class="row mt16 o_settings_container" id="jd_api">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="lost_agent_id"/>
<field name="lost_agent_id"/>
</div>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="True">
<!-- 工单流水号 -->
<record id="seq_work_order" model="ir.sequence">
<field name="name">seq_work_order</field>
<field name="company_id"/>
<field name="code">system.work.order</field>
<field name="prefix">SO%(year)s%(month)s%(day)s</field>
<field name="padding">1</field>
</record>
<!-- 模板编号 -->
<record id="seq_order_template" model="ir.sequence">
<field name="name">seq_order_template</field>
<field name="company_id"/>
<field name="code">work.order.template</field>
<field name="prefix">TL</field>
<field name="padding">1</field>
</record>
</data>
</odoo>

View File

@@ -1,243 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!--工单信息-->
<record model="ir.ui.view" id="work_order_tree">
<field name="name">工单信息</field>
<field name="model">system.work.order</field><!--对应表单名称-->
<field name="arch" type="xml">
<tree>
<field name="state" widget="badge" decoration-primary="state == 'draft'"
decoration-success="state in ('processed', 'completed')"
decoration-danger="state == 'pending'" decoration-warning="state in ('unconfirmed')"/>
<field name="order_number"/>
<field name="title"/>
<field name="initiator_id"/>
<field name="date"/>
</tree>
</field>
</record>
<!--新建系统工单-->
<record model="ir.ui.view" id="ork_order_form">
<field name="name">新建系统工单</field>
<field name="model">system.work.order</field>
<field name="arch" type="xml">
<form>
<header>
<field name="is_display" invisible="1"/>
<button string='提交' class="oe_highlight" states="draft"
type="object" name="do_unconfirmed"
attrs="{'invisible': [('state', '!=', 'draft')]}"/>
<button string='追回编辑' states="unconfirmed"
type="action" name="%(system_work_order_wizard_view_act_window)d"
context="{'explain':'确认要执行此操作吗?','object_name':'system.work.order','function_name':'do_draft','object_id':id}"/>
<button name="do_pending" states="unconfirmed"
string="确认可处理" type="object" class="oe_highlight"
groups="jikimo_system_order.group_operations_permissions_rwc"/>
<button string='处理工单' class="oe_highlight" states="pending"
type="action" name="%(launch_order_technician_wizard)d"
groups="jikimo_system_order.group_operations_permissions_rwc"/>
<button string='评价' class="oe_highlight" attrs="{'invisible': [('is_display', '=', False)]}"
type="action" name="%(launch_order_other_wizard)d" context="{'active_id':id}"/>
<button name="%(launch_order_close_wizard)d" string="关闭该工单"
attrs="{'invisible': ['|',('state', '=', 'draft'),'|',('state','=','completed'),('state','=','closed')]}"
type="action" context="{'active_id':id}"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<group>
<!-- <label for="order_number" class="oe_edit_only"/>-->
<group>
<field name="order_number" required="True" readonly="1"/>
<field name="order_type" required="True" attrs="{'readonly': [('state', '!=', 'draft')]}" options="{'no_create': True}"/>
<field name="date" required="True" readonly="True"/>
<field name="order_template_id" attrs="{'readonly': [('state', '!=', 'draft')]}"
domain="[('work_order_type','=',order_type),('state','=',True)]" options="{'no_create': True}"/>
<field name="confirmation_date" readonly="True"/>
<field name="urgency_degree" required="True" attrs="{'readonly': [('state','!=','draft')]}" widget="priority"/>
</group>
<group>
<field name="initiator_company_id" required="True" readonly="True"/>
<!-- <field name="initiator_department_id" required="True" readonly="True"/>-->
<field name="initiator_id" required="True" readonly="True"/>
<field name="confirm_id" readonly="True"/>
<field name="solve_people_id" readonly="True"/>
<field name="close_user_id" readonly="True"/>
</group>
<group>
<field name="title" attrs="{'readonly': [('state', '!=', 'draft')]}" required="True"/>
</group>
</group>
<notebook>
<page string="工单内容">
<field name="text" attrs="{'readonly': [('state','!=','draft')]}" required="True"/>
</page>
<page string="解决方案">
<group>
<field name="users_problem" readonly="True"/>
<field name="solution" readonly="True"/>
</group>
</page>
<page string="其他">
<group>
<field name="close_cause" readonly="True"/>
<field name="close_time" readonly="True"/>
<field name="grade" readonly="True"/>
</group>
</page>
</notebook>
</sheet>
<!-- <div class="oe_chatter">-->
<!-- <field name="message_follower_ids" widget="mail_followers"/>-->
<!-- <field name="message_ids" widget="mail_thread"/>-->
<!-- </div>-->
</form>
</field>
</record>
<!-- 搜索工单 -->
<record model="ir.ui.view" id="restaurant_search">
<field name="name">搜索工单</field>
<field name="model">system.work.order</field>
<field name="arch" type="xml">
<search>
<field string='发起人' name="initiator_id" widget="char" required="True"/>
<field string='标题' name="title" widget="char"/>
<field string='正文' name="text" widget="html"/>
<field string='实际问题' name="users_problem" widget="text"/>
<field string='解决方案' name="solution" widget="text"/>
<filter name="today" string="今日工单" domain="[('date','=',time.strftime('%%Y-%%m-%%d'))]"/>
<filter name="yesterday" string="昨日工单"
domain="[('date', '=', (context_today() - relativedelta(days=1)).strftime('%Y-%m-%d'))]"/>
<filter name="month" string="本月工单"
domain="[('date','&gt;=', time.strftime('%Y-%m-01')),('date','&lt;', (context_today() + relativedelta(months=1)).strftime('%Y-%m-01'))]"/>
<filter name="last_month" string="上月工单"
domain="[('date','&lt;', time.strftime('%Y-%m-01')),('date','&gt;=', (context_today() - relativedelta(months=1)).strftime('%Y-%m-01'))]"/>
<filter name="unconfirmed" string="待确认" domain="[('state','=','unconfirmed')]"/>
<filter name="pending" string="待处理" domain="[('state','=','pending')]"/>
<filter name="processed" string="已处理"
domain="['|', ('state','=','processed'), ('state','=','closed')]"/>
<group>
<filter string='发起人' name="initiator_id" context='{"group_by":"initiator_id"}'/>
<filter string='工单分类' name="order_type" context='{"group_by":"order_type"}'/>
<filter string='模板' name="order_template_id" context='{"group_by":"order_template_id"}'/>
<filter string='状态' name="state" context='{"group_by":"state"}'/>
<filter string='紧急情况' name="state" context='{"group_by":"urgency_degree"}'/>
</group>
</search>
</field>
</record>
<record model="ir.ui.view" id="graph_tree">
<field name="name">工单图表</field>
<field name="model">system.work.order</field><!--对应表单名称-->
<field name="arch" type="xml">
<pivot>
<field name="date" type="row" interval="day"/>
<field name="order_type" type="col"/>
<field name="state" type="row"/>
</pivot>
</field>
</record>
<!-- 工单 -->
<record model="ir.actions.act_window" id="system_order">
<field name="name">工单</field>
<field name="res_model">system.work.order</field>
<field name="view_mode">tree,form,search,graph,pivot</field>
</record>
<!--工单模板信息-->
<record model="ir.ui.view" id="order_template_tree">
<field name="name">工单模板信息</field>
<field name="model">work.order.template</field><!--对应表单名称-->
<field name="arch" type="xml">
<tree>
<field name="num"/>
<field name="name"/>
<field name="work_order_type"/>
<field name="title_template"/>
<field name="template_explain"/>
<field name="state"/>
</tree>
</field>
</record>
<!--新建系统工单模板-->
<record model="ir.ui.view" id="order_template_form">
<field name="name">新建系统工单模板</field>
<field name="model">work.order.template</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="num" required="True" readonly="True"/>
<field name="name" required="True"/>
<field name="work_order_type" required="True"/>
<field name="template_explain" required="True" style="height: 50px;"/>
<field name="title_template" required="True"/>
<field name="state"/>
<field name="text_template" required="True"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- 工单模板 -->
<record model="ir.actions.act_window" id="work_template">
<field name="name">工单模板</field>
<field name="res_model">work.order.template</field>
<field name="view_mode">tree,form</field>
</record>
<!--工单分类信息-->
<record model="ir.ui.view" id="order_type_tree">
<field name="name">工单分类信息</field>
<field name="model">order.classify</field><!--对应表单名称-->
<field name="arch" type="xml">
<tree>
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="state"/>
</tree>
</field>
</record>
<!--新建系统分类信息-->
<record model="ir.ui.view" id="order_type_form">
<field name="name">新建系统分类信息</field>
<field name="model">order.classify</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="name" required="True"/>
<field name="sequence" invisible="True"/>
<field name="state"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- 工单分类 -->
<record model="ir.actions.act_window" id="classify">
<field name="name">工单分类</field>
<field name="res_model">order.classify</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem name="系统工单" id="work_order_1_list" web_icon="jikimo_system_order,static/description/icon.png"/>
<menuitem name="工单" id="work_order" parent="work_order_1_list" action="system_order"/>
<menuitem name="工单模板" id="work_order_template" parent="work_order_1_list" action="work_template" groups="jikimo_system_order.group_operations_permissions_rwc"/>
<menuitem name="工单分类" id="work_order_type" parent="work_order_1_list" action="classify" groups="jikimo_system_order.group_operations_permissions_rwc"/>
<menuitem name="工单设置" id="system_order_notice_user_config" parent="work_order_1_list" action="action_system_order_notice_view" groups="jikimo_system_order.group_operations_permissions_rwc"/>
</data>
</odoo>

View File

@@ -1,6 +0,0 @@
# -*- coding: utf-8 -*-
from . import order_other_wizard
from . import order_technician_wizard
from . import order_close_wizard
from . import system_work_order_wizard

View File

@@ -1,79 +0,0 @@
# -*- 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}**-<font color=\"#FF0000\">**已关闭**</font>
>提交时间:{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 {}

View File

@@ -1,42 +0,0 @@
# -*- 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 {}

View File

@@ -1,59 +0,0 @@
# -*- 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}**-<font color=\"info\">**已处理**</font>
>提交时间:{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 {}

View File

@@ -1,122 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- 技术员向导form-->
<record model="ir.ui.view" id="wizard_technician_form_view">
<field name="name">技术员向导</field>
<field name="model">order.technician.wizard</field>
<field name="arch" type="xml">
<form string="技术员编辑">
<group>
<field name="order_id" required="1" readonly="1"/>
<field name="solve_people_id" required="1"/>
<field name="users_problem" required="1" style="height: 50px;"/>
<field name="solution" required="1" style="height: 50px;"/>
</group>
<footer>
<button name="sure" string="确定" type="object" class="oe_highlight"/>
or
<button string="取消" class="oe_link" special="cancel"/>
</footer>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="launch_order_technician_wizard">
<field name="name">技术员编辑</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">order.technician.wizard</field>
<field name="view_mode">form</field>
<field name="view_id" ref="wizard_technician_form_view"/>
<field name="context">{'display_default_code':False}</field>
<field name="target">new</field>
</record>
<!-- 其它向导form-->
<record model="ir.ui.view" id="wizard_other_form_view">
<field name="name">其它向导</field>
<field name="model">order.other.wizard</field>
<field name="arch" type="xml">
<form string="其它编辑">
<group>
<field name="order_id" required="1" readonly="1"/>
<field name="close_time" required="1" readonly="1"/>
<field name="grade" required="1"/>
<field name="close_user_id" required="1" readonly="1"/>
</group>
<footer>
<button name="sure" string="确定" type="object" class="oe_highlight"/>
or
<button string="取消" class="oe_link" special="cancel"/>
</footer>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="launch_order_other_wizard">
<field name="name">其它编辑</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">order.other.wizard</field>
<field name="view_mode">form</field>
<field name="view_id" ref="wizard_other_form_view"/>
<field name="context">{'display_default_code':False}</field>
<field name="target">new</field>
</record>
<!--关闭向导form-->
<record model="ir.ui.view" id="wizard_close_form_view">
<field name="name">关闭向导</field>
<field name="model">order.close.wizard</field>
<field name="arch" type="xml">
<form string="关闭工单">
<group>
<field name="order_id" required="1" readonly="1"/>
<field name="close_cause" required="1" style="height: 50px;"/>
<field name="close_time" required="1" readonly="1"/>
<field name="close_user_id" required="1" readonly="1"/>
</group>
<footer>
<button name="sure" string="确定" type="object" class="oe_highlight"/>
or
<button string="取消" class="oe_link" special="cancel"/>
</footer>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="launch_order_close_wizard">
<field name="name">关闭工单</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">order.close.wizard</field>
<field name="view_mode">form</field>
<field name="view_id" ref="wizard_close_form_view"/>
<field name="context">{'display_default_code':False}</field>
<field name="target">new</field>
</record>
<record id="system_work_order_wizard_view" model="ir.ui.view">
<field name="name">system_work_order_wizard_view</field>
<field name="model">system.work.order.wizard</field>
<field name="arch" type="xml">
<form string="二次确认">
<field name="explain" readonly="1"/>
<footer>
<button name="sure" string="确定" type="object" class="oe_highlight"/>
or
<button string="取消" class="oe_link" special="cancel"/>
</footer>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="system_work_order_wizard_view_act_window">
<field name="name">二次确认</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">system.work.order.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</odoo>

View File

@@ -1,42 +0,0 @@
#!/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)

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# 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 odoo import fields, models, api from odoo import fields, models
class MrpProduction(models.Model): class MrpProduction(models.Model):
@@ -12,8 +12,7 @@ class MrpProduction(models.Model):
check_ids = fields.One2many('quality.check', 'production_id', string="Checks") check_ids = fields.One2many('quality.check', 'production_id', string="Checks")
def _split_productions(self, amounts=False, cancel_remaining_qty=False, set_consumed_qty=False): def _split_productions(self, amounts=False, cancel_remaining_qty=False, set_consumed_qty=False):
productions = super()._split_productions(amounts=amounts, cancel_remaining_qty=cancel_remaining_qty, productions = super()._split_productions(amounts=amounts, cancel_remaining_qty=cancel_remaining_qty, set_consumed_qty=set_consumed_qty)
set_consumed_qty=set_consumed_qty)
backorders = productions[1:] backorders = productions[1:]
if not backorders: if not backorders:
return productions return productions
@@ -21,4 +20,3 @@ class MrpProduction(models.Model):
if wo.current_quality_check_id.component_id: if wo.current_quality_check_id.component_id:
wo.current_quality_check_id._update_component_quantity() wo.current_quality_check_id._update_component_quantity()
return productions return productions

View File

@@ -1,44 +1,41 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<!-- Manufacturing Order for Planing view --> <!-- Manufacturing Order for Planing view -->
<record id="mrp_production_tree_view_planning" model="ir.ui.view"> <record id="mrp_production_tree_view_planning" model="ir.ui.view">
<field name="name">mrp.production.tree.inherit.planning</field> <field name="name">mrp.production.tree.inherit.planning</field>
<field name="model">mrp.production</field> <field name="model">mrp.production</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree default_order="date_planned_start asc" decoration-info="state=='confirmed'" <tree default_order="date_planned_start asc" decoration-info="state=='confirmed'" decoration-danger="date_planned_start&lt;current_date and state not in ('done','cancel')" decoration-muted="state in ('done','cancel')" string="Manufacturing Orders" name="Production">
decoration-danger="date_planned_start&lt;current_date and state not in ('done','cancel')" <field name="message_needaction" invisible="1"/>
decoration-muted="state in ('done','cancel')" string="Manufacturing Orders" name="Production"> <field name="name"/>
<field name="message_needaction" invisible="1"/> <field name="date_planned_start"/>
<field name="name"/> <field name="product_id"/>
<field name="date_planned_start"/> <field name="product_qty" sum="Total Qty" string="Quantity"/>
<field name="product_id"/> <field name="product_uom_id" string="Unit of Measure" options="{'no_open':True,'no_create':True}" groups="uom.group_uom"/>
<field name="product_qty" sum="Total Qty" string="Quantity"/> <field name="reservation_state" string="Availability"/>
<field name="product_uom_id" string="Unit of Measure" options="{'no_open':True,'no_create':True}" <field name="origin"/>
groups="uom.group_uom"/> <field name="state"/>
<field name="reservation_state" string="Availability"/> </tree>
<field name="origin"/> </field>
<field name="state"/> </record>
</tree>
</field>
</record>
<!-- <record id="mrp_production_form_inherit_planning" model="ir.ui.view">--> <!-- <record id="mrp_production_form_inherit_planning" model="ir.ui.view">-->
<!-- <field name="name">mrp.production.form_inherit_planning</field>--> <!-- <field name="name">mrp.production.form_inherit_planning</field>-->
<!-- <field name="model">mrp.production</field>--> <!-- <field name="model">mrp.production</field>-->
<!-- <field name="inherit_id" ref="mrp.mrp_production_form_view"/>--> <!-- <field name="inherit_id" ref="mrp.mrp_production_form_view"/>-->
<!-- <field name="arch" type="xml">--> <!-- <field name="arch" type="xml">-->
<!-- <xpath expr="div[hasclass('oe_chatter')]" position="replace">--> <!-- <xpath expr="div[hasclass('oe_chatter')]" position="replace">-->
<!-- &lt;!&ndash; 这里放置替换后的内容 &ndash;&gt;--> <!-- &lt;!&ndash; 这里放置替换后的内容 &ndash;&gt;-->
<!-- </xpath>--> <!-- </xpath>-->
<!-- <xpath expr="//notebook" position="after">--> <!-- <xpath expr="//notebook" position="after">-->
<!-- <div class="oe_chatter">--> <!-- <div class="oe_chatter">-->
<!-- <field name="message_follower_ids"/>--> <!-- <field name="message_follower_ids"/>-->
<!-- <field name="activity_ids"/>--> <!-- <field name="activity_ids"/>-->
<!-- <field name="message_ids"/>--> <!-- <field name="message_ids"/>-->
<!-- </div>--> <!-- </div>-->
<!-- </xpath>--> <!-- </xpath>-->
<!-- </field>--> <!-- </field>-->
<!-- </record>--> <!-- </record>-->
<record id="mrp_production_view_search_inherit_planning" model="ir.ui.view"> <record id="mrp_production_view_search_inherit_planning" model="ir.ui.view">
<field name="name">mrp.production.search.view.inherit.planning</field> <field name="name">mrp.production.search.view.inherit.planning</field>
@@ -46,9 +43,7 @@
<field name="inherit_id" ref="mrp.view_mrp_production_filter"/> <field name="inherit_id" ref="mrp.view_mrp_production_filter"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<filter name="filter_planned" position="attributes"> <filter name="filter_planned" position="attributes">
<attribute name="domain">[('is_planned', '=', True), ('date_planned_start', '!=', False), <attribute name="domain">[('is_planned', '=', True), ('date_planned_start', '!=', False), ('date_planned_finished', '!=', False)]</attribute>
('date_planned_finished', '!=', False)]
</attribute>
</filter> </filter>
</field> </field>
</record> </record>
@@ -56,33 +51,30 @@
<record id="production_order_unplan_server_action" model="ir.actions.server"> <record id="production_order_unplan_server_action" model="ir.actions.server">
<field name="name">Unplan orders</field> <field name="name">Unplan orders</field>
<field name="model_id" ref="mrp.model_mrp_production"/> <field name="model_id" ref="mrp.model_mrp_production"/>
<field name="binding_model_id" ref="mrp.model_mrp_production"/> <field name="binding_model_id" ref="mrp.model_mrp_production" />
<field name="binding_view_types">list</field> <field name="binding_view_types">list</field>
<field name="state">code</field> <field name="state">code</field>
<field name="code">records.button_unplan()</field> <field name="code">records.button_unplan()</field>
</record> </record>
<record id="mrp.act_product_mrp_production_workcenter" model="ir.actions.act_window"> <record id="mrp.act_product_mrp_production_workcenter" model="ir.actions.act_window">
<field name="domain">[('bom_id', '!=', False), ('bom_id.operation_ids.workcenter_id', '=', active_id), <field name="domain">[('bom_id', '!=', False), ('bom_id.operation_ids.workcenter_id', '=', active_id), ('date_planned_start', '!=', False), ('date_planned_finished', '!=', False)]</field>
('date_planned_start', '!=', False), ('date_planned_finished', '!=', False)]
</field>
<field name="view_id" ref="mrp_production_tree_view_planning"/> <field name="view_id" ref="mrp_production_tree_view_planning"/>
</record> </record>
<menuitem id="mrp_workorder_menu_planning" <menuitem id="mrp_workorder_menu_planning"
name="Work Orders" name="Work Orders"
sequence="2" sequence="2"
parent="mrp.mrp_planning_menu_root" parent="mrp.mrp_planning_menu_root"
groups="mrp.group_mrp_routings"/> groups="mrp.group_mrp_routings"/>
<menuitem id="menu_mrp_workorder_production" <menuitem id="menu_mrp_workorder_production"
name="Planning by Production" name="Planning by Production"
sequence="1" sequence="1"
action="mrp.action_mrp_workorder_production" action="mrp.action_mrp_workorder_production"
parent="mrp_workorder_menu_planning"/> parent="mrp_workorder_menu_planning"/>
<menuitem id="menu_mrp_workorder_workcenter" <menuitem id="menu_mrp_workorder_workcenter"
name="Planning by Workcenter" name="Planning by Workcenter"
sequence="2" sequence="2"
action="mrp_workorder.action_mrp_workorder_dependencies_workcenter" action="mrp_workorder.action_mrp_workorder_dependencies_workcenter"
parent="mrp_workorder_menu_planning"/> parent="mrp_workorder_menu_planning"/>
</odoo> </odoo>

View File

@@ -35,7 +35,6 @@
], ],
'web.assets_backend': [ 'web.assets_backend': [
'sf_base/static/src/scss/*.scss', 'sf_base/static/src/scss/*.scss',
'sf_base/static/src/js/*.js',
], ],
}, },

View File

@@ -11,10 +11,11 @@ class Printer(models.Model):
class TableStyle(models.Model): class TableStyle(models.Model):
_name = 'table.style' _name = 'label.style'
_description = '标签样式' _description = '标签样式'
name = fields.Char(string='名称', required=True) name = fields.Char(string='名称', required=True)
zpl_code = fields.Text(string='zpl指令')
# todo # todo
@@ -25,4 +26,5 @@ class PrinterConfiguration(models.Model):
name = fields.Char(string='名称', required=True) name = fields.Char(string='名称', required=True)
printer_id = fields.Many2one('printer', string='打印机') printer_id = fields.Many2one('printer', string='打印机')
model = fields.Many2one('ir.model', string='模型名称') model = fields.Many2one('ir.model', string='模型名称')
label_id = fields.Many2one('label.style', '标签')
# # 其他相关字段... # # 其他相关字段...

View File

@@ -43,19 +43,19 @@ class PrintingUtils(models.AbstractModel):
zpl_code += "^CI28\n" zpl_code += "^CI28\n"
# 设置二维码位置 # 设置二维码位置
zpl_code += "^FO50,50\n" # 调整二维码位置,使其与资产编号在同一行 zpl_code += "^FO50,260\n" # 调整二维码位置,使其与资产编号在同一行
zpl_code += f"^BQN,2,6^FDLM,B0093{code}^FS\n" zpl_code += f"^BQN,2,5^FDLM,B0093{code}^FS\n"
# 设置资产编号文本位置 # # 设置资产编号文本位置
zpl_code += "^FO300,60\n" # 资产编号文本的位置,与二维码在同一行 # zpl_code += "^FO300,60\n" # 资产编号文本的位置,与二维码在同一行
zpl_code += "^A1N,45,45^FD编码名称: ^FS\n" # zpl_code += "^A1N,45,45^FD编码名称: ^FS\n"
# 设置{code}文本位置 # 设置{code}文本位置
# 假设{code}文本需要位于资产编号和二维码下方,中间位置 # 假设{code}文本需要位于资产编号和二维码下方,中间位置
# 设置{code}文本位置并启用自动换行 # 设置{code}文本位置并启用自动换行
zpl_code += "^FO300,120\n" # {code}文本的起始位置 zpl_code += "^FO240,10\n" # {code}文本的起始位置
zpl_code += "^FB400,4,0,L,0\n" # 定义一个宽度为500点的文本框最多4行左对齐 zpl_code += "^FB600,10,0,L,0\n" # 定义一个宽度为500点的文本框最多4行左对齐
zpl_code += f"^A1N,40,40^FD{code}^FS\n" zpl_code += f"^A1B,40,40^FD{code}^FS\n"
# 在{code}文本框周围绘制线框 # 在{code}文本框周围绘制线框
# 假设线框的外部尺寸为宽度500点高度200点 # 假设线框的外部尺寸为宽度500点高度200点

View File

@@ -5,4 +5,3 @@ from . import fixture
from . import functional_fixture from . import functional_fixture
from . import tool_other_features from . import tool_other_features
from . import basic_parameters_fixture from . import basic_parameters_fixture
from . import ir_sequence

View File

@@ -13,7 +13,7 @@ class BasicParametersFixture(models.Model):
diameter = fields.Float('直径(mm)', digits=(16, 2)) diameter = fields.Float('直径(mm)', digits=(16, 2))
# '零点卡盘' 字段 # '零点卡盘' 字段
weight = fields.Float('重量(kg)', digits=(16, 2)) weight = fields.Float('重量(mm)', digits=(16, 2))
orientation_dish_diameter = fields.Float('定位盘直径(mm)', digits=(16, 2)) orientation_dish_diameter = fields.Float('定位盘直径(mm)', digits=(16, 2))
clamping_diameter = fields.Float('装夹直径(mm)', digits=(16, 2)) clamping_diameter = fields.Float('装夹直径(mm)', digits=(16, 2))
clamping_num = fields.Selection([('1', '1'), ('2', '2'), ('4', '4'), ('6', '6'), ('8', '8')], string='装夹单元数') clamping_num = fields.Selection([('1', '1'), ('2', '2'), ('4', '4'), ('6', '6'), ('8', '8')], string='装夹单元数')

View File

@@ -61,10 +61,12 @@ class MrsMaterialModel(models.Model):
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)
@api.constrains("gain_way") @api.onchange('gain_way')
def _check_supplier_ids(self): def _check_gain_way(self):
for item in self: if not self.gain_way:
if item.gain_way in ('外协', '采购') and not item.supplier_ids: raise UserError("请选择获取方式")
if self.gain_way in ['外协', '采购']:
if not self.supplier_ids:
raise UserError("请添加供应商") raise UserError("请添加供应商")
@@ -84,21 +86,17 @@ class MrsProductionProcessCategory(models.Model):
class MrsProductionProcess(models.Model): class MrsProductionProcess(models.Model):
_name = 'sf.production.process' _name = 'sf.production.process'
_description = '表面工艺' _description = '表面工艺'
order = 'sequence asc'
code = fields.Char("编码") code = fields.Char("编码")
name = fields.Char('名称') name = fields.Char('名称')
remark = fields.Text("备注") remark = fields.Text("备注")
sequence = fields.Integer('排序')
# processing_order_ids = fields.One2many('sf.processing.order', 'production_process_id', string='工序') # processing_order_ids = fields.One2many('sf.processing.order', 'production_process_id', string='工序')
partner_process_ids = fields.Many2many('res.partner', 'process_ids', '加工工厂') partner_process_ids = fields.Many2many('res.partner', 'process_ids', '加工工厂')
active = fields.Boolean('有效', default=True) active = fields.Boolean('有效', default=True)
parameter_ids = fields.One2many('sf.production.process.parameter', 'process_id', string='可选参数') parameter_ids = fields.One2many('sf.production.process.parameter', 'process_id', string='可选参数')
category_id = fields.Many2one('sf.production.process.category', string='表面工艺类别') category_id = fields.Many2one('sf.production.process.category')
# workcenter_ids = fields.Many2many('mrp.workcenter', 'rel_workcenter_process', required=True) # workcenter_ids = fields.Many2many('mrp.workcenter', 'rel_workcenter_process', required=True)
processing_day = fields.Float('加工天数/d')
travel_day = fields.Float('路途天数/d')
sequence = fields.Integer('排序')
# class MrsProcessingTechnology(models.Model): # class MrsProcessingTechnology(models.Model):
# _name = 'sf.processing.technology' # _name = 'sf.processing.technology'
@@ -145,12 +143,8 @@ class MrsProductionProcessParameter(models.Model):
is_check = fields.Boolean(default=False) is_check = fields.Boolean(default=False)
# price = fields.Float('单价') # price = fields.Float('单价')
process_id = fields.Many2one('sf.production.process', string='表面工艺') process_id = fields.Many2one('sf.production.process', string='表面工艺')
process_description = fields.Char(string='工艺描述')
materials_model_ids = fields.Many2many('sf.materials.model', 'applicable_material', string='适用材料') materials_model_ids = fields.Many2many('sf.materials.model', 'applicable_material', string='适用材料')
processing_day = fields.Float('加工天数/d')
travel_day = fields.Float('路途天数/d')
active = fields.Boolean('有效', default=True) active = fields.Boolean('有效', default=True)
processing_mm = fields.Char('加工厚度/mm')
def name_get(self): def name_get(self):
result = [] result = []

View File

@@ -1,74 +0,0 @@
import calendar
from datetime import timedelta
from odoo import models, fields
class IrSequence(models.Model):
_inherit = 'ir.sequence'
date_range_period = fields.Selection(
[('day', '每日'), ('month', '每月'), ('year', '每年')],
string='日期期间',
)
def _next(self, sequence_date=None):
""" Returns the next number in the preferred sequence in all the ones given in self."""
if not self.use_date_range:
return self._next_do()
# date mode
dt = sequence_date or self._context.get('ir_sequence_date', fields.Date.today())
seq_date = self.env['ir.sequence.date_range'].search(
[
('sequence_id', '=', self.id),
('date_from', '<=', dt),
('date_to', '>=', dt),
('date_range_period', '=', self.date_range_period)
], limit=1)
if not seq_date:
if self.date_range_period:
seq_date = self._create_date_range_seq_by_period(dt, self.date_range_period)
else:
seq_date = self._create_date_range_seq(dt)
return seq_date.with_context(ir_sequence_date_range=seq_date.date_from)._next()
def _create_date_range_seq_by_period(self, date, period):
if period == 'year':
year = fields.Date.from_string(date).strftime('%Y')
date_from = '{}-01-01'.format(year)
date_to = '{}-12-31'.format(year)
if period == 'month':
# 计算当前月份的第一天和最后一天
year = fields.Date.from_string(date).strftime('%Y')
month = fields.Date.from_string(date).strftime('%m')
date_from = fields.Date.from_string(date).strftime('%Y-%m-01')
date_to = '{}-{}-{}'.format(year, month, calendar.monthrange(int(year), int(month))[1])
if period == 'day':
date_from = date
date_to = date
date_range = self.env['ir.sequence.date_range'].search(
[
('sequence_id', '=', self.id),
('date_to', '>=', date_from),
('date_to', '<=', date),
('date_range_period', '=', period)
],
order='date_to desc', limit=1)
if date_range:
date_from = date_range.date_to + timedelta(days=1)
seq_date_range = self.env['ir.sequence.date_range'].sudo().create({
'date_from': date_from,
'date_to': date_to,
'sequence_id': self.id,
'date_range_period': period,
})
return seq_date_range
class IrSequenceDateRange(models.Model):
_inherit = 'ir.sequence.date_range'
date_range_period = fields.Selection(
[('day', '每日'), ('month', '每月'), ('year', '每年')],
string='日期期间',
)

View File

@@ -331,7 +331,7 @@ class ToolInventory(models.Model):
work_material = fields.Selection([('', ''), ('', '')], string='加工材料') work_material = fields.Selection([('', ''), ('', '')], string='加工材料')
life_span = fields.Float('寿命(min)') life_span = fields.Float('寿命(min)')
tool_groups_id = fields.Many2one('sf.tool.groups', string='刀具组', required=True) tool_groups_id = fields.Many2one('sf.tool.groups', string='刀具组')
active = fields.Boolean('已归档', default=True) active = fields.Boolean('已归档', default=True)

View File

@@ -0,0 +1,10 @@
diff a/sf_base/models/tool_base_new.py b/sf_base/models/tool_base_new.py (rejected hunks)
@@ -108,6 +108,4 @@
cutting_speed_ids = fields.One2many('sf.cutting.speed', 'standard_library_id', string='切削速度Vc')
- feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz',
- domain=[('cutting_speed', '!=', False)])
- feed_per_tooth_ids_3 = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz',
- domain=[('cutting_speed', '!=', False)])
+ feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz')
+ feed_per_tooth_ids_3 = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz')

View File

@@ -11,8 +11,8 @@ access_sf_machine_control_system,sf_machine_control_system,model_sf_machine_cont
access_sf_machine_control_system_admin,sf_machine_control_system_admin,model_sf_machine_control_system,base.group_system,1,1,1,0 access_sf_machine_control_system_admin,sf_machine_control_system_admin,model_sf_machine_control_system,base.group_system,1,1,1,0
access_sf_production_process_group_sale_director,sf_production_process_group_sale_director,model_sf_production_process,sf_base.group_sale_director,1,0,0,0 access_sf_production_process_group_sale_director,sf_production_process_group_sale_director,model_sf_production_process,sf_base.group_sale_director,1,0,0,0
access_sf_production_process_group_sale_salemanager,sf_production_process_group_sale_salemanager,model_sf_production_process,sf_base.group_sale_salemanager,1,0,0,0 access_sf_production_process_group_sale_salemanager,sf_production_process_group_sale_salemanager,model_sf_production_process,sf_base.group_sale_salemanager,1,0,0,0
access_res_partner_category_group_sale_salemanager,res_partner_category_group_sale_salemanager,base.model_res_partner_category,sf_base.group_sale_salemanager,1,1,1,0 access_res_partner_category_group_sale_salemanager,res_partner_category_group_sale_salemanager,base.model_res_partner_category,sf_base.group_sale_salemanager,1,0,1,0
access_res_partner_category_group_sale_director,res_partner_category_group_sale_director,base.model_res_partner_category,sf_base.group_sale_director,1,1,1,0 access_res_partner_category_group_sale_director,res_partner_category_group_sale_director,base.model_res_partner_category,sf_base.group_sale_director,1,0,1,0
access_sf_production_process,sf_production_process,model_sf_production_process,base.group_user,1,1,1,0 access_sf_production_process,sf_production_process,model_sf_production_process,base.group_user,1,1,1,0
access_sf_production_process_admin,sf_production_process_admin,model_sf_production_process,base.group_system,1,1,1,0 access_sf_production_process_admin,sf_production_process_admin,model_sf_production_process,base.group_system,1,1,1,0
access_sf_production_materials,sf_production_materials,model_sf_production_materials,base.group_user,1,1,1,0 access_sf_production_materials,sf_production_materials,model_sf_production_materials,base.group_user,1,1,1,0
@@ -208,6 +208,7 @@ access_sf_machine_brand_tags_group_purchase_director,sf_machine_brand_tags_group
access_printer,printer,model_printer,base.group_user,1,1,1,1 access_printer,printer,model_printer,base.group_user,1,1,1,1
access_printer_configuration,printer.configuration,model_printer_configuration,base.group_user,1,1,1,1 access_printer_configuration,printer.configuration,model_printer_configuration,base.group_user,1,1,1,1
access_label_style,label.style,model_label_style,base.group_user,1,1,1,1
access_group_sf_mrp_user,sf_tool_inventory,model_sf_tool_inventory,base.group_user,1,1,1,0 access_group_sf_mrp_user,sf_tool_inventory,model_sf_tool_inventory,base.group_user,1,1,1,0
access_group_sf_mrp_user_admin,sf_tool_inventory_admin,model_sf_tool_inventory,base.group_system,1,1,1,0 access_group_sf_mrp_user_admin,sf_tool_inventory_admin,model_sf_tool_inventory,base.group_system,1,1,1,0
@@ -242,8 +243,3 @@ access_sf_fixture_materials_basic_parameters_group_sf_stock_manager,sf_fixture_m
access_sf_multi_mounting_type_group_sf_stock_manager,sf_multi_mounting_type_group_sf_stock_manager,model_sf_multi_mounting_type,sf_base.group_sf_stock_manager,1,0,0,0 access_sf_multi_mounting_type_group_sf_stock_manager,sf_multi_mounting_type_group_sf_stock_manager,model_sf_multi_mounting_type,sf_base.group_sf_stock_manager,1,0,0,0
access_sf_machine_brand_group_sf_stock_manager,sf_machine_brand_group_sf_stock_manager,model_sf_machine_brand,sf_base.group_sf_stock_manager,1,0,0,0 access_sf_machine_brand_group_sf_stock_manager,sf_machine_brand_group_sf_stock_manager,model_sf_machine_brand,sf_base.group_sf_stock_manager,1,0,0,0
access_sf_cutting_tool_type_group_sf_stock_manager,sf_cutting_tool_type_group_sf_stock_manager,model_sf_cutting_tool_type,sf_base.group_sf_stock_manager,1,0,0,0 access_sf_cutting_tool_type_group_sf_stock_manager,sf_cutting_tool_type_group_sf_stock_manager,model_sf_cutting_tool_type,sf_base.group_sf_stock_manager,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_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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
11 access_sf_machine_control_system_admin sf_machine_control_system_admin model_sf_machine_control_system base.group_system 1 1 1 0
12 access_sf_production_process_group_sale_director sf_production_process_group_sale_director model_sf_production_process sf_base.group_sale_director 1 0 0 0
13 access_sf_production_process_group_sale_salemanager sf_production_process_group_sale_salemanager model_sf_production_process sf_base.group_sale_salemanager 1 0 0 0
14 access_res_partner_category_group_sale_salemanager res_partner_category_group_sale_salemanager base.model_res_partner_category sf_base.group_sale_salemanager 1 1 0 1 0
15 access_res_partner_category_group_sale_director res_partner_category_group_sale_director base.model_res_partner_category sf_base.group_sale_director 1 1 0 1 0
16 access_sf_production_process sf_production_process model_sf_production_process base.group_user 1 1 1 0
17 access_sf_production_process_admin sf_production_process_admin model_sf_production_process base.group_system 1 1 1 0
18 access_sf_production_materials sf_production_materials model_sf_production_materials base.group_user 1 1 1 0
208 access_sf_multi_mounting_type_group_purchase_director access_sf_fixture_material_group_purchase_director sf_multi_mounting_type_group_purchase_director sf_fixture_material_group_purchase_director model_sf_multi_mounting_type model_sf_fixture_material sf_base.group_purchase_director 1 0 0 0
209 access_sf_fixture_model_group_purchase_director access_sf_multi_mounting_type_group_purchase_director sf_fixture_model_group_purchase_director sf_multi_mounting_type_group_purchase_director model_sf_fixture_model model_sf_multi_mounting_type sf_base.group_purchase_director 1 0 0 0
210 access_sf_fixture_materials_basic_parameters_group_purchase_director access_sf_fixture_model_group_purchase_director sf_fixture_materials_basic_parameters_group_purchase_director sf_fixture_model_group_purchase_director model_sf_fixture_materials_basic_parameters model_sf_fixture_model sf_base.group_purchase_director 1 0 0 0
211 access_sf_fixture_materials_basic_parameters_group_purchase_director sf_fixture_materials_basic_parameters_group_purchase_director model_sf_fixture_materials_basic_parameters sf_base.group_purchase_director 1 0 0 0
212 access_sf_machine_tool_type_group_purchase_director sf_machine_tool_type_group_purchase_director model_sf_machine_tool_type sf_base.group_purchase_director 1 0 0 0
213 access_sf_fixture_material_group_sale_director sf_fixture_material_group_sale_director model_sf_fixture_material sf_base.group_sale_director 1 0 0 0
214 access_sf_multi_mounting_type_group_sale_director sf_multi_mounting_type_group_sale_director model_sf_multi_mounting_type sf_base.group_sale_director 1 0 0 0
243
244
245

View File

@@ -1,61 +0,0 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { barcodeGenericHandlers } from '@barcodes/barcode_handlers';
import { patch } from "@web/core/utils/patch";
// 定义新的 clickOnButton 函数
function customClickOnButton(selector) {
console.log("This is the custom clickOnButton function!");
const buttons = document.body.querySelectorAll(selector);
let length = buttons.length;
if (length > 0) {
buttons[length - 1].click();
} else {
console.warn(`Button with selector ${selector} not found`);
}
}
patch(barcodeGenericHandlers, "start", {
start(env, { ui, barcode, notification }) {
// 使用新定义的 clickOnButton 函数
const COMMANDS = {
"O-CMD.EDIT": () => customClickOnButton(".o_form_button_edit"),
"O-CMD.DISCARD": () => customClickOnButton(".o_form_button_cancel"),
"O-CMD.SAVE": () => customClickOnButton(".o_form_button_save"),
"O-CMD.PREV": () => customClickOnButton(".o_pager_previous"),
"O-CMD.NEXT": () => customClickOnButton(".o_pager_next"),
"O-CMD.PAGER-FIRST": () => updatePager("first"),
"O-CMD.PAGER-LAST": () => updatePager("last"),
"O-CMD.CONFIRM": () => customClickOnButton(".jikimo_button_confirm"),
};
barcode.bus.addEventListener("barcode_scanned", (ev) => {
const barcode = ev.detail.barcode;
if (barcode.startsWith("O-BTN.")) {
let targets = [];
try {
targets = getVisibleElements(ui.activeElement, `[barcode_trigger=${barcode.slice(6)}]`);
} catch (_e) {
console.warn(`Barcode '${barcode}' is not valid`);
}
for (let elem of targets) {
elem.click();
}
}
if (barcode.startsWith("O-CMD.")) {
const fn = COMMANDS[barcode];
if (fn) {
fn();
} else {
notification.add(env._t("Barcode: ") + `'${barcode}'`, {
title: env._t("Unknown barcode command"),
type: "danger"
});
}
}
});
}
})

View File

@@ -1,42 +0,0 @@
/** @odoo-module **/
import { registry } from '@web/core/registry';
import { formView } from '@web/views/form/form_view';
import { FormController } from '@web/views/form/form_controller';
import { listView } from '@web/views/list/list_view';
import { ListController } from '@web/views/list/list_controller'
import { onRendered, onMounted } from "@odoo/owl";
export class RemoveFocusFormController extends FormController {
setup() {
super.setup();
onMounted(() => {
this.__owl__.bdom.el.querySelectorAll(':focus').forEach(element => element.blur());
})
}
}
registry.category('views').add('remove_focus_form_view', {
...formView,
Controller: RemoveFocusFormController,
});
export class RemoveFocusListController extends ListController {
setup() {
super.setup();
onMounted(() => {
this.__owl__.bdom.el.querySelectorAll(':focus').forEach(element => element.blur());
})
}
}
registry.category('views').add('remove_focus_list_view', {
...listView,
Controller: RemoveFocusListController,
});

View File

@@ -38,6 +38,7 @@
<field name="name"/> <field name="name"/>
<field name="printer_id"/> <field name="printer_id"/>
<field name="model"/> <field name="model"/>
<field name="label_id"/>
<!-- 其他字段... --> <!-- 其他字段... -->
</tree> </tree>
</field> </field>
@@ -53,6 +54,36 @@
<field name="name"/> <field name="name"/>
<field name="printer_id"/> <field name="printer_id"/>
<field name="model"/> <field name="model"/>
<field name="label_id"/>
<!-- 其他字段... -->
</group>
</sheet>
</form>
</field>
</record>
<record id="view_label_style_tree" model="ir.ui.view">
<field name="name">label.style.tree</field>
<field name="model">label.style</field>
<field name="arch" type="xml">
<tree string="label style">
<field name="name"/>
<!-- <field name="zpl_code"/> -->
<!-- 其他字段... -->
</tree>
</field>
</record>
<record id="view_label_style_form" model="ir.ui.view">
<field name="name">label.style.form</field>
<field name="model">label.style</field>
<field name="arch" type="xml">
<form string="label style">
<sheet>
<group>
<field name="name"/>
<field name="zpl_code"/>
<!-- 其他字段... --> <!-- 其他字段... -->
</group> </group>
</sheet> </sheet>
@@ -74,6 +105,11 @@
<field name="res_model">printer.configuration</field> <field name="res_model">printer.configuration</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<record id="action_label_style" model="ir.actions.act_window">
<field name="name">标签样式</field>
<field name="res_model">label.style</field>
<field name="view_mode">tree,form,kanban</field>
</record>
<!-- Add a menu item for the printer configuration --> <!-- Add a menu item for the printer configuration -->
<!-- <record id="menu_printer_configuration" model="ir.ui.menu"> --> <!-- <record id="menu_printer_configuration" model="ir.ui.menu"> -->
@@ -108,5 +144,12 @@
sequence="2" sequence="2"
parent="printer_main_menu"/> parent="printer_main_menu"/>
<menuitem
id="menu_label_style"
name="标签样式"
action="action_label_style"
sequence="3"
parent="printer_main_menu"/>
</data> </data>
</odoo> </odoo>

View File

@@ -12,10 +12,11 @@
</tree> </tree>
</field> </field>
</record> </record>
<record model="ir.ui.view" id="mrs_production_process_parameter_form"> <record model="ir.ui.view" id="mrs_production_process_parameter_form">
<field name="model">sf.production.process.parameter</field> <field name="model">sf.production.process.parameter</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="表面工艺可选参数" create="0" delete="0" > <form string="表面工艺可选参数" create="0" delete="0">
<sheet> <sheet>
<div class="oe_title"> <div class="oe_title">
<h1> <h1>
@@ -25,19 +26,14 @@
<group> <group>
<group> <group>
<field name="code" readonly="1"/> <field name="code" readonly="1"/>
<field name="process_id" attrs="{'readonly': [('code', '!=', False)]}"/> <field name="process_id" readonly="1"/>
<field name="process_description" attrs="{'readonly': [('code', '!=', False)]}"/>
<field name="gain_way"/> <field name="gain_way"/>
</group> </group>
<group>
<field name="processing_day" attrs="{'readonly': [('code', '!=', False)]}"/>
<field name="travel_day" attrs="{'readonly': [('code', '!=', False)]}"/>
<field name="processing_mm" attrs="{'readonly': [('code', '!=', False)]}"/>
</group>
</group> </group>
<notebook> <notebook>
<page string="适用材料"> <page string="适用材料">
<field name="materials_model_ids" attrs="{'readonly': [('code', '!=', False)]}"></field> <field name="materials_model_ids"></field>
</page> </page>
</notebook> </notebook>
</sheet> </sheet>
@@ -52,7 +48,7 @@
<search> <search>
<filter name="filter_active" string="已归档" domain="[('active','=',False)]"/> <filter name="filter_active" string="已归档" domain="[('active','=',False)]"/>
<field name="name" string="名称" filter_domain="[('name','ilike',self)]"/> <field name="name" string="名称" filter_domain="[('name','ilike',self)]"/>
<field name="code" string="编码" filter_domain="[('code','ilike',self)]"/> <field name="code" string="编码" filter_domain="[('codeNum','ilike',self)]"/>
<searchpanel class="account_root"> <searchpanel class="account_root">
<field name="process_id" icon="fa-filter"/> <field name="process_id" icon="fa-filter"/>
</searchpanel> </searchpanel>
@@ -140,7 +136,7 @@
<field name="model">sf.production.process.category</field> <field name="model">sf.production.process.category</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="表面工艺类别" default_order="sequence, id" create="0" edit="0" delete="1"> <tree string="表面工艺类别" default_order="sequence, id" create="0" edit="0" delete="1">
<field name="sequence" widget="handle" string="序号" readonly="1"/> <field name="sequence" widget="handle" string="序号"/>
<field name="code"/> <field name="code"/>
<field name="name" string="名称"/> <field name="name" string="名称"/>
</tree> </tree>
@@ -163,8 +159,7 @@
<record model="ir.ui.view" id="sf_production_process_tree"> <record model="ir.ui.view" id="sf_production_process_tree">
<field name="model">sf.production.process</field> <field name="model">sf.production.process</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="表面工艺" create="0" edit="0" delete="0"> <tree string="表面工艺" create="0" edit="0" delete="1">
<field name="sequence" string="加工顺序" readonly="1"/>
<field name="code"/> <field name="code"/>
<field name="name" string="名称"/> <field name="name" string="名称"/>
<field name="remark"/> <field name="remark"/>
@@ -175,7 +170,7 @@
<record model="ir.ui.view" id="sf_production_process_form"> <record model="ir.ui.view" id="sf_production_process_form">
<field name="model">sf.production.process</field> <field name="model">sf.production.process</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="表面工艺" create="0" delete="0"> <form string="表面工艺" create="0" edit="1" delete="1">
<sheet> <sheet>
<div class="oe_title"> <div class="oe_title">
<h1> <h1>
@@ -184,46 +179,41 @@
</div> </div>
<group> <group>
<group> <group>
<field name="code" readonly="1"/> <field name="code"/>
<field name="category_id" readonly="1"/>
</group> </group>
<group> <notebook>
<field name="processing_day" readonly="1"/> <page string="可选参数">
<field name="travel_day" readonly="1"/> <field name="parameter_ids">
</group> <tree force_save="1">
</group> <field name="code" readonly="1" force_save="1"/>
<notebook> <field name="name"/>
<page string="可选参数" > <field name="gain_way"/>
<field name="parameter_ids" > <field name='process_id' default="default"/>
<tree force_save="1" create="0"> </tree>
<field name="code" readonly="1" force_save="1"/> <form>
<field name="name" readonly="1"/> <sheet>
<field name="gain_way"/>
<field name='process_id' default="default"/>
</tree>
<form>
<sheet>
<group>
<group> <group>
<field name="code"/> <group>
<field name="name" string="参数名"/> <field name="code"/>
<field name="name" string="参数名"/>
</group>
<group>
<field name='process_id'/>
<field name="gain_way"/>
</group>
</group> </group>
<group> <notebook>
<field name='process_id'/> <page string="适用材料">
<field name="gain_way"/> <field name="materials_model_ids"/>
</group> </page>
</group> </notebook>
<notebook> </sheet>
<page string="适用材料"> </form>
<field name="materials_model_ids"/> </field>
</page> </page>
</notebook>
</sheet>
</form>
</field>
</page>
</notebook> </notebook>
</group>
<group> <group>
<group> <group>
<field name="remark"/> <field name="remark"/>
@@ -261,7 +251,7 @@
<group> <group>
<group> <group>
<field name="materials_no" readonly="1" force_save="1"/> <field name="materials_no" readonly="1" force_save="1"/>
<field name="gain_way" required="0"/> <field name="gain_way" required="1"/>
<field name="tensile_strength" required="1"/> <field name="tensile_strength" required="1"/>
<field name="hardness" required="1"/> <field name="hardness" required="1"/>
<field name="density" readonly="1"/> <field name="density" readonly="1"/>
@@ -280,9 +270,9 @@
<notebook> <notebook>
<page string="供应商"> <page string="供应商">
<field name='supplier_ids' class="supplier_ids_set_css"> <field name='supplier_ids' class="supplier_ids_set_css">
<tree editable='bottom' delete="1"> <tree editable='bottom'>
<field name="sequence" widget="handle" string="序号"/> <field name="sequence" widget="handle" string="序号"/>
<field name="partner_id" string="名称" options="{'no_create': True}"/> <field name="partner_id" string="名称"/>
</tree> </tree>
</field> </field>
</page> </page>

View File

@@ -171,7 +171,7 @@
<field name="width"/> <field name="width"/>
<field name="height"/> <field name="height"/>
<field name="diameter"/> <field name="diameter"/>
<field name="weight" string="重量(kg)"/> <field name="weight"/>
<field name="orientation_dish_diameter"/> <field name="orientation_dish_diameter"/>
<field name="clamping_diameter"/> <field name="clamping_diameter"/>
<field name="clamping_num"/> <field name="clamping_num"/>
@@ -197,7 +197,7 @@
<field name="width"/> <field name="width"/>
<field name="height"/> <field name="height"/>
<field name="diameter"/> <field name="diameter"/>
<field name="weight" string="重量(kg)"/> <field name="weight"/>
<field name="clamping_diameter"/> <field name="clamping_diameter"/>
<field name="connector_diameter"/> <field name="connector_diameter"/>
<field name="chucking_power_max"/> <field name="chucking_power_max"/>
@@ -220,7 +220,7 @@
<field name="length"/> <field name="length"/>
<field name="width"/> <field name="width"/>
<field name="height"/> <field name="height"/>
<field name="weight" string="重量(kg)"/> <field name="weight"/>
<field name="gripper_length_min"/> <field name="gripper_length_min"/>
<field name="gripper_width_min"/> <field name="gripper_width_min"/>
<field name="gripper_height_min"/> <field name="gripper_height_min"/>
@@ -248,7 +248,7 @@
<field name="length"/> <field name="length"/>
<field name="width"/> <field name="width"/>
<field name="height"/> <field name="height"/>
<field name="weight" string="重量(kg)"/> <field name="weight"/>
<field name="gripper_length_min"/> <field name="gripper_length_min"/>
<field name="gripper_width_min"/> <field name="gripper_width_min"/>
<field name="gripper_height_min"/> <field name="gripper_height_min"/>
@@ -278,7 +278,7 @@
<field name="width"/> <field name="width"/>
<field name="height"/> <field name="height"/>
<field name="height_tolerance_value"/> <field name="height_tolerance_value"/>
<field name="weight" string="重量(kg)"/> <field name="weight"/>
<field name="gripper_length_min"/> <field name="gripper_length_min"/>
<field name="gripper_width_min"/> <field name="gripper_width_min"/>
<field name="gripper_height_min"/> <field name="gripper_height_min"/>
@@ -307,7 +307,7 @@
<field name="length"/> <field name="length"/>
<field name="width"/> <field name="width"/>
<field name="height"/> <field name="height"/>
<field name="weight" string="重量(kg)"/> <field name="weight"/>
<field name="gripper_length_min"/> <field name="gripper_length_min"/>
<field name="gripper_width_min"/> <field name="gripper_width_min"/>
<field name="gripper_height_min"/> <field name="gripper_height_min"/>
@@ -335,7 +335,7 @@
<field name="width"/> <field name="width"/>
<field name="height"/> <field name="height"/>
<field name="diameter"/> <field name="diameter"/>
<field name="weight" string="重量(kg)"/> <field name="weight"/>
<field name="gripper_length_min"/> <field name="gripper_length_min"/>
<field name="gripper_width_min"/> <field name="gripper_width_min"/>
<field name="gripper_height_min"/> <field name="gripper_height_min"/>

View File

@@ -80,10 +80,10 @@
<field name="name">sf.cutter.function.tree</field> <field name="name">sf.cutter.function.tree</field>
<field name="model">sf.functional.cutting.tool.model</field> <field name="model">sf.functional.cutting.tool.model</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="功能刀具类型" create="0" delete="0" edit="1" editable="bottom"> <tree string="功能刀具类型" create="0" delete="0" edit="1">
<field name="name" string="名称" readonly="1"/> <field name="name" string="名称"/>
<field name="code" readonly="1"/> <field name="code"/>
<field name="remark" readonly="1"/> <field name="remark"/>
</tree> </tree>
</field> </field>
</record> </record>
@@ -555,9 +555,9 @@
<field name="model">sf.tool.inventory</field> <field name="model">sf.tool.inventory</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="功能刀具清单" create="1" edit="1" delete="0" editable="bottom"> <tree string="功能刀具清单" create="1" edit="1" delete="0" editable="bottom">
<field name="name" attrs="{'readonly': [('id', '!=', False)]}"/> <field name="name"/>
<field name="functional_cutting_tool_model_id"/> <field name="functional_cutting_tool_model_id"/>
<field name="tool_groups_id" required="1" attrs="{'readonly': [('id', '!=', False)]}"/> <field name="tool_groups_id"/>
<field name="work_material"/> <field name="work_material"/>
<field name="life_span"/> <field name="life_span"/>
<field name="prefix" optional="hide"/> <field name="prefix" optional="hide"/>

View File

@@ -21,7 +21,6 @@ class Http(models.AbstractModel):
def _auth_method_sf_token(cls): def _auth_method_sf_token(cls):
# 从headers.environ中获取对方传过来的token,timestamp,加密的校验字符串 # 从headers.environ中获取对方传过来的token,timestamp,加密的校验字符串
datas = request.httprequest.headers.environ datas = request.httprequest.headers.environ
_logger.info('datas:%s' % datas)
if 'HTTP_TOKEN' in datas: if 'HTTP_TOKEN' in datas:
_logger.info('token:%s' % datas['HTTP_TOKEN']) _logger.info('token:%s' % datas['HTTP_TOKEN'])
# 查询密钥 # 查询密钥
@@ -36,7 +35,7 @@ class Http(models.AbstractModel):
post_time = int(datas['HTTP_TIMESTAMP']) post_time = int(datas['HTTP_TIMESTAMP'])
datetime_post = datetime.fromtimestamp(post_time) datetime_post = datetime.fromtimestamp(post_time)
datetime_now = datetime.now().replace(microsecond=0) datetime_now = datetime.now().replace(microsecond=0)
datetime_del = datetime_now + timedelta(seconds=30) datetime_del = datetime_now + timedelta(seconds=5)
if datetime_post > datetime_del: if datetime_post > datetime_del:
raise AuthenticationError('请求已过期') raise AuthenticationError('请求已过期')
check_str = '%s%s%s' % (datas['HTTP_TOKEN'], post_time, factory_secret.sf_secret_key) check_str = '%s%s%s' % (datas['HTTP_TOKEN'], post_time, factory_secret.sf_secret_key)

View File

@@ -5,7 +5,7 @@ import requests
import cpca import cpca
# from odoo.exceptions import UserError # from odoo.exceptions import UserError
# from odoo.exceptions import ValidationError # from odoo.exceptions import ValidationError
from odoo import api, fields, models, _ from odoo import api, fields, models
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -14,7 +14,7 @@ _logger = logging.getLogger(__name__)
class JdEclp(models.Model): class JdEclp(models.Model):
_inherit = 'stock.picking' _inherit = 'stock.picking'
senderNickName = fields.Char(string='寄件工厂简称', required=True, default='XT') senderNickName = fields.Char(string='寄件工厂简称', required=True, default='MW')
# receiverName = fields.Char(string='收件人姓名') # receiverName = fields.Char(string='收件人姓名')
# receiverMobile = fields.Char(string='收件人电话') # receiverMobile = fields.Char(string='收件人电话')
@@ -149,7 +149,7 @@ class JdEclp(models.Model):
}, },
} }
_logger.info('准备调接口1') _logger.info('准备调接口1')
url1 = config['bfm_url_new'] + '/api/create/jd/order' url1 = config['bfm_url'] + '/api/create/jd/order'
requests.post(url1, json=json1, data=None) requests.post(url1, json=json1, data=None)
_logger.info('调用成功1') _logger.info('调用成功1')
_logger.info('准备调接口2') _logger.info('准备调接口2')
@@ -158,31 +158,18 @@ class JdEclp(models.Model):
'orderNo': self.origin, 'orderNo': self.origin,
}, },
} }
url2 = config['bfm_url_new'] + '/api/get/jd/no' url2 = config['bfm_url'] + '/api/get/jd/no'
response = requests.post(url2, json=json2, data=None) response = requests.post(url2, json=json2, data=None)
# _logger.info('调用成功2', response.json()['result']['wbNo']) # _logger.info('调用成功2', response.json()['result']['wbNo'])
tem_ret = response.json().get('result') self.carrier_tracking_ref = response.json()['result']['wbNo']
if not tem_ret:
raise ValidationError('京东物流返回异常,请联系管理员')
self.carrier_tracking_ref = response.json()['result'].get('wbNo')
if not self.carrier_tracking_ref:
raise ValidationError('物流下单未成功,请联系管理员')
self.is_bill = True self.is_bill = True
self.logistics_status = '1' self.logistics_status = '1'
notification = { # # 京东物流下单后,销售订单状态改为待收货
'type': 'ir.actions.client', # self.env['sale.order'].search([('name', '=', self.origin)]).write({'scheduled_status': 'to receive'})
'tag': 'display_notification',
'params': {
'title': _('成功'),
'type': 'success',
'message': '物流下单成功',
'sticky': False,
'next': {'type': 'ir.actions.client', 'tag': 'reload'}
}
}
return notification # else:
# raise UserError("选择京东物流才能下单呦")
def get_bill(self): def get_bill(self):
""" """
@@ -196,7 +183,7 @@ class JdEclp(models.Model):
'no': self.origin, 'no': self.origin,
}, },
} }
url1 = config['bfm_url_new'] + '/api/create/jd/bill' url1 = config['bfm_url'] + '/api/create/jd/bill'
response = requests.post(url1, json=json1, data=None) response = requests.post(url1, json=json1, data=None)
# _logger.info('调用成功2', response.json()) # _logger.info('调用成功2', response.json())

View File

@@ -1,9 +1,7 @@
import traceback
from datetime import datetime from datetime import datetime
import logging import logging
import requests import requests
from odoo.exceptions import UserError from odoo import fields, models
from odoo import fields, models, _
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -16,52 +14,26 @@ class StatusChange(models.Model):
def action_confirm(self): def action_confirm(self):
# 在原有方法执行前记录日志和执行其他操作 # 在原有方法执行前记录日志和执行其他操作
logging.info('函数已经执行=============') logging.info('函数已经执行=============')
server_product_none = []
for order in self.order_line:
gain_way_no = order.product_template_id.model_process_parameters_ids.filtered(lambda a: not a.gain_way)
if gain_way_no:
process_parameters = [item.name for item in gain_way_no]
raise UserError(
_("请先至【制造】-【配置】中【表面工艺可选参数】为【%s】填写获取方式", ", ".join(process_parameters)))
for item in order.product_template_id.model_process_parameters_ids:
if item.gain_way == '外协':
server_product = self.env['product.template'].search(
[('server_product_process_parameters_id', '=', item.id),
('detailed_type', '=', 'service')])
if not server_product:
server_product_none.append(item.name)
if server_product_none:
raise UserError(_("请先至【产品】中创建【表面工艺参数】为【%s】的服务产品", ", ".join(server_product_none)))
# 使用super()来调用原始方法(在本例中为'sale.order'模型的'action_confirm'方法) # 使用super()来调用原始方法(在本例中为'sale.order'模型的'action_confirm'方法)
try: res = super(StatusChange, self).action_confirm()
res = super(StatusChange, self).action_confirm()
# 原有方法执行后进行额外的操作如调用外部API # 原有方法执行后进行额外的操作如调用外部API
process_start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') process_start_time = str(datetime.now())
config = self.env['res.config.settings'].get_values() config = self.env['res.config.settings'].get_values()
json1 = { json1 = {
'params': { 'params': {
'model_name': 'jikimo.process.order', 'model_name': 'jikimo.process.order',
'field_name': 'name', 'field_name': 'name',
'default_code': self.default_code, 'default_code': self.default_code,
'state': '加工中', 'state': '加工中',
'process_start_time': process_start_time, 'process_start_time': process_start_time,
}, },
} }
url1 = config['bfm_url_new'] + '/api/get/state/get_order' url1 = config['bfm_url'] + '/api/get/state/get_order'
ret = requests.post(url1, json=json1, data=None) requests.post(url1, json=json1, data=None)
ret = ret.json() logging.info('接口已经执行=============')
if not ret.get('error'):
logging.info('接口已经执行=============')
else:
traceback_error = traceback.format_exc()
logging.error("bfm订单状态同步失败:%s request info %s" % traceback_error)
logging.error('/api/get/state/get_order 请求失败{}'.format(ret))
raise UserError('工厂加工同步订单状态到bfm失败')
except UserError as e:
traceback_error = traceback.format_exc()
logging.error("工厂加工同步订单状态失败:%s " % traceback_error)
raise UserError(e)
return res return res
def action_cancel(self): def action_cancel(self):
@@ -82,7 +54,7 @@ class StatusChange(models.Model):
'state': '待派单', 'state': '待派单',
}, },
} }
url1 = config['bfm_url_new'] + '/api/get/state/cancel_order' url1 = config['bfm_url'] + '/api/get/state/cancel_order'
requests.post(url1, json=json1, data=None) requests.post(url1, json=json1, data=None)
return res return res
@@ -230,12 +202,12 @@ class FinishStatusChange(models.Model):
[('id', 'child_of', self.picking_type_id.warehouse_id.view_location_id.id), [('id', 'child_of', self.picking_type_id.warehouse_id.view_location_id.id),
('usage', '!=', 'supplier')]) ('usage', '!=', 'supplier')])
if self.env['stock.move'].search([ if self.env['stock.move'].search([
('state', 'in', ['confirmed', 'partially_available', 'waiting', 'assigned']), ('state', 'in', ['confirmed', 'partially_available', 'waiting', 'assigned']),
('product_qty', '>', 0), ('product_qty', '>', 0),
('location_id', 'in', wh_location_ids), ('location_id', 'in', wh_location_ids),
('move_orig_ids', '=', False), ('move_orig_ids', '=', False),
('picking_id', 'not in', self.ids), ('picking_id', 'not in', self.ids),
('product_id', 'in', lines.product_id.ids)], limit=1): ('product_id', 'in', lines.product_id.ids)], limit=1):
action = self.action_view_reception_report() action = self.action_view_reception_report()
action['context'] = {'default_picking_ids': self.ids} action['context'] = {'default_picking_ids': self.ids}
return action return action

View File

@@ -32,7 +32,7 @@
<field name="is_bill" invisible="True"/> <field name="is_bill" invisible="True"/>
<field name="logistics_status" invisible="True"/> <field name="logistics_status" invisible="True"/>
<field name="logistics_way" invisible="True"/> <field name="logistics_way" invisible="True"/>
<button string="物流下单" name="create_order" type="object" confirm="是否确认物流下单" class="btn-primary" <button string="京东物流下单" name="create_order" type="object" confirm="是否确认物流下单" class="btn-primary"
attrs="{'invisible': ['|', '|', '|', ('check_out', '!=', 'OUT'), ('state', '!=', 'assigned'), ('is_bill', '=', True), ('logistics_way', '=', '自提')]}"/> attrs="{'invisible': ['|', '|', '|', ('check_out', '!=', 'OUT'), ('state', '!=', 'assigned'), ('is_bill', '=', True), ('logistics_way', '=', '自提')]}"/>
<button string="获取物流面单" name="get_bill" type="object" confirm="是否获取物流面单" class="btn-primary" <button string="获取物流面单" name="get_bill" type="object" confirm="是否获取物流面单" class="btn-primary"
attrs="{'invisible': ['|', '|', '|', '|', ('check_out', '!=', 'OUT'), ('state', '!=', 'assigned'), ('logistics_status', '=', '2'), ('is_bill', '=', False), ('logistics_way', '=', '自提')]}"/> attrs="{'invisible': ['|', '|', '|', '|', ('check_out', '!=', 'OUT'), ('state', '!=', 'assigned'), ('logistics_status', '=', '2'), ('is_bill', '=', False), ('logistics_way', '=', '自提')]}"/>
@@ -45,50 +45,42 @@
<field name="model">stock.picking</field> <field name="model">stock.picking</field>
<field name="inherit_id" ref="delivery.view_picking_withcarrier_out_form"/> <field name="inherit_id" ref="delivery.view_picking_withcarrier_out_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="location_id" position="after"> <field name="location_id" position="after">
<field name="logistics_status" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/> <field name="logistics_status" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="logistics_way" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/> <field name="logistics_way" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
</field> </field>
</field>
</record>
<record id="tracking_only_view" model="ir.ui.view"> <xpath expr="//group//field[@name='carrier_id']" position="after">
<field name="name">tracking only</field> <!-- <field name="senderNickName" domain="[('self.name', 'like', '%OUT%')]"/> -->
<field name="model">stock.picking</field> <field name="senderNickName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="inherit_id" ref="stock.view_picking_form"/> <field name="expressItemName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="arch" type="xml"> <field name="deliveryType" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<xpath expr="//form//sheet//notebook//page[@name='operations']" position="after"> <field name="receiverName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<page string="发货信息" name="tracking"> <field name="receiverMobile" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<group> <field name="receiverProvinceName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<group> <field name="receiverCityName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="senderNickName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/> <field name="receiverCountyName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="expressItemName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/> <field name="receiverTownName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="grossWeight" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/> <field name="receiverCompany" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="grossVolume" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/> <field name="remark" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="deliveryType" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/> <field name="grossWeight" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="receiverName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/> <field name="grossVolume" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="receiverMobile" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/> <field name="pickupBeginTime" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="receiverProvinceName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/> <field name="bill_show" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="receiverCityName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/> <field name="logistics_status"/>
<field name="receiverCountyName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="receiverTownName" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="receiverCompany" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="remark" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
<field name="pickupBeginTime" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
</group>
<group>
<field name="logistics_status"/>
<field name="carrier_id"/>
<field name="carrier_tracking_ref"/>
<field name="bill_show" attrs="{'invisible': [('check_out', '!=', 'OUT')]}" string='面单下载'/>
<field name="bill_show" widget="pdf_viewer" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
</group>
</group>
</page>
</xpath> </xpath>
<xpath expr="//group//field[@name='group_id']" position="after">
<field name="bill_show" widget="pdf_viewer" attrs="{'invisible': [('check_out', '!=', 'OUT')]}"/>
</xpath>
<!-- <xpath expr="//group[@name='other_infos']" position="after"> -->
<!-- <div> -->
<!-- <button string="京东物流下单" name="create_order" type="object" confirm="是否确认物流下单" class="btn-primary"/> -->
<!-- </div> -->
<!-- <div> -->
<!-- <button string="获取物流面单" name="get_bill" type="object" confirm="是否获取物流面单" class="btn-primary"/> -->
<!-- </div> -->
<!-- </xpath> -->
</field> </field>
</record> </record>
</odoo> </odoo>

View File

@@ -122,7 +122,7 @@ class ResMrpBomMo(models.Model):
# 查bom的原材料 # 查bom的原材料
def get_raw_bom(self, product): def get_raw_bom(self, product):
raw_bom = self.env['product.product'].search( raw_bom = self.env['product.product'].search(
[('categ_id.type', '=', '原材料'), ('materials_type_id', '=', product.materials_type_id.id)],limit=1) [('categ_id.type', '=', '原材料'), ('materials_type_id', '=', product.materials_type_id.id)])
return raw_bom return raw_bom

View File

@@ -22,16 +22,6 @@
<field name="company_id" ref="base.main_company"/> <field name="company_id" ref="base.main_company"/>
</record> </record>
<record id="stock_location_tool_dismantle" model="stock.location">
<field name="name">拆解</field>
<field name="location_id" ref="stock.stock_location_locations_virtual"/>
<field name="usage">internal</field>
<field name="barcode">DJCJ</field>
<field name="scrap_location">true</field>
<field name="active">true</field>
<field name="company_id" ref="base.main_company"/>
</record>
<record id="after_assembly_picking_in" model="stock.picking.type"> <record id="after_assembly_picking_in" model="stock.picking.type">
<field name="name">刀具组装入库</field> <field name="name">刀具组装入库</field>

View File

@@ -1,11 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<data> <data>
<record id="mrp.product_template_action" model="ir.actions.act_window">
<field name="context">
{"search_default_categ_id":1,"search_default_consumable": 1, 'default_detailed_type': 'product'}
</field>
</record>
<record model="ir.ui.view" id="view_sale_product_template_form_inherit_sf"> <record model="ir.ui.view" id="view_sale_product_template_form_inherit_sf">
<field name="name">product.template.form.inherit.sf</field> <field name="name">product.template.form.inherit.sf</field>
<field name="model">product.template</field> <field name="model">product.template</field>
@@ -93,8 +88,7 @@
</div> </div>
<field name="model_volume" string="体积[mm³]"/> <field name="model_volume" string="体积[mm³]"/>
<field name="product_model_type_id" string="模型类型"/> <field name="product_model_type_id" string="模型类型"/>
<field name="model_processing_panel" placeholder="例如R,U" string="加工面板" <field name="model_processing_panel" placeholder="例如R,U" string="加工面板"/>
readonly="1"/>
<field name="model_machining_precision"/> <field name="model_machining_precision"/>
<field name="model_process_parameters_ids" string="表面工艺参数" <field name="model_process_parameters_ids" string="表面工艺参数"
widget="many2many_tags" widget="many2many_tags"
@@ -109,11 +103,11 @@
'刀具')], 'required': True} '刀具')], 'required': True}
</attribute> </attribute>
</xpath> </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)]}-->
<!-- </attribute>--> <!-- </attribute>-->
<!-- </xpath>--> <!-- </xpath>-->
</field> </field>
</record> </record>
@@ -311,7 +305,7 @@
<field name="cutting_tool_blade_type" <field name="cutting_tool_blade_type"
attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_coarse_medium_fine" string="粗/中/精" placeholder="请选择" <field name="cutting_tool_coarse_medium_fine" string="粗/中/精" placeholder="请选择"
attrs="{'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))],'readonly': [('id', '!=', False)]}"/> attrs="{'required': [('cutting_tool_type','=','整体式刀具')],'invisible': [('cutting_tool_type', 'not in', ('整体式刀具','刀片'))],'readonly': [('id', '!=', False)]}"/>
<!--整体式刀具--> <!--整体式刀具-->
<field name="cutting_tool_shank_diameter" string="柄部直径(mm)" class="diameter" <field name="cutting_tool_shank_diameter" string="柄部直径(mm)" class="diameter"
attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/>

View File

@@ -1,3 +0,0 @@
# -*- coding: utf-8 -*-
from . import models

View File

@@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': '机企猫智能工厂 员工管理',
'version': '1.0',
'summary': '智能工厂员工模块',
'sequence': 1,
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['hr'],
'data': [
'views/hr_employee.xml',
'views/res_config_settings_views.xml',
'data/cron_data.xml',
],
'demo': [
],
'qweb': [
],
'license': 'LGPL-3',
'installable': True,
'application': False,
'auto_install': False,
}

View File

@@ -1,15 +0,0 @@
<odoo>
<data noupdate="1">
<record model="ir.cron" id="ir_cron_employee_info_sync">
<field name="name">员工企微id同步</field>
<field name="model_id" ref="hr.model_hr_employee"/>
<field name="state">code</field>
<field name="code">model._employee_info_sync()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
</record>
</data>
</odoo>

View File

@@ -1,4 +0,0 @@
# -*- coding: utf-8 -*-
from . import hr_employee
from . import res_config_setting

View File

@@ -1,26 +0,0 @@
import logging
import requests
from odoo import models, fields, api, _
_logger = logging.getLogger(__name__)
class JkmPracticeEmployee(models.Model):
_inherit = 'hr.employee'
_description = '员工信息'
we_id = fields.Char(string='企微ID', index=True)
def _employee_info_sync(self):
url = '/api/get/organization'
config = self.env['res.config.settings'].get_values()
ret = requests.post((config['ims_url'] + url), json={}, data={})
result = ret.json()['result']
if result['code'] == 200:
if result['employee_list']:
for employee_info in result['employee_list']:
if employee_info['work_email']:
self.sudo().search([('work_email', '=', employee_info['work_email'])]).write(
{'we_id': employee_info['we_id']})
else:
logging.info('_employee_info_sync error:%s' % result['message'])

View File

@@ -1,30 +0,0 @@
# -*- coding: utf-8 -*-
import logging
from odoo import api, fields, models
_logger = logging.getLogger(__name__)
class ResIMSConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
ims_url = fields.Char('综合管理系统访问地址')
@api.model
def get_values(self):
"""
重载获取参数的方法,参数都存在系统参数中
:return:
"""
values = super(ResIMSConfigSettings, self).get_values()
config = self.env['ir.config_parameter'].sudo()
ims_url = config.get_param('ims_url', default='')
values.update(
ims_url=ims_url,
)
return values
def set_values(self):
super(ResIMSConfigSettings, self).set_values()
ir_config = self.env['ir.config_parameter'].sudo()
ir_config.set_param("ims_url", self.ims_url or "")

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="view_form_employee_extend" model="ir.ui.view">
<field name="name">employee_form</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_form"/>
<field name="arch" type="xml">
<xpath expr="//group//field[@name='work_email']" position="attributes">
<attribute name="required">1</attribute>
</xpath>
<xpath expr="//page[@name='public']" position='after'>
<page string="企业微信">
<group col="2">
<group>
<field name="we_id"/>
</group>
</group>
</page>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="res_config_settings_finance_view_form_extend" model="ir.ui.view">
<field name="name">res.config.settings.finance.view.form.extend</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[hasclass('app_settings_block')]/div" position="before">
<div>
<h2>综合管理系统接口配置</h2>
<div class="row mt16 o_settings_container" id="jd_api">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="ims_url"/>
<field name="ims_url"/>
</div>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -1,3 +1,2 @@
from . import models from . import models
from . import wizard from . import wizard
from . import controllers

View File

@@ -30,7 +30,6 @@
'views/machine_info_present.xml', 'views/machine_info_present.xml',
'views/delivery_record.xml', 'views/delivery_record.xml',
'views/res_config_settings_views.xml', 'views/res_config_settings_views.xml',
'views/maintenance_views.xml',
], ],
'assets': { 'assets': {

View File

@@ -1 +0,0 @@
from . import controllers

File diff suppressed because it is too large Load Diff

View File

@@ -2,4 +2,3 @@ from . import ftp_client
from . import ftp_operate from . import ftp_operate
from . import py2opcua from . import py2opcua
from . import res_config_setting from . import res_config_setting
from . import mrp_workorder

View File

@@ -121,189 +121,130 @@ class Machine_ftp(models.Model):
""" """
_inherit = 'maintenance.equipment' _inherit = 'maintenance.equipment'
# 机床首次上线时间(默认取值2024年08月01日零点)
def _get_default_online_time(self):
return datetime(2024, 1, 1, 0, 0, 0)
first_online_time = fields.Datetime(string='首次上线时间', default=_get_default_online_time)
# workorder_ids = fields.One2many('mrp.workorder', 'machine_tool_id', string='工单') # workorder_ids = fields.One2many('mrp.workorder', 'machine_tool_id', string='工单')
# # 机床配置项目 # 机床配置项目
# # ftp相关 # ftp相关
# ftp_num = fields.Char('ftp账号') ftp_num = fields.Char('ftp账号')
# ftp_pwd = fields.Char('ftp密码') ftp_pwd = fields.Char('ftp密码')
# ftp_host = fields.Char('ftp地址') ftp_host = fields.Char('ftp地址')
# ftp_port = fields.Integer('ftp端口') ftp_port = fields.Integer('ftp端口')
# ftp_remote_path = fields.Char('机床ftp路径') ftp_remote_path = fields.Char('机床ftp路径')
# # 补偿值写入相关 # 补偿值写入相关
# x_compensation_node = fields.Char('x补偿值节点') x_compensation_node = fields.Char('x补偿值节点')
# y_compensation_node = fields.Char('y补偿值节点') y_compensation_node = fields.Char('y补偿值节点')
# # 数采配置相关 # 数采配置相关
# machine_ip = fields.Char('机床IP') machine_ip = fields.Char('机床IP')
# machine_signed = fields.Char('机床刷新间隔') machine_signed = fields.Char('机床刷新间隔')
# machine_status = fields.Char('机床在线状态') machine_status = fields.Char('机床在线状态')
# machine_cnc_type = fields.Char('机床CNC型号') machine_cnc_type = fields.Char('机床CNC型号')
# machine_axis_count = fields.Char('机床轴总数') machine_axis_count = fields.Char('机床轴总数')
# machine_run_status = fields.Char('机床运行状态') machine_run_status = fields.Char('机床运行状态')
# machine_emg_status = fields.Char('机床急停状态') machine_emg_status = fields.Char('机床急停状态')
# machine_cut_status = fields.Char('机床当前切削状态') machine_cut_status = fields.Char('机床当前切削状态')
# machine_mode = fields.Char('机床当前操作模式') machine_mode = fields.Char('机床当前操作模式')
# machine_spindle_load = fields.Char('机床主轴负载') machine_spindle_load = fields.Char('机床主轴负载')
# machine_x_mach = fields.Char('机床X轴机械坐标') machine_x_mach = fields.Char('机床X轴机械坐标')
# machine_x_abs_mach = fields.Char('机床X轴当前位置') machine_x_abs_mach = fields.Char('机床X轴当前位置')
# machine_x_rel_mach = fields.Char('机床X轴相对工件坐标') machine_x_rel_mach = fields.Char('机床X轴相对工件坐标')
# machine_x_dis_mach = fields.Char('机床X轴目标距离') machine_x_dis_mach = fields.Char('机床X轴目标距离')
# machine_x_axis_load = fields.Char('机床X轴伺服轴负载') machine_x_axis_load = fields.Char('机床X轴伺服轴负载')
# machine_y_mach = fields.Char('机床Y轴机械坐标') machine_y_mach = fields.Char('机床Y轴机械坐标')
# machine_y_abs_mach = fields.Char('机床Y轴当前位置') machine_y_abs_mach = fields.Char('机床Y轴当前位置')
# machine_y_rel_mach = fields.Char('机床Y轴相对工件坐标') machine_y_rel_mach = fields.Char('机床Y轴相对工件坐标')
# machine_y_dis_mach = fields.Char('机床Y轴目标距离') machine_y_dis_mach = fields.Char('机床Y轴目标距离')
# machine_y_axis_load = fields.Char('机床Y轴伺服轴负载') machine_y_axis_load = fields.Char('机床Y轴伺服轴负载')
# machine_z_mach = fields.Char('机床Z轴机械坐标') machine_z_mach = fields.Char('机床Z轴机械坐标')
# machine_z_abs_mach = fields.Char('机床Z轴当前位置') machine_z_abs_mach = fields.Char('机床Z轴当前位置')
# machine_z_rel_mach = fields.Char('机床Z轴相对工件坐标') machine_z_rel_mach = fields.Char('机床Z轴相对工件坐标')
# machine_z_dis_mach = fields.Char('机床Z轴目标距离') machine_z_dis_mach = fields.Char('机床Z轴目标距离')
# machine_z_axis_load = fields.Char('机床Z轴伺服轴负载') machine_z_axis_load = fields.Char('机床Z轴伺服轴负载')
# machine_tool_num = fields.Char('机床当前刀位号') machine_tool_num = fields.Char('机床当前刀位号')
# machine_program = fields.Char('机床主程序名称') machine_program = fields.Char('机床主程序名称')
# machine_current_prg = fields.Char('机床当前执行指令') machine_current_prg = fields.Char('机床当前执行指令')
# machine_prg_seq = fields.Char('机床当前执行语句号') machine_prg_seq = fields.Char('机床当前执行语句号')
# machine_spindle_speed_set = fields.Char('机床设定主轴速度') machine_spindle_speed_set = fields.Char('机床设定主轴速度')
# machine_act_spindle_speed = fields.Char('机床实际主轴转速') machine_act_spindle_speed = fields.Char('机床实际主轴转速')
# machine_feed_speed_set = fields.Char('机床设定进给速度') machine_feed_speed_set = fields.Char('机床设定进给速度')
# machine_act_feed_speed = fields.Char('机床实际进给速度') machine_act_feed_speed = fields.Char('机床实际进给速度')
# machine_spindle_feed = fields.Char('机床主轴倍率') machine_spindle_feed = fields.Char('机床主轴倍率')
# machine_feed_rate = fields.Char('机床进给倍率') machine_feed_rate = fields.Char('机床进给倍率')
# machine_rapid_feed = fields.Char('机床快速移动倍率') machine_rapid_feed = fields.Char('机床快速移动倍率')
# machine_run_time = fields.Char('机床运行时间') machine_run_time = fields.Char('机床运行时间')
# machine_cut_time = fields.Char('机床切削时间') machine_cut_time = fields.Char('机床切削时间')
# machine_keep_alive_time = fields.Char('机床上电时间') machine_keep_alive_time = fields.Char('机床上电时间')
# machine_circle_time = fields.Char('机床循环时间') machine_circle_time = fields.Char('机床循环时间')
# machine_product_counts = fields.Char('机床加工件数') machine_product_counts = fields.Char('机床加工件数')
# machine_system_date = fields.Char('机床系统日期') machine_system_date = fields.Char('机床系统日期')
# machine_system_time = fields.Char('机床系统时间') machine_system_time = fields.Char('机床系统时间')
# machine_alarm_msg = fields.Char('机床系统报警') machine_alarm_msg = fields.Char('机床系统报警')
# # 刀位配置 # 刀位配置
# tool_num1 = fields.Char('刀位1') tool_num1 = fields.Char('刀位1')
# tool_num2 = fields.Char('刀位2') tool_num2 = fields.Char('刀位2')
# tool_num3 = fields.Char('刀位3') tool_num3 = fields.Char('刀位3')
# tool_num4 = fields.Char('刀位4') tool_num4 = fields.Char('刀位4')
# tool_num5 = fields.Char('刀位5') tool_num5 = fields.Char('刀位5')
# tool_num6 = fields.Char('刀位6') tool_num6 = fields.Char('刀位6')
# tool_num7 = fields.Char('刀位7') tool_num7 = fields.Char('刀位7')
# tool_num8 = fields.Char('刀位8') tool_num8 = fields.Char('刀位8')
# tool_num9 = fields.Char('刀位9') tool_num9 = fields.Char('刀位9')
# tool_num10 = fields.Char('刀位10') tool_num10 = fields.Char('刀位10')
# tool_num11 = fields.Char('刀位11') tool_num11 = fields.Char('刀位11')
# tool_num12 = fields.Char('刀位12') tool_num12 = fields.Char('刀位12')
# tool_num13 = fields.Char('刀位13') tool_num13 = fields.Char('刀位13')
# tool_num14 = fields.Char('刀位14') tool_num14 = fields.Char('刀位14')
# tool_num15 = fields.Char('刀位15') tool_num15 = fields.Char('刀位15')
# tool_num16 = fields.Char('刀位16') tool_num16 = fields.Char('刀位16')
# tool_num17 = fields.Char('刀位17') tool_num17 = fields.Char('刀位17')
# tool_num18 = fields.Char('刀位18') tool_num18 = fields.Char('刀位18')
# tool_num19 = fields.Char('刀位19') tool_num19 = fields.Char('刀位19')
# tool_num20 = fields.Char('刀位20') tool_num20 = fields.Char('刀位20')
# tool_num21 = fields.Char('刀位21') tool_num21 = fields.Char('刀位21')
# tool_num22 = fields.Char('刀位22') tool_num22 = fields.Char('刀位22')
# tool_num23 = fields.Char('刀位23') tool_num23 = fields.Char('刀位23')
# tool_num24 = fields.Char('刀位24') tool_num24 = fields.Char('刀位24')
# 机床采集项目 # 机床采集项目
timestamp = fields.Datetime('时间戳', readonly=True) timestamp = fields.Datetime('时间戳', readonly=True)
status = fields.Boolean('机床在线状态', readonly=True) signed = fields.Integer('刷新间隔', readonly=True)
# run_status = fields.Selection([('0', '空闲中'), ('1', '加工中'), ('2', '加工中'), ('3', '加工中')], string='机床运行状态', status = fields.Boolean('在线状态', readonly=True)
# readonly=True, default='0') time_on = fields.Char('总在线时长', readonly=True)
run_status = fields.Char('机床运行状态', readonly=True) time_on_now = fields.Char('本次在线时长', readonly=True)
run_time = fields.Char('机床累计运行时长', readonly=True) tool_num = fields.Integer('当前刀具', readonly=True)
# 机床系统日期 program = fields.Char('当前程序', readonly=True)
system_date = fields.Char('机床系统日期', readonly=True) run_status = fields.Selection([('0', '空闲中'), ('1', '加工中'), ('2', '加工中'), ('3', '加工中')], string='运行状态',
# 机床系统时间 readonly=True, default='0')
system_time = fields.Char('机床系统时间', readonly=True) run_time = fields.Char('总运行时长', readonly=True)
cut_time = fields.Char('机床累计切削时', readonly=True) cut_time = fields.Char('切削时', readonly=True)
# cut_status = fields.Selection([('0', '未切削'), ('1', '切削中'), ('2', '切削中'), ('3', '切削中')], string='机床当前切削状态', cut_status = fields.Selection([('0', '未切削'), ('1', '切削中'), ('2', '切削中'), ('3', '切削中')], string='切削状态',
# readonly=True, default='0') readonly=True, default='0')
cut_status = fields.Char('机床当前切削状态', readonly=True) spindle_speed = fields.Char('主轴转速', readonly=True)
# 当前程序名
program = fields.Char('机床当前程序', readonly=True)
# 当前刀具号
tool_num = fields.Integer('机床当前刀具号', readonly=True)
# 机床通电开机时间, 机床加工件数, 机床当前操作模式, 开始加工时间, 结束加工时间, 加工程序开始时间, 加工程序结束时间, 待机开始时间,
# 待机结束时间, 机床离线开始时间, 机床离线结束时间, 机床急停状态, 机床主程序名称, 程序运行的状态, 机床当前执行指令, 机床当前执行语句号
# 机床X轴当前位置, 机床Y轴当前位置, 机床Z轴当前位置
machine_power_on_time = fields.Char('机床通电开机时间', readonly=True)
product_counts = fields.Char('机床加工件数', readonly=True)
mode = fields.Char('机床当前操作模式', readonly=True)
start_time = fields.Char('开始加工时间', readonly=True)
end_time = fields.Char('结束加工时间', readonly=True)
program_start_time = fields.Char('加工程序开始时间', readonly=True)
program_end_time = fields.Char('加工程序结束时间', readonly=True)
standby_start_time = fields.Char('待机开始时间', readonly=True)
standby_end_time = fields.Char('待机结束时间', readonly=True)
offline_start_time = fields.Char('机床离线开始时间', readonly=True)
offline_end_time = fields.Char('机床离线结束时间', readonly=True)
emg_status = fields.Char('机床急停状态', readonly=True)
program_name = fields.Char('机床主程序名称', readonly=True)
program_status = fields.Char('程序运行状态', readonly=True)
current_program = fields.Char('机床当前执行指令', readonly=True)
current_program_seq = fields.Char('机床当前执行语句号', readonly=True)
x_abs_pos = fields.Char('机床X轴当前位置(mm)', readonly=True)
y_abs_pos = fields.Char('机床Y轴当前位置(mm)', readonly=True)
z_abs_pos = fields.Char('机床Z轴当前位置(mm)', readonly=True)
# 机床设定进给速度, 机床实际进给速度, 机床设定主轴转速, 机床实际主轴转速, 机床主轴负载, 机床X轴伺服轴负载, 机床Y轴伺服轴负载 tool_num_process_time1 = fields.Char('刀位1', readonly=True, default='0')
# 机床Z轴伺服轴负载, 机床快速移动倍率, 机床进给倍率, 机床X轴机械坐标, 机床Y轴机械坐标, 机床Z轴机械坐标, 机床X轴相对工件坐标 tool_num_process_time2 = fields.Char('刀位2', readonly=True, default='0')
# 机床Y轴相对工件坐标, 机床Z轴相对工件坐标, 机床X轴目标距离, 机床Y轴目标距离, 机床Z轴目标距离 tool_num_process_time3 = fields.Char('刀位3', readonly=True, default='0')
feed_speed_set = fields.Char('机床设定进给速度(mm/min)', readonly=True) tool_num_process_time4 = fields.Char('刀位4', readonly=True, default='0')
act_feed_speed = fields.Char('机床实际进给速度(mm/min)', readonly=True) tool_num_process_time5 = fields.Char('刀位5', readonly=True, default='0')
spindle_speed_set = fields.Char('机床设定主轴转速(r/min)', readonly=True) tool_num_process_time6 = fields.Char('刀位6', readonly=True, default='0')
act_spindle_speed = fields.Char('机床实际主轴转速(r/min)', readonly=True) tool_num_process_time7 = fields.Char('刀位7', readonly=True, default='0')
spindle_load = fields.Char('机床主轴负载(%)', readonly=True) tool_num_process_time8 = fields.Char('刀位8', readonly=True, default='0')
x_axis_load = fields.Char('机床X轴伺服轴负载(%)', readonly=True) tool_num_process_time9 = fields.Char('刀位9', readonly=True, default='0')
y_axis_load = fields.Char('机床Y轴伺服轴负载(%)', readonly=True) tool_num_process_time10 = fields.Char('刀位10', readonly=True, default='0')
z_axis_load = fields.Char('机床Z轴伺服轴负载(%)', readonly=True) tool_num_process_time11 = fields.Char('刀位11', readonly=True, default='0')
rapid_feed = fields.Char('机床快速移动倍率(%)', readonly=True) tool_num_process_time12 = fields.Char('刀位12', readonly=True, default='0')
feed_rate = fields.Char('机床进给倍率(%)', readonly=True) tool_num_process_time13 = fields.Char('刀位13', readonly=True, default='0')
x_mach_coord = fields.Char('机床X轴机械坐标(mm)', readonly=True) tool_num_process_time14 = fields.Char('刀位14', readonly=True, default='0')
y_mach_coord = fields.Char('机床Y轴机械坐标(mm)', readonly=True) tool_num_process_time15 = fields.Char('刀位15', readonly=True, default='0')
z_mach_coord = fields.Char('机床Z轴机械坐标(mm)', readonly=True) tool_num_process_time16 = fields.Char('刀位16', readonly=True, default='0')
x_rel_coord = fields.Char('机床X轴相对工件坐标(mm)', readonly=True) tool_num_process_time17 = fields.Char('刀位17', readonly=True, default='0')
y_rel_coord = fields.Char('机床Y轴相对工件坐标(mm)', readonly=True) tool_num_process_time18 = fields.Char('刀位18', readonly=True, default='0')
z_rel_coord = fields.Char('机床Z轴相对工件坐标(mm)', readonly=True) tool_num_process_time19 = fields.Char('刀位19', readonly=True, default='0')
x_dis_coord = fields.Char('机床X轴目标距离(mm)', readonly=True) tool_num_process_time20 = fields.Char('刀位20', readonly=True, default='0')
y_dis_coord = fields.Char('机床Y轴目标距离(mm)', readonly=True) tool_num_process_time21 = fields.Char('刀位21', readonly=True, default='0')
z_dis_coord = fields.Char('机床Z轴目标距离(mm)', readonly=True) tool_num_process_time22 = fields.Char('刀位22', readonly=True, default='0')
tool_num_process_time23 = fields.Char('刀位23', readonly=True, default='0')
# 故障报警时间, 故障报警信息, 故障消除时间(复原时间) tool_num_process_time24 = fields.Char('刀位24', readonly=True, default='0')
alarm_time = fields.Char('故障报警时间', readonly=True)
alarm_msg = fields.Char('故障报警信息', readonly=True)
clear_time = fields.Char('故障消除时间(复原时间)', readonly=True)
# # 开动率
run_rate = fields.Char('开动率', readonly=True)
# 同步CNC设备到oee
def sync_oee(self):
"""
同步CNC设备到oee
:return:
"""
for record in self:
record.ensure_one()
cnc_oee_dict = {
'equipment_id': record.id,
'type_id': record.type_id.id,
'machine_tool_picture': record.machine_tool_picture,
'equipment_code': record.code,
'function_type': record.function_type,
}
if self.env['maintenance.equipment.oee.logs'].search([('equipment_id', '=', record.id)]):
self.env['maintenance.equipment.oee.logs'].write(cnc_oee_dict)
else:
self.env['maintenance.equipment.oee.logs'].create(cnc_oee_dict)
class WorkCenterBarcode(models.Model): class WorkCenterBarcode(models.Model):
@@ -318,59 +259,39 @@ class WorkCenterBarcode(models.Model):
button_compensation_state = fields.Boolean(string='是否已经补偿', readonly=True) button_compensation_state = fields.Boolean(string='是否已经补偿', readonly=True)
button_up_all_state = fields.Boolean(string='是否已经全部下发', readonly=True) button_up_all_state = fields.Boolean(string='是否已经全部下发', readonly=True)
machine_tool_id = fields.Many2one('sf.machine_tool.type', string='机床') machine_tool_id = fields.Many2one('sf.machine_tool.type', string='机床')
# machine_tool_name = fields.Char(string='机床名称', default='未知机床', compute='_run_info', readonly=True) machine_tool_name = fields.Char(string='机床名称', default='未知机床', compute='_run_info', readonly=True)
# machine_tool_type_id = fields.Char(string='机床型号', default='未知型号', compute='_run_info', readonly=True) machine_tool_type_id = fields.Char(string='机床型号', default='未知型号', compute='_run_info', readonly=True)
# machine_tool_status = fields.Boolean(string='在线状态', compute='_run_info', readonly=True) machine_tool_status = fields.Boolean(string='在线状态', compute='_run_info', readonly=True)
# machine_tool_run_status = fields.Selection([('0', '关机中'), ('1', '加工中'), ('2', '加工中'), ('3', '加工中')],
# string='运行状态', compute='_run_info', readonly=True, default='0')
# machine_tool_timestamp = fields.Datetime('时间戳', compute='_run_info', readonly=True)
# machine_tool_time_on = fields.Char('总在线时长', compute='_run_info', readonly=True)
# machine_tool_time_on_now = fields.Char('本次在线时长', compute='_run_info', readonly=True)
# machine_tool_tool_num = fields.Integer('当前刀具', compute='_run_info', readonly=True)
# machine_tool_program = fields.Char('当前程序', compute='_run_info', readonly=True)
# machine_tool_machine_ip = fields.Char('机床IP', compute='_run_info', readonly=True)
# machine_tool_cut_status = fields.Selection([('0', '未切削'), ('1', '切削中'), ('2', '切削中'), ('3', '切削中')],
# string='切削状态', compute='_run_info', readonly=True, default='0')
# machine_tool_compensation_value_x = fields.Char('x补偿值', compute='_run_info', readonly=True)
# machine_tool_compensation_value_y = fields.Char('y补偿值', compute='_run_info', readonly=True)
machine_tool_name = fields.Char(string='机床名称', default='未知机床', readonly=True)
machine_tool_type_id = fields.Char(string='机床型号', default='未知型号', readonly=True)
machine_tool_status = fields.Boolean(string='在线状态', readonly=True)
machine_tool_run_status = fields.Selection([('0', '关机中'), ('1', '加工中'), ('2', '加工中'), ('3', '加工中')], machine_tool_run_status = fields.Selection([('0', '关机中'), ('1', '加工中'), ('2', '加工中'), ('3', '加工中')],
string='运行状态', readonly=True, default='0') string='运行状态', compute='_run_info', readonly=True, default='0')
machine_tool_timestamp = fields.Datetime('时间戳', readonly=True) machine_tool_timestamp = fields.Datetime('时间戳', compute='_run_info', readonly=True)
machine_tool_time_on = fields.Char('总在线时长', readonly=True) machine_tool_time_on = fields.Char('总在线时长', compute='_run_info', readonly=True)
machine_tool_time_on_now = fields.Char('本次在线时长', readonly=True) machine_tool_time_on_now = fields.Char('本次在线时长', compute='_run_info', readonly=True)
machine_tool_tool_num = fields.Integer('当前刀具', readonly=True) machine_tool_tool_num = fields.Integer('当前刀具', compute='_run_info', readonly=True)
machine_tool_program = fields.Char('当前程序', readonly=True) machine_tool_program = fields.Char('当前程序', compute='_run_info', readonly=True)
machine_tool_machine_ip = fields.Char('机床IP', readonly=True) machine_tool_machine_ip = fields.Char('机床IP', compute='_run_info', readonly=True)
machine_tool_cut_status = fields.Selection([('0', '未切削'), ('1', '切削中'), ('2', '切削中'), ('3', '切削中')], machine_tool_cut_status = fields.Selection([('0', '未切削'), ('1', '切削中'), ('2', '切削中'), ('3', '切削中')],
string='切削状态', readonly=True, default='0') string='切削状态', compute='_run_info', readonly=True, default='0')
machine_tool_compensation_value_x = fields.Char('x补偿值', readonly=True) machine_tool_compensation_value_x = fields.Char('x补偿值', compute='_run_info', readonly=True)
machine_tool_compensation_value_y = fields.Char('y补偿值', readonly=True) machine_tool_compensation_value_y = fields.Char('y补偿值', compute='_run_info', readonly=True)
# 工单状态
delivery_records = fields.One2many('delivery.record', 'workorder_id', string="下发记录") delivery_records = fields.One2many('delivery.record', 'workorder_id', string="下发记录")
@api.depends('equipment_id.timestamp') @api.depends('equipment_id.timestamp')
def _run_info(self): def _run_info(self):
# self.machine_tool_name = '1号机床' # self.machine_tool_name = '1号机床'
# self.machine_tool_name = self.equipment_id.name self.machine_tool_name = self.equipment_id.name
# self.machine_tool_type_id = self.equipment_id.type_id.name self.machine_tool_type_id = self.equipment_id.type_id.name
# self.machine_tool_status = self.equipment_id.status self.machine_tool_status = self.equipment_id.status
# self.machine_tool_run_status = self.equipment_id.run_status self.machine_tool_run_status = self.equipment_id.run_status
# self.machine_tool_timestamp = self.equipment_id.timestamp self.machine_tool_timestamp = self.equipment_id.timestamp
# self.machine_tool_time_on = self.equipment_id.time_on self.machine_tool_time_on = self.equipment_id.time_on
# self.machine_tool_time_on_now = self.equipment_id.time_on_now self.machine_tool_time_on_now = self.equipment_id.time_on_now
# self.machine_tool_tool_num = self.equipment_id.tool_num self.machine_tool_tool_num = self.equipment_id.tool_num
# self.machine_tool_program = self.equipment_id.program self.machine_tool_program = self.equipment_id.program
# self.machine_tool_machine_ip = self.equipment_id.machine_ip self.machine_tool_machine_ip = self.equipment_id.machine_ip
# self.machine_tool_cut_status = self.equipment_id.cut_status self.machine_tool_cut_status = self.equipment_id.cut_status
# self.machine_tool_compensation_value_x = self.compensation_value_x self.machine_tool_compensation_value_x = self.compensation_value_x
# self.machine_tool_compensation_value_y = self.compensation_value_y self.machine_tool_compensation_value_y = self.compensation_value_y
pass
def compensation(self): def compensation(self):

View File

@@ -1,38 +0,0 @@
import re
from odoo import fields, models, api
class ResMrpWorkOrder(models.Model):
_inherit = 'mrp.workorder'
mixed_search_field = fields.Char(string='坯料产品名称/RFID')
@api.model
def web_read_group(self, domain, fields, groupby, limit=None, offset=0, orderby=False,
lazy=True, expand=False, expand_limit=None, expand_orderby=False):
domain = domain or []
for index, item in enumerate(domain):
if isinstance(item, list):
if item[0] == 'mixed_search_field':
if self._is_rfid_code(item[2]):
domain[index] = ['rfid_code', item[1], item[2]]
else:
domain[index] = ['product_tmpl_name', item[1], item[2]]
return super(ResMrpWorkOrder, self).web_read_group(domain, fields, groupby, limit=limit, offset=offset, orderby=orderby,
lazy=lazy, expand=expand, expand_limit=expand_limit, expand_orderby=expand_orderby)
def _is_rfid_code(self, tag):
"""
判断是否是rfid_code
"""
# 基于长度判断假设RFID标签长度为10到16个字符
if not 10 <= len(tag) <= 16:
return False
# 基于字符集判断(仅包含数字和字母)
if not re.match("^[0-9]*$", tag):
return False
return True

View File

@@ -8,15 +8,11 @@ _logger = logging.getLogger(__name__)
class ResBFMConfigSettings(models.TransientModel): class ResBFMConfigSettings(models.TransientModel):
_inherit = 'res.config.settings' _inherit = 'res.config.settings'
# bfm_url = fields.Selection( bfm_url = fields.Selection(
# [("https://bfm.cs.jikimo.com", "开发环境(https://bfm.cs.jikimo.com)"), [("https://bfm.cs.jikimo.com", "开发环境(https://bfm.cs.jikimo.com)"),
# ("https://bfm.t.jikimo.com", "测试环境(https://bfm.t.jikimo.com)"), ("https://bfm.t.jikimo.com", "测试环境(https://bfm.t.jikimo.com)"),
# ("https://bfm.r.jikimo.com", "预发布环境(https://bfm.r.jikimo.com)"), # ("正式环境", "https://bfm.jikimo.com")], string='bfm环境', store=True)
# # ("正式环境", "https://bfm.jikimo.com")], string='bfm环境', store=True) ("https://bfm.jikimo.com", "正式环境(https://bfm.jikimo.com)")], string='bfm环境', store=True)
# ("https://bfm.jikimo.com", "正式环境(https://bfm.jikimo.com)")], string='bfm环境', store=True)
bfm_url_new = fields.Char('业务平台环境路径', placeholder='请输入当前对应的业务平台环境路径')
get_check_file_path = fields.Char('获取检查文件路径', default='')
@api.model @api.model
def get_values(self): def get_values(self):
@@ -26,17 +22,14 @@ class ResBFMConfigSettings(models.TransientModel):
""" """
values = super(ResBFMConfigSettings, self).get_values() values = super(ResBFMConfigSettings, self).get_values()
config = self.env['ir.config_parameter'].sudo() config = self.env['ir.config_parameter'].sudo()
bfm_url_new = config.get_param('bfm_url_new', default='') bfm_url = config.get_param('bfm_url', default='')
get_check_file_path = config.get_param('get_check_file_path', default='')
values.update( values.update(
bfm_url_new=bfm_url_new, bfm_url=bfm_url,
get_check_file_path=get_check_file_path
) )
return values return values
def set_values(self): def set_values(self):
super(ResBFMConfigSettings, self).set_values() super(ResBFMConfigSettings, self).set_values()
ir_config = self.env['ir.config_parameter'].sudo() ir_config = self.env['ir.config_parameter'].sudo()
ir_config.set_param("bfm_url_new", self.bfm_url_new or "") ir_config.set_param("bfm_url", self.bfm_url or "")
ir_config.set_param("get_check_file_path", self.get_check_file_path or "")

View File

@@ -25,11 +25,6 @@
<filter string="人工编程" name="manual_quotation" domain="[('manual_quotation', '=', True)]"/> <filter string="人工编程" name="manual_quotation" domain="[('manual_quotation', '=', True)]"/>
<filter string="自动编程" name="no_manual_quotation" domain="[('manual_quotation', '=', False)]"/> <filter string="自动编程" name="no_manual_quotation" domain="[('manual_quotation', '=', False)]"/>
</xpath> </xpath>
<xpath expr="//field[@name='production_id']" position="before">
<field name="mixed_search_field"/>
<field name="product_tmpl_name"/>
<field name="rfid_code"/>
</xpath>
</field> </field>
</record> </record>
</odoo> </odoo>

View File

@@ -5,46 +5,39 @@
<field name="model">mrp.workorder</field> <field name="model">mrp.workorder</field>
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/> <field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<!-- <xpath expr="//header" position="inside">&ndash;&gt;--> <xpath expr="//header" position="inside">
<!-- <button string="程序下载" name="cnc_file_download" type="object" class="oe_highlight" attrs='{"invisible": ["|",--> <button string="程序下载" name="cnc_file_download" type="object" class="oe_highlight" attrs='{"invisible": ["|",
<!-- ("user_permissions","=",False),("routing_type","!=","CNC加工")]}'/>--> ("user_permissions","=",False),("routing_type","!=","CNC加工")]}'/>
<!-- </xpath>-->
<xpath expr="//page//field[@name='cnc_ids']" position="before">
<group>
<group>
<field name="compensation_value_x"/>
<field name="compensation_value_y"/>
</group>
<div>
<div>
<!-- <field name="button_compensation_state" attrs='{"invisible": ["|",-->
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
<!-- <span>&#32;</span>-->
<!-- <button name="button_send_program_again" type="object" string="重新下发NC程序"-->
<!-- class="btn-primary"-->
<!-- confirm="是否确认重新下发NC程序"-->
<!-- groups="sf_base.group_sf_order_user,sf_base.group_sf_equipment_user"-->
<!-- attrs="{'invisible': ['|', '|', '|',('routing_type','!=','装夹预调'),('state','in',['done', 'cancel',-->
<!-- 'progress']),('processing_drawing','=',False),('is_send_program_again','=',True)]}"/>-->
<!-- <button string="一键补偿" name="compensation" type="object" confirm="是否确认下发补偿"-->
<!-- class="btn-primary" attrs='{"invisible": ["|",-->
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
<!-- <span>&#32;</span>-->
<!-- <button string="一键下发" name="up_all" type="object" style="text-align: right;" confirm="是否确认一键下发"-->
<!-- class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",-->
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
<!-- <span>&#32;</span>-->
<!-- <button string="合并下发" id="action_up_select" name="%(sf_machine_connect.action_up_select)d"-->
<!-- type="action" class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",-->
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
<!-- <span>&#32;</span>-->
<!-- <button string="一键合并下发" name="up_merge_all" type="object" style="text-align: right;" confirm="是否确认一键合并下发"-->
<!-- class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",-->
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
</div>
</div>
</group>
</xpath> </xpath>
<xpath expr="//page//field[@name='cnc_ids']" position="before">
<group>
<group>
<field name="compensation_value_x"/>
<field name="compensation_value_y"/>
</group>
<div>
<div>
<field name="button_compensation_state" attrs='{"invisible": ["|",
("state","!=","progress"),("user_permissions","=",False)]}'/>
<button string="一键补偿" name="compensation" type="object" confirm="是否确认下发补偿"
class="btn-primary" attrs='{"invisible": ["|",
("state","!=","progress"),("user_permissions","=",False)]}'/>
<span>&#32;</span>
<button string="一键下发" name="up_all" type="object" style="text-align: right;" confirm="是否确认一键下发"
class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
("state","!=","progress"),("user_permissions","=",False)]}'/>
<span>&#32;</span>
<button string="合并下发" id="action_up_select" name="%(sf_machine_connect.action_up_select)d"
type="action" class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
("state","!=","progress"),("user_permissions","=",False)]}'/>
<span>&#32;</span>
<button string="一键合并下发" name="up_merge_all" type="object" style="text-align: right;" confirm="是否确认一键合并下发"
class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
("state","!=","progress"),("user_permissions","=",False)]}'/>
</div>
</div>
</group>
</xpath>
</field> </field>
</record> </record>

View File

@@ -9,9 +9,9 @@
<tree> <tree>
<field name="sequence_number"/> <field name="sequence_number"/>
<field name="program_name"/> <field name="program_name"/>
<field name="cnc_id" string="文件"/>
<field name="functional_tool_type_id"/> <field name="functional_tool_type_id"/>
<field name="cutting_tool_name"/> <field name="cutting_tool_name"/>
<field name="tool_state"/>
<field name="cutting_tool_no"/> <field name="cutting_tool_no"/>
<field name="processing_type"/> <field name="processing_type"/>
<field name="margin_x_y"/> <field name="margin_x_y"/>

View File

@@ -19,7 +19,7 @@
<!-- attrs='{"invisible": ["|",("state","!=","progress"), --> <!-- attrs='{"invisible": ["|",("state","!=","progress"), -->
<!-- ("user_permissions","!=",True)]}'/> --> <!-- ("user_permissions","!=",True)]}'/> -->
<!-- <button string="下发" name="up" type="object" class="btn-primary" confirm="是否确认下发此程序" context="{'default_cnc_ids': cnc_ids}"/> --> <!-- <button string="下发" name="up" type="object" class="btn-primary" confirm="是否确认下发此程序" context="{'default_cnc_ids': cnc_ids}"/> -->
<!-- <button string="下发" name="up" type="object" class="btn-primary" confirm="是否确认下发此程序"--> <button string="下发" name="up" type="object" class="btn-primary" confirm="是否确认下发此程序"
context="{'default_sf_cnc_processing_id': id}" attrs='{"invisible": ["|",("state","!=","progress"), context="{'default_sf_cnc_processing_id': id}" attrs='{"invisible": ["|",("state","!=","progress"),
("user_permissions","!=",True)]}'/> ("user_permissions","!=",True)]}'/>
<!-- <button string="下发" name="up" type="object" class="btn-primary" confirm="是否确认下发此程序"--> <!-- <button string="下发" name="up" type="object" class="btn-primary" confirm="是否确认下发此程序"-->

View File

@@ -13,139 +13,294 @@
<page string="机床运行状态" attrs="{'invisible': [('equipment_type', '!=', '机床')]}"> <page string="机床运行状态" attrs="{'invisible': [('equipment_type', '!=', '机床')]}">
<group string='状态监控'> <group string='状态监控'>
<group> <group>
<!-- <field name="timestamp"/> --> <field name="timestamp"/>
<field name="signed"/>
<field name="status"/> <field name="status"/>
<field name="run_status"/> <field name="time_on"/>
<field name="run_time"/> <field name="time_on_now"/>
<field name="system_date"/>
<field name="first_online_time"/>
</group> </group>
<group> <group>
<field name="run_status"/>
<field name="run_time"/>
<field name="cut_status"/> <field name="cut_status"/>
<field name="cut_time"/>
<!-- <field name="cut_time"/> --> <!-- <field name="cut_time"/> -->
<field name="program"/> <field name="program"/>
<field name="tool_num"/> <field name="tool_num"/>
<field name="spindle_speed"/>
</group> </group>
</group> </group>
<!-- <group string='刀位统计'> -->
<!-- <group> -->
<!-- <group> -->
<!-- <field name="tool_num_process_time1"/> -->
<!-- <field name="tool_num_process_time5"/> -->
<!-- <field name="tool_num_process_time9"/> -->
<!-- <field name="tool_num_process_time13"/> -->
<!-- <field name="tool_num_process_time17"/> -->
<!-- <field name="tool_num_process_time21"/> -->
<!-- </group> -->
<!-- <group> -->
<!-- <field name="tool_num_process_time2"/> -->
<!-- <field name="tool_num_process_time6"/> -->
<!-- <field name="tool_num_process_time10"/> -->
<!-- <field name="tool_num_process_time14"/> -->
<!-- <field name="tool_num_process_time18"/> -->
<!-- <field name="tool_num_process_time22"/> -->
<!-- </group> -->
<!-- </group> -->
<!-- <group> -->
<!-- <group> -->
<!-- <field name="tool_num_process_time3"/> -->
<!-- <field name="tool_num_process_time7"/> -->
<!-- <field name="tool_num_process_time11"/> -->
<!-- <field name="tool_num_process_time15"/> -->
<!-- <field name="tool_num_process_time19"/> -->
<!-- <field name="tool_num_process_time23"/> -->
<!-- </group> -->
<!-- <group> -->
<!-- <field name="tool_num_process_time4"/> -->
<!-- <field name="tool_num_process_time8"/> -->
<!-- <field name="tool_num_process_time12"/> -->
<!-- <field name="tool_num_process_time16"/> -->
<!-- <field name="tool_num_process_time20"/> -->
<!-- <field name="tool_num_process_time24"/> -->
<!-- </group> -->
<!-- </group> -->
<!-- </group> -->
<!-- <div class="o_address_format"> -->
<!-- <label for="tool_num_process_time1" string="刀位1"/> -->
<!-- <field name="tool_num_process_time1" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time2" string="刀位2"/> -->
<!-- <field name="tool_num_process_time2" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time3" string="刀位3"/> -->
<!-- <field name="tool_num_process_time3" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time4" string="刀位4"/> -->
<!-- <field name="tool_num_process_time4" class="o_form_label"/> -->
<!-- <div></div> -->
<!-- <label for="tool_num_process_time5" string="刀位5"/> -->
<!-- <field name="tool_num_process_time5" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time6" string="刀位6"/> -->
<!-- <field name="tool_num_process_time6" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time7" string="刀位7"/> -->
<!-- <field name="tool_num_process_time7" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time8" string="刀位8"/> -->
<!-- <field name="tool_num_process_time8" class="o_form_label"/> -->
<!-- <div></div> -->
<!-- <label for="tool_num_process_time9" string="刀位9"/> -->
<!-- <field name="tool_num_process_time9" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time10" string="刀位10"/> -->
<!-- <field name="tool_num_process_time10" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time11" string="刀位11"/> -->
<!-- <field name="tool_num_process_time11" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time12" string="刀位12"/> -->
<!-- <field name="tool_num_process_time12" class="o_form_label"/> -->
<!-- <div></div> -->
<!-- <label for="tool_num_process_time13" string="刀位13"/> -->
<!-- <field name="tool_num_process_time13" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time14" string="刀位14"/> -->
<!-- <field name="tool_num_process_time14" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time15" string="刀位15"/> -->
<!-- <field name="tool_num_process_time15" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time16" string="刀位16"/> -->
<!-- <field name="tool_num_process_time16" class="o_form_label"/> -->
<!-- <div></div> -->
<!-- <label for="tool_num_process_time17" string="刀位17"/> -->
<!-- <field name="tool_num_process_time17" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time18" string="刀位18"/> -->
<!-- <field name="tool_num_process_time18" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time19" string="刀位19"/> -->
<!-- <field name="tool_num_process_time19" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time20" string="刀位20"/> -->
<!-- <field name="tool_num_process_time20" class="o_form_label"/> -->
<!-- <div></div> -->
<!-- <label for="tool_num_process_time21" string="刀位21"/> -->
<!-- <field name="tool_num_process_time21" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time22" string="刀位22"/> -->
<!-- <field name="tool_num_process_time22" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time23" string="刀位23"/> -->
<!-- <field name="tool_num_process_time23" class="o_form_label"/> -->
<!-- <span>&amp;nbsp;</span> -->
<!-- <label for="tool_num_process_time24" string="刀位24"/> -->
<!-- <field name="tool_num_process_time24" class="o_form_label"/> -->
<!-- </div> -->
<!-- </group> -->
</page> </page>
<page string="机床运行数据" attrs="{'invisible': [('equipment_type', '!=', '机床')]}"> <page string="机床运行数据" attrs="{'invisible': [('equipment_type', '!=', '机床')]}">
<group string="运行数据"> <!-- <group string="机床配置">--> -->
<group> <group string="ftp相关">
<field name="machine_power_on_time"/> <group>
<field name="product_counts"/> <field name="ftp_num"/>
<field name="mode"/> <field name="ftp_pwd"/>
<field name="start_time"/> <field name="ftp_host"/>
<field name="end_time"/> </group>
<field name="program_start_time"/> <group>
<field name="program_end_time"/> <field name="ftp_port"/>
<field name="standby_start_time"/> <field name="ftp_remote_path"/>
<field name="standby_end_time"/> </group>
<field name="offline_start_time"/>
<field name="offline_end_time"/>
<field name="emg_status"/>
<field name="program_name"/>
<field name="program_status"/>
<field name="current_program"/>
<field name="current_program_seq"/>
<field name="x_abs_pos"/>
<field name="y_abs_pos"/>
<field name="z_abs_pos"/>
</group> </group>
<group> <group string="补偿值相关">
<field name="feed_speed_set"/> <group>
<field name="act_feed_speed"/> <field name="x_compensation_node"/>
<field name="spindle_speed_set"/> </group>
<field name="act_spindle_speed"/> <group>
<field name="spindle_load"/> <field name="y_compensation_node"/>
<field name="x_axis_load"/> </group>
<field name="y_axis_load"/> </group>
<field name="z_axis_load"/> <group string="数采相关">
<field name="rapid_feed"/> <group>
<field name="feed_rate"/> <field name="machine_ip"/>
<field name="x_mach_coord"/> <field name="machine_signed"/>
<field name="y_mach_coord"/> <field name="machine_status"/>
<field name="z_mach_coord"/> <field name="machine_cnc_type"/>
<field name="x_rel_coord"/> <field name="machine_axis_count"/>
<field name="y_rel_coord"/> <field name="machine_run_status"/>
<field name="z_rel_coord"/> <field name="machine_emg_status"/>
<field name="x_dis_coord"/> <field name="machine_cut_status"/>
<field name="y_dis_coord"/> <field name="machine_mode"/>
<field name="z_dis_coord"/> <field name="machine_spindle_load"/>
<field name="machine_x_mach"/>
<field name="machine_x_abs_mach"/>
<field name="machine_x_rel_mach"/>
<field name="machine_x_dis_mach"/>
<field name="machine_x_axis_load"/>
<field name="machine_y_mach"/>
<field name="machine_y_abs_mach"/>
<field name="machine_y_rel_mach"/>
<field name="machine_y_dis_mach"/>
<field name="machine_y_axis_load"/>
<field name="machine_z_mach"/>
<field name="machine_z_abs_mach"/>
</group>
<group>
<field name="machine_z_rel_mach"/>
<field name="machine_z_dis_mach"/>
<field name="machine_z_axis_load"/>
<field name="machine_tool_num"/>
<field name="machine_program"/>
<field name="machine_current_prg"/>
<field name="machine_prg_seq"/>
<field name="machine_spindle_speed_set"/>
<field name="machine_act_spindle_speed"/>
<field name="machine_feed_speed_set"/>
<field name="machine_act_feed_speed"/>
<field name="machine_spindle_feed"/>
<field name="machine_feed_rate"/>
<field name="machine_rapid_feed"/>
<field name="machine_run_time"/>
<field name="machine_cut_time"/>
<field name="machine_keep_alive_time"/>
<field name="machine_circle_time"/>
<field name="machine_product_counts"/>
<field name="machine_system_date"/>
<field name="machine_system_time"/>
<field name="machine_alarm_msg"/>
</group>
</group> </group>
</group>
<!-- <group string="ftp相关"> -->
<!-- <group> -->
<!-- <field name="ftp_num"/> -->
<!-- <field name="ftp_pwd"/> -->
<!-- <field name="ftp_host"/> -->
<!-- </group> --> <!-- </group> -->
<!-- <group> -->
<!-- <field name="ftp_port"/> -->
<!-- <field name="ftp_remote_path"/> -->
<!-- </group> -->
<!-- </group> -->
<!-- <group string="补偿值相关"> -->
<!-- <group> -->
<!-- <field name="x_compensation_node"/> -->
<!-- </group> -->
<!-- <group> -->
<!-- <field name="y_compensation_node"/> -->
<!-- </group> -->
<!-- </group> -->
<!-- <group string="数采相关"> -->
<!-- <group> -->
<!-- <field name="machine_ip"/> -->
<!-- <field name="machine_signed"/> -->
<!-- <field name="machine_status"/> -->
<!-- <field name="machine_cnc_type"/> -->
<!-- <field name="machine_axis_count"/> -->
<!-- <field name="machine_run_status"/> -->
<!-- <field name="machine_emg_status"/> -->
<!-- <field name="machine_cut_status"/> -->
<!-- <field name="machine_mode"/> -->
<!-- <field name="machine_spindle_load"/> -->
<!-- <field name="machine_x_mach"/> -->
<!-- <field name="machine_x_abs_mach"/> -->
<!-- <field name="machine_x_rel_mach"/> -->
<!-- <field name="machine_x_dis_mach"/> -->
<!-- <field name="machine_x_axis_load"/> -->
<!-- <field name="machine_y_mach"/> -->
<!-- <field name="machine_y_abs_mach"/> -->
<!-- <field name="machine_y_rel_mach"/> -->
<!-- <field name="machine_y_dis_mach"/> -->
<!-- <field name="machine_y_axis_load"/> -->
<!-- <field name="machine_z_mach"/> -->
<!-- <field name="machine_z_abs_mach"/> -->
<!-- </group> -->
<!-- <group> -->
<!-- <field name="machine_z_rel_mach"/> -->
<!-- <field name="machine_z_dis_mach"/> -->
<!-- <field name="machine_z_axis_load"/> -->
<!-- <field name="machine_tool_num"/> -->
<!-- <field name="machine_program"/> -->
<!-- <field name="machine_current_prg"/> -->
<!-- <field name="machine_prg_seq"/> -->
<!-- <field name="machine_spindle_speed_set"/> -->
<!-- <field name="machine_act_spindle_speed"/> -->
<!-- <field name="machine_feed_speed_set"/> -->
<!-- <field name="machine_act_feed_speed"/> -->
<!-- <field name="machine_spindle_feed"/> -->
<!-- <field name="machine_feed_rate"/> -->
<!-- <field name="machine_rapid_feed"/> -->
<!-- <field name="machine_run_time"/> -->
<!-- <field name="machine_cut_time"/> -->
<!-- <field name="machine_keep_alive_time"/> -->
<!-- <field name="machine_circle_time"/> -->
<!-- <field name="machine_product_counts"/> -->
<!-- <field name="machine_system_date"/> -->
<!-- <field name="machine_system_time"/> -->
<!-- <field name="machine_alarm_msg"/> -->
<!-- </group> -->
<!-- </group> -->
</page> </page>
<!-- <page string="刀位配置"> -->
<!-- <group string="刀位配置"> -->
<!-- <group> -->
<!-- <group> -->
<!-- <field name="tool_num1"/> -->
<!-- <field name="tool_num5"/> -->
<!-- <field name="tool_num9"/> -->
<!-- <field name="tool_num13"/> -->
<!-- <field name="tool_num17"/> -->
<!-- <field name="tool_num21"/> -->
<!-- </group> -->
<!-- <group> -->
<!-- <field name="tool_num2"/> -->
<!-- <field name="tool_num6"/> -->
<!-- <field name="tool_num10"/> -->
<!-- <field name="tool_num14"/> -->
<!-- <field name="tool_num18"/> -->
<!-- <field name="tool_num22"/> -->
<!-- </group> -->
<!-- </group> -->
<!-- <group> -->
<!-- <group> -->
<!-- <field name="tool_num3"/> -->
<!-- <field name="tool_num7"/> -->
<!-- <field name="tool_num11"/> -->
<!-- <field name="tool_num15"/> -->
<!-- <field name="tool_num19"/> -->
<!-- <field name="tool_num23"/> -->
<!-- </group> -->
<!-- <group> -->
<!-- <field name="tool_num4"/> -->
<!-- <field name="tool_num8"/> -->
<!-- <field name="tool_num12"/> -->
<!-- <field name="tool_num16"/> -->
<!-- <field name="tool_num20"/> -->
<!-- <field name="tool_num24"/> -->
<!-- </group> -->
<!-- </group> -->
<!-- </group> -->
<!-- </page> -->
<!-- </notebook> -->
</xpath> </xpath>
</field> </field>
</record> </record>
<!-- 刀具寿命 -->
<!-- <record id="view_cutting_tool_inherited" model="ir.ui.view"> -->
<!-- <field name="name">sf_cutting_tool_extension</field> -->
<!-- <field name="model">sf.cutting_tool.type</field> -->
<!-- <field name="inherit_id" ref="sf_base.form_sf_machine_tool_type"/> -->
<!-- <field name="arch" type="xml"> -->
<!-- <xpath expr="//form//group" position="after"> -->
<!-- <group string='刀具寿命'> -->
<!-- <group> -->
<!-- <field name="total_cut_time"/> -->
<!-- <field name="tool_position"/> -->
<!-- </group> -->
<!-- <group> -->
<!-- <field name="predict_life_time"/> -->
<!-- </group> -->
<!-- <div> -->
<!-- <div> -->
<!-- <field name='is_connect_tool_position' invisible='1'/> -->
<!-- <button string="绑定刀位" name="tool_connect_machine" type="object" confirm="是否确认绑定此刀位" -->
<!-- class="btn-primary"/> -->
<!-- attrs='{"invisible": [("is_connect_tool_position","!=", -->
<!-- "False")]}' -->
<!-- <span>&#32;</span> -->
<!-- <button string="解绑刀位" name="tool_unconnect_machine" type="object" confirm="是否解绑此刀位" -->
<!-- class="btn-primary"/> -->
<!-- attrs='{"invisible": [("is_connect_tool_position","!=", -->
<!-- "False")]}' -->
<!-- </div> -->
<!-- </div> -->
<!-- </group> -->
<!-- </xpath> -->
<!-- </field> -->
<!-- </record> -->
</odoo> </odoo>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0"?>
<odoo>
<!-- 修改设备列表视图-->
<record id="sf_machine_hr_equipment_view_tree_inherit" model="ir.ui.view">
<field name="name">sf.machine.hr.equipment.view.tree.inherit</field>
<field name="model">maintenance.equipment</field>
<field name="inherit_id" ref="maintenance.hr_equipment_view_tree"/>
<field name="arch" type="xml">
<xpath expr="//tree" position="inside">
<header>
<button name="sync_oee" type="object" string="同步设备至OEE"/>
</header>
</xpath>
</field>
</record>
</odoo>

View File

@@ -14,41 +14,14 @@
<div class="o_setting_left_pane"/> <div class="o_setting_left_pane"/>
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<div class="text-muted"> <div class="text-muted">
<label for="bfm_url_new" /> <label for="bfm_url" />
<field name="bfm_url_new" string="业务平台访问地址"/> <field name="bfm_url" string="访问地址"/>
</div> </div>
</div> </div>
<!-- </div> --> <!-- </div> -->
</div> </div>
</div> </div>
</div> </div>
<div>
<h2>获取检测报告服务配置</h2>
<div class="row mt16 o_settings_container" id="check_report_config">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="get_check_file_path" />
<field name="get_check_file_path" string="检测报告服务地址"/>
</div>
</div>
<!-- </div> -->
</div>
</div>
</div>
</xpath>
<xpath expr="//div[@id='check_report_config']/div" position="after">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="is_get_detection_file"/>
</div>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="is_get_detection_file"/>
</div>
</div>
</div>
</xpath> </xpath>
</field> </field>
</record> </record>

View File

@@ -14,7 +14,7 @@
<!-- <field name="program_ids" domain="[('workorder_id', '=', workorder_id)]"/>--> <!-- <field name="program_ids" domain="[('workorder_id', '=', workorder_id)]"/>-->
</group> </group>
<footer> <footer>
<!-- <button string="合并下发" name="confirm_up" type="object" class="btn-primary" confirm="是否确认合并下发"/>--> <button string="合并下发" name="confirm_up" type="object" class="btn-primary" confirm="是否确认合并下发"/>
<button string="取消" class="btn-secondary" special="cancel"/> <button string="取消" class="btn-secondary" special="cancel"/>
</footer> </footer>
</form> </form>

View File

@@ -24,7 +24,6 @@ class SfEquipmentSaintenanceStandards(models.Model):
remark = fields.Char('备注') remark = fields.Char('备注')
maintenance_type = fields.Selection([('保养', '保养'), ("检修", "检修")], string='类型', default='保养') maintenance_type = fields.Selection([('保养', '保养'), ("检修", "检修")], string='类型', default='保养')
name = fields.Char(string='名称') name = fields.Char(string='名称')
active = fields.Boolean(default=True)
@api.model_create_multi @api.model_create_multi
def create(self, vals_list): def create(self, vals_list):

View File

@@ -38,7 +38,8 @@ class SfMaintenanceEquipment(models.Model):
crea_url = "/api/machine_tool/create" crea_url = "/api/machine_tool/create"
# AGV运行日志
#AGV运行日志
agv_logs = fields.One2many('maintenance.equipment.agv.log', 'equipment_id', string='AGV运行日志') agv_logs = fields.One2many('maintenance.equipment.agv.log', 'equipment_id', string='AGV运行日志')
# 1212修改后的字段 # 1212修改后的字段
number_of_axles = fields.Selection( number_of_axles = fields.Selection(
@@ -116,6 +117,7 @@ class SfMaintenanceEquipment(models.Model):
# num = "%04d" % m # num = "%04d" % m
# return num # return num
equipment_maintenance_standards_ids = fields.Many2many('equipment.maintenance.standards', equipment_maintenance_standards_ids = fields.Many2many('equipment.maintenance.standards',
'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='设备保养标准',
@@ -177,8 +179,7 @@ class SfMaintenanceEquipment(models.Model):
type_id = fields.Many2one('sf.machine_tool.type', '型号') type_id = fields.Many2one('sf.machine_tool.type', '型号')
state = fields.Selection( state = fields.Selection(
[("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"), [("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"), ("封存(报废)", "封存(报废)")],
("封存(报废)", "封存(报废)")],
default='正常', string="机床状态") default='正常', string="机床状态")
run_time = fields.Char('总运行时长') run_time = fields.Char('总运行时长')
# 0606新增字段 # 0606新增字段
@@ -327,7 +328,7 @@ class SfMaintenanceEquipment(models.Model):
item.tool_diameter_min = item.type_id.tool_diameter_min item.tool_diameter_min = item.type_id.tool_diameter_min
item.machine_tool_category = item.type_id.machine_tool_category.id item.machine_tool_category = item.type_id.machine_tool_category.id
item.brand_id = item.type_id.brand_id.id item.brand_id = item.type_id.brand_id.id
# 新增修改字段 #新增修改字段
item.taper_type_id = item.type_id.taper_type_id.id item.taper_type_id = item.type_id.taper_type_id.id
item.function_type = item.type_id.function_type item.function_type = item.type_id.function_type
item.a_axis = item.type_id.a_axis item.a_axis = item.type_id.a_axis
@@ -369,6 +370,7 @@ class SfMaintenanceEquipment(models.Model):
item.image_id = item.type_id.jg_image_id.ids item.image_id = item.type_id.jg_image_id.ids
item.image_lq_id = item.type_id.lq_image_id.ids item.image_lq_id = item.type_id.lq_image_id.ids
# AGV小车设备参数 # AGV小车设备参数
AGV_L = fields.Char('AGV尺寸(长)') AGV_L = fields.Char('AGV尺寸(长)')
AGV_W = fields.Char('AGV尺寸(宽)') AGV_W = fields.Char('AGV尺寸(宽)')
@@ -459,6 +461,18 @@ class SfMaintenanceEquipment(models.Model):
original_value = fields.Char('原值') original_value = fields.Char('原值')
incomplete_value = fields.Char('残值') incomplete_value = fields.Char('残值')
# 注册同步机床 # 注册同步机床
def enroll_machine_tool(self): def enroll_machine_tool(self):
sf_sync_config = self.env['res.config.settings'].get_values() sf_sync_config = self.env['res.config.settings'].get_values()
@@ -749,7 +763,7 @@ class SfMaintenanceEquipment(models.Model):
image_id = fields.Many2many('maintenance.equipment.image', 'equipment_id', image_id = fields.Many2many('maintenance.equipment.image', 'equipment_id',
domain="[('type', '=', '加工能力')]") domain="[('type', '=', '加工能力')]")
image_lq_id = fields.Many2many('maintenance.equipment.image', 'equipment_lq_id', string='冷却方式', image_lq_id = fields.Many2many('maintenance.equipment.image', 'equipment_lq_id', string='冷却方式',
domain="[('type', '=', '冷却方式')]") domain="[('type', '=', '冷却方式')]")
class SfRobotAxisNum(models.Model): class SfRobotAxisNum(models.Model):
@@ -763,5 +777,4 @@ class SfRobotAxisNum(models.Model):
weight = fields.Char('最大负载(kg)') weight = fields.Char('最大负载(kg)')
permissible_load_torque = fields.Char('允许负载扭矩(N-m)') permissible_load_torque = fields.Char('允许负载扭矩(N-m)')
permissible_inertial_torque = fields.Char('允许惯性扭矩(kg-m²)') permissible_inertial_torque = fields.Char('允许惯性扭矩(kg-m²)')
equipment_id = fields.Many2one('maintenance.equipment', string='机器人', equipment_id = fields.Many2one('maintenance.equipment', string='机器人', domain="[('equipment_type', '=', '机器人')]")
domain="[('equipment_type', '=', '机器人')]")

View File

@@ -10,21 +10,21 @@ class SfMaintenanceLogs(models.Model):
name = fields.Char(string='名称') name = fields.Char(string='名称')
type = fields.Selection([('type1', '类型1'), ('type2', '类型2')], string='类型') type = fields.Selection([('type1', '类型1'), ('type2', '类型2')], string='类型')
brand = fields.Many2one('sf.machine.brand', related='maintenance_equipment_id.brand_id', string='品牌') brand = fields.Many2one('sf.machine.brand', related='maintenance_equipment_id.brand_id', string='品牌')
maintenance_equipment_id = fields.Many2one('maintenance.equipment', string='机台号') maintenance_equipment_id = fields.Many2one('maintenance.equipment', string='设备')
maintenance_equipment_oee_id = fields.Many2one('maintenance.equipment.oee', string='设备oee') maintenance_equipment_oee_id = fields.Many2one('maintenance.equipment.oee', string='设备oee')
code_location = fields.Char(string='编码位置') code_location = fields.Char(string='编码位置')
fault_type = fields.Selection( fault_type = fields.Selection(
[('电气类', '电气类'), ('机械类', '机械类'), ('程序类', '程序类'), ('系统类', '系统类')], string='故障类型') [('电气类', '电气类'), ('机械类', '机械类'), ('程序类', '程序类'), ('系统类', '系统类')], string='故障类型')
fault_code = fields.Char(string='故障代码') fault_code = fields.Char(string='故障代码')
fault_alarm_info = fields.Text(string='故障报警信息') fault_alarm_info = fields.Char(string='故障报警信息')
alarm_level = fields.Selection([('一级', '一级(严重)'), ('二级', '二级(中等)'), ('三级', '三级(轻微)')], alarm_level = fields.Selection([('一级', '一级(严重)'), ('二级', '二级(中等)'), ('三级', '三级(轻微)')],
string='报警级别') string='报警级别')
alarm_time = fields.Datetime(string='故障报警时间') alarm_time = fields.Datetime(string='报警时间')
alarm_way = fields.Selection([('文本提示报警', '文本提示报警'), ('声光报警', '声光报警'), ('图文报警', '图文报警')], alarm_way = fields.Selection([('文本提示报警', '文本提示报警'), ('声光报警', '声光报警'), ('图文报警', '图文报警')],
string='报警方式') string='报警方式')
fault_process = fields.Text(string='故障处理方法') fault_process = fields.Text(string='故障处理方法')
operator = fields.Many2one('res.users', string='处理人') operator = fields.Many2one('res.users', string='处理人')
recovery_time = fields.Datetime(string='故障消除时间') recovery_time = fields.Datetime(string='复原时间')
fault_duration = fields.Float(string='故障时长') fault_duration = fields.Float(string='故障时长')
note = fields.Text(string='备注') note = fields.Text(string='备注')
active = fields.Boolean('Active', default=True) active = fields.Boolean('Active', default=True)

View File

@@ -7,23 +7,20 @@ class SfMaintenanceEquipmentOEE(models.Model):
_description = '设备OEE' _description = '设备OEE'
name = fields.Char('设备oee') name = fields.Char('设备oee')
equipment_id = fields.Many2one('maintenance.equipment', '机台号', equipment_id = fields.Many2one('maintenance.equipment', '设备',
domain="[('category_id.equipment_type', '=', '机床'),('state_zc', '=', '已注册')]") domain="[('category_id.equipment_type', '=', '机床'),('state_zc', '=', '已注册')]")
type_id = fields.Many2one('sf.machine_tool.type', '型号', related='equipment_id.type_id') type_id = fields.Many2one('sf.machine_tool.type', '型号', related='equipment_id.type_id')
machine_tool_picture = fields.Binary('设备图片', related='equipment_id.machine_tool_picture') machine_tool_picture = fields.Binary('设备图片', related='equipment_id.machine_tool_picture')
state = fields.Selection( state = fields.Selection(
[("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"), [("正常", "正常"), ("故障停机", "故障停机"), ("计划维保", "计划维保"), ("空闲", "空闲"),
("封存(报废)", "封存(报废)")], ("封存(报废)", "封存(报废)")],
default='正常', string="机床状态", related='equipment_id.state') default='正常', string="机床状态", related='equipment_id.state')
run_time = fields.Float('加工时长(h)') run_time = fields.Float('正常运行总时长(h)')
equipment_time = fields.Float('开机时长(h)') equipment_time = fields.Float('时长(h)')
done_nums = fields.Integer('加工件数') done_nums = fields.Integer('累计加工件数')
utilization_rate = fields.Char('可用') utilization_rate = fields.Char('开动')
fault_time = fields.Float('故障时长') fault_time = fields.Float('故障停机总时长(h)')
fault_nums = fields.Integer('故障次数') fault_nums = fields.Integer('故障次数')
# 故障率
fault_rate = fields.Char('故障率')
# 设备故障日志
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', '设备故障日志',
related='equipment_id.sf_maintenance_logs_ids') related='equipment_id.sf_maintenance_logs_ids')
oee_logs = fields.One2many('maintenance.equipment.oee.logs', 'equipment_oee_id', string='运行日志') oee_logs = fields.One2many('maintenance.equipment.oee.logs', 'equipment_oee_id', string='运行日志')
@@ -41,58 +38,12 @@ class SfMaintenanceEquipmentOEELog(models.Model):
_name = 'maintenance.equipment.oee.logs' _name = 'maintenance.equipment.oee.logs'
_description = '设备运行日志' _description = '设备运行日志'
equipment_id = fields.Many2one('maintenance.equipment', '机台号', readonly='True') name = fields.Char('运行日志')
equipment_code = fields.Char('设备编码', readonly='True') run_time = fields.Datetime('时间')
name = fields.Char('设备名称', readonly='True') state = fields.Selection([("开机", "开机"), ("关机", "关机"), ("等待", "等待"), ("开始加工", "开始加工"),
function_type = fields.Selection( ("结束加工", "结束加工"), ("故障", "故障"),
[("ZXJGZX", "钻铣加工中心"), ("CXJGZX", "车削加工中心"), ("FHJGZX", "复合加工中心")],
default="", string="功能类型")
machine_tool_picture = fields.Binary('设备图片')
type_id = fields.Many2one('sf.machine_tool.type', '品牌型号', reaonly='True')
state = fields.Selection([("加工", "加工"), ("关机", "关机"), ("待机", "待机"), ("故障", "故障"),
("检修", "检修"), ("保养", "保养")], default="", string="实时状态")
online_time = fields.Char('开机时长', reaonly='True')
offline_time = fields.Char('关机时长', reaonly='True')
offline_nums = fields.Integer('关机次数', reaonly='True')
# 待机时长
idle_time = fields.Char('待机时长', reaonly='True')
# 待机率
idle_rate = fields.Char('待机率', reaonly='True')
work_time = fields.Char('加工时长', reaonly='True')
work_rate = fields.Char('可用率', reaonly='True')
fault_time = fields.Char('故障时长', reaonly='True')
fault_rate = fields.Char('故障率', reaonly='True')
fault_nums = fields.Integer('故障次数', reaonly='True')
detail_ids = fields.One2many('maintenance.equipment.oee.log.detail', 'log_id', string='日志详情')
# maintenance_time = fields.Char('维保时长')
# work_nums = fields.Integer('加工件数')
equipment_oee_id = fields.Many2one('maintenance.equipment.oee', '设备OEE')
@api.onchange('equipment_id')
def get_name(self):
self.name = self.equipment_id.name
self.equipment_code = self.equipment_id.code
# 设备运行日志详情
class SfMaintenanceEquipmentOEELogDetail(models.Model):
_name = 'maintenance.equipment.oee.log.detail'
_description = '设备运行日志详情'
_order = 'time desc'
# sequence = fields.Integer('序号', related='id')
time = fields.Datetime('时间')
state = fields.Selection([("加工", "加工"), ("关机", "关机"), ("待机", "待机"), ("故障", "故障"),
("检修", "检修"), ("保养", "保养")], default="", string="事件/状态") ("检修", "检修"), ("保养", "保养")], default="", string="事件/状态")
production_name = fields.Char('加工') workorder_id = fields.Char('加工')
time = fields.Char('持续时长')
log_id = fields.Many2one('maintenance.equipment.oee.logs', '日志') color = fields.Char('颜色', default=1)
# equipment_code = fields.Char('设备编码', related='log_id.equipment_code') equipment_oee_id = fields.Many2one('maintenance.equipment.oee', '设备OEE')
equipment_code = fields.Char('设备编码', readonly='True')

View File

@@ -67,6 +67,3 @@ access_sf_cutting_tool_type_admin_sf_group_equipment_user,sf_cutting_tool_type_a
access_sf_cutting_tool_type_group_purchase_director_sf_group_equipment_user,sf_cutting_tool_type_group_purchase_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0 access_sf_cutting_tool_type_group_purchase_director_sf_group_equipment_user,sf_cutting_tool_type_group_purchase_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0
access_sf_cutting_tool_type_group_sale_director_sf_group_equipment_user,sf_cutting_tool_type_group_sale_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0 access_sf_cutting_tool_type_group_sale_director_sf_group_equipment_user,sf_cutting_tool_type_group_sale_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0
access_sf_cutting_tool_type_group_plan_director_sf_group_equipment_user,sf_cutting_tool_type_group_plan_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0 access_sf_cutting_tool_type_group_plan_director_sf_group_equipment_user,sf_cutting_tool_type_group_plan_director,sf_base.model_sf_cutting_tool_type,sf_maintenance.sf_group_equipment_user,1,0,0,0
access_maintenance_equipment_oee_logs,maintenance_equipment_oee_logs,model_maintenance_equipment_oee_logs,sf_maintenance.sf_group_equipment_manager,1,1,1,1
access_maintenance_equipment_oee_log_detail,maintenance_equipment_oee_log_detail,model_maintenance_equipment_oee_log_detail,sf_maintenance.sf_group_equipment_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
67
68
69

View File

@@ -6,16 +6,15 @@
<field name="name">equipment.maintenance.standards.form</field> <field name="name">equipment.maintenance.standards.form</field>
<field name="model">equipment.maintenance.standards</field> <field name="model">equipment.maintenance.standards</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="设备维保标准" delete="false" duplicate="false"> <form string="设备维保标准">
<sheet> <sheet>
<group> <group>
<group> <group>
<field name="active" invisible="1"/> <field name="code" readonly="1" force_save="1"/>
<field name="code" readonly="1" force_save="1"/> <field name="name" readonly="1" force_save="1"/>
<field name="name" readonly="1" force_save="1"/> <field name="maintenance_equipment_category_id" required="1" />
<field name="maintenance_equipment_category_id" required="1"/> <field name="eq_maintenance_ids" invisible='1'/>
<field name="eq_maintenance_ids" invisible='1'/> <field name="overhaul_ids" invisible='1'/>
<field name="overhaul_ids" invisible='1'/>
</group> </group>
@@ -51,8 +50,7 @@
<field name="name">equipment.maintenance.standards.tree</field> <field name="name">equipment.maintenance.standards.tree</field>
<field name="model">equipment.maintenance.standards</field> <field name="model">equipment.maintenance.standards</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="设备维保标准" delete="false"> <tree string="设备维保标准">
<field name="active" invisible="1"/>
<field name="code" readonly="1" force_save="1"/> <field name="code" readonly="1" force_save="1"/>
<field name="maintenance_type" required="1"/> <field name="maintenance_type" required="1"/>
<field name="name" required="1"/> <field name="name" required="1"/>
@@ -79,7 +77,6 @@
<field name="name" string="日常机床保养"/> <field name="name" string="日常机床保养"/>
<field name="created_user_id" string="创建人"/> <field name="created_user_id" string="创建人"/>
<field name="maintenance_equipment_category_id" string="设备类别"/> <field name="maintenance_equipment_category_id" string="设备类别"/>
<filter name="filter_active" string="已归档" domain="[('active','=',False)]"/>
</search> </search>
</field> </field>
</record> </record>

View File

@@ -14,7 +14,6 @@
<field name="utilization_rate"/> <field name="utilization_rate"/>
<field name="fault_time"/> <field name="fault_time"/>
<field name="fault_nums"/> <field name="fault_nums"/>
<field name="fault_rate"/>
</tree> </tree>
</field> </field>
</record> </record>
@@ -50,19 +49,19 @@
</group> </group>
</group> </group>
<!-- <notebook> --> <notebook>
<!-- <page string="运行日志"> --> <page string="运行日志">
<!-- <field name="oee_logs"> --> <field name="oee_logs">
<!-- <tree create="1" edit="1" delete="1" editable="bottom"> --> <tree create="1" edit="1" delete="1" editable="bottom">
<!-- <field name = 'run_time'/> --> <field name = 'run_time'/>
<!-- <field name = 'state'/> --> <field name = 'state'/>
<!-- <field name = 'workorder_id'/> --> <field name = 'workorder_id'/>
<!-- <field name = 'time'/> --> <field name = 'time'/>
<!-- <field name = 'color' widget="color"/> --> <field name = 'color' widget="color"/>
<!-- </tree> --> </tree>
<!-- </field> --> </field>
<!-- </page> --> </page>
<!-- </notebook> --> </notebook>
</sheet> </sheet>
</form> </form>
</field> </field>

View File

@@ -7,20 +7,22 @@
<field name="model">sf.maintenance.logs</field> <field name="model">sf.maintenance.logs</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree> <tree>
<field name="code"/>
<field name="type" optional="hide"/> <field name="type" optional="hide"/>
<field name="brand"/> <field name="brand"/>
<field name="maintenance_equipment_id"/> <field name="maintenance_equipment_id"/>
<field name="code_location" optional="hide"/> <field name="code_location" optional="hide"/>
<field name="fault_type"/>
<field name="fault_code" optional="hide"/> <field name="fault_code" optional="hide"/>
<field name="alarm_time"/>
<field name="fault_alarm_info"/> <field name="fault_alarm_info"/>
<field name="alarm_level" optional="hide"/> <field name="alarm_level" optional="hide"/>
<field name="alarm_time"/>
<field name="alarm_way" optional="hide"/> <field name="alarm_way" optional="hide"/>
<field name="fault_process" optional="hide"/> <field name="fault_process"/>
<field name="operator" optional="hide"/> <field name="operator"/>
<field name="recovery_time"/> <field name="recovery_time"/>
<field name="fault_duration"/> <field name="fault_duration"/>
<field name="note" optional="hide"/> <field name="note"/>
</tree> </tree>
</field> </field>
</record> </record>
@@ -43,32 +45,25 @@
<group> <group>
<group> <group>
<!-- <field name="name"/> --> <field name="name"/>
<!-- <field name="type" required="1" widget="radio" options="{'horizontal': true}"/> --> <field name="type" required="1" widget="radio" options="{'horizontal': true}"/>
<field name="maintenance_equipment_id"/>
<field name="brand"/> <field name="brand"/>
<field name="alarm_time"/> <field name="maintenance_equipment_id"/>
<field name="fault_alarm_info"/> <field name="code_location"/>
<field name="fault_type" required="1" widget="radio" options="{'horizontal': true}"/>
<!-- <field name="code_location"/> --> <field name="fault_code"/>
<!-- <field name="fault_type" required="1" widget="radio" options="{'horizontal': true}"/> --> <field name="fault_process"/>
<!-- <field name="fault_code"/> -->
</group> </group>
<group> <group>
<field name="fault_alarm_info"/>
<field name="alarm_time"/>
<field name="alarm_way" required="1" widget="radio" options="{'horizontal': true}"/>
<field name="operator"/> <field name="operator"/>
<field name="fault_process"/>
<!-- <field name="alarm_way" required="1" widget="radio" options="{'horizontal': true}"/> -->
<field name="recovery_time"/> <field name="recovery_time"/>
<field name="fault_duration"/> <field name="fault_duration"/>
<field name="note"/>
</group> </group>
</group>
<group>
<field name="note"/>
</group> </group>
</sheet> </sheet>
</form> </form>
@@ -105,248 +100,6 @@
</field> </field>
</record> </record>
<!-- 设备运行日志 -->
<record id="view_maintenance_logs_run_tree" model="ir.ui.view">
<field name="name">maintenance.logs.run.tree</field>
<field name="model">maintenance.equipment.oee.logs</field>
<field name="arch" type="xml">
<tree>
<field name="equipment_id"/>
</tree>
</field>
</record>
<record id="view_maintenance_logs_run_form" model="ir.ui.view">
<field name="name">maintenance.logs.run.form</field>
<field name="model">maintenance.equipment.oee.logs</field>
<field name="arch" type="xml">
<!-- <form string="设备运行日志"> -->
<!-- <header> -->
<!-- <field name="equipment_id" readonly="1"/> -->
<!-- </header> -->
<!-- <sheet> -->
<!-- <div class="oe_title"> -->
<!-- <h1> -->
<!-- <field name="start_time" readonly="1"/> -->
<!-- </h1> -->
<!-- </div> -->
<!-- <group> -->
<!-- <group> -->
<!-- <field name="stop_time" readonly="1"/> -->
<!-- <field name="duration" readonly="1"/> -->
<!-- <field name="oee" readonly="1"/> -->
<!-- </group> -->
<!-- <group> -->
<!-- <field name="note"/> -->
<!-- </group> -->
<!-- </group> -->
<!-- </sheet> -->
<!-- </form> -->
<form string="设备运行日志">
<!-- <header> -->
<!-- <field name="name" readonly="1"/> -->
<!-- </header> -->
<sheet>
<div class="oe_title">
<h1>
<field name="name"/>
</h1>
</div>
<group>
<group>
<group>
<field name="equipment_id" domain="[('name','ilike','加工中心')]"/>
<field name="type_id"/>
<field name="state"/>
<field name="equipment_code"/>
<field name="function_type"/>
</group>
</group>
<group>
<group>
<!-- <field name="state" nolabel="1"/> -->
<field name="state" string=""/>
</group>
<group>
<field name="machine_tool_picture" widget="image" nolabel="1"/>
</group>
</group>
</group>
<group>
<group>
<group>
<field name="online_time" readonly="1"/>
<field name="offline_time" readonly="1"/>
<field name="fault_rate" readonly="1"/>
</group>
<group>
<field name="offline_nums" readonly="1"/>
<field name="fault_time" readonly="1"/>
<field name="fault_nums" readonly="1"/>
</group>
</group>
<group>
<group>
<field name="idle_time"/>
<field name="idle_rate"/>
</group>
<group>
<field name="work_time"/>
<field name="work_rate"/>
</group>
</group>
</group>
<notebook>
<page string="24H日志详情">
<!-- 筛选出24小时内的日志 -->
<!-- <field name="detail_ids" domain="[('time','&lt;',(datetime.datetime.now() - datetime.timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S'))]"> -->
<field name="detail_ids" domain="[('state','ilike','加工')]">
<tree>
<!-- <field name="sequence"/> -->
<field name="time"/>
<field name="state"/>
<field name="production_name"/>
</tree>
<!-- <form> -->
<!-- <field name="sequence"/> -->
<!-- <field name="time"/> -->
<!-- <field name="state"/> -->
<!-- <field name="production_id"/> -->
<!-- </form> -->
</field>
</page>
<page string="历史日志详情">
<field name="detail_ids">
<tree>
<!-- <field name="sequence"/> -->
<field name="time"/>
<field name="state"/>
<field name="production_name"/>
</tree>
<!-- <form> -->
<!-- <field name="sequence"/> -->
<!-- <field name="time"/> -->
<!-- <field name="state"/> -->
<!-- <field name="production_id"/> -->
<!-- </form> -->
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- <record id="view_maintenance_logs_run_search" model="ir.ui.view"> -->
<!-- <field name="name">maintenance.logs.run.search</field> -->
<!-- <field name="model">maintenance.equipment.oee.logs</field> -->
<!-- <field name="arch" type="xml"> -->
<!-- <search> -->
<!-- <field name="equipment_id"/> -->
<!-- <field name="start_time"/> -->
<!-- <field name="stop_time"/> -->
<!-- <field name="duration"/> -->
<!-- <field name="oee"/> -->
<!-- <field name="note"/> -->
<!-- </search> -->
<!-- </field> -->
<!-- </record> -->
<!-- 设备运行日志详情 -->
<record id="view_maintenance_logs_run_detail_tree" model="ir.ui.view">
<field name="name">maintenance.logs.run.detail.tree</field>
<field name="model">maintenance.equipment.oee.log.detail</field>
<field name="arch" type="xml">
<tree>
<!-- <field name="sequence"/> -->
<field name="time"/>
<field name="state"/>
<field name="production_name"/>
</tree>
</field>
</record>
<record id="view_maintenance_logs_run_detail_form" model="ir.ui.view">
<field name="name">maintenance.logs.run.detail.form</field>
<field name="model">maintenance.equipment.oee.log.detail</field>
<field name="arch" type="xml">
<form string="设备运行日志详情">
<sheet>
<group>
<group>
<field name="state"/>
<!-- <field name="production_id"/> -->
</group>
<group>
<!-- <field name="sequence"/> -->
<field name="time"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<!-- <record id="view_maintenance_logs_run_detail_search" model="ir.ui.view"> -->
<!-- <field name="name">maintenance.logs.run.detail.search</field> -->
<!-- <field name="model">maintenance.equipment.oee.logs.detail</field> -->
<!-- <field name="arch" type="xml"> -->
<!-- <search> -->
<!-- <field name="equipment_id"/> -->
<!-- <field name="start_time"/> -->
<!-- <field name="stop_time"/> -->
<!-- <field name="duration"/> -->
<!-- <field name="oee"/> -->
<!-- <field name="note"/> -->
<!-- </search> -->
<!-- </field> -->
<!-- </record> -->
<!-- 设备运行日志详情action -->
<!-- <record id="action_maintenance_logs_run_detail" model="ir.actions.act_window"> -->
<!-- <field name="name">设备运行日志详情</field> -->
<!-- <field name="type">ir.actions.act_window</field> -->
<!-- <field name="res_model">maintenance.equipment.oee.logs.detail</field> -->
<!-- <field name="view_mode">tree,form</field> -->
<!-- <field name="view_id" ref="view_maintenance_logs_run_detail_tree"/> -->
<!-- <field name="help" type="html"> -->
<!-- <p class="oe_view_nocontent_create"> -->
<!-- 设备运行日志详情 -->
<!-- </p> -->
<!-- </field> -->
<!-- -->
<!-- </record> -->
<record id="action_maintenance_logs_run" model="ir.actions.act_window">
<field name="name">设备运行日志</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">maintenance.equipment.oee.logs</field>
<!-- <field name="search_view_id" ref="view_maintenance_logs_run_search"/> -->
<field name="view_mode">tree,form</field>
<!-- <field name="view_mode">form</field> -->
<field name="view_id" ref="view_maintenance_logs_run_tree"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
设备运行日志
</p>
</field>
</record>
<menuitem name="设备运行日志" id="menu_maintenance_logs_run" parent="maintenance.menu_m_request"
sequence="10" action="action_maintenance_logs_run"/>
<!-- Action --> <!-- Action -->

View File

@@ -14,15 +14,10 @@
'data': [ 'data': [
'data/stock_data.xml', 'data/stock_data.xml',
'data/empty_racks_data.xml', 'data/empty_racks_data.xml',
'data/panel_data.xml',
'data/agv_scheduling_data.xml',
'security/group_security.xml', 'security/group_security.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'wizard/workpiece_delivery_views.xml', 'wizard/workpiece_delivery_views.xml',
'wizard/rework_wizard_views.xml',
'wizard/production_wizard_views.xml',
'views/mrp_views_menus.xml', 'views/mrp_views_menus.xml',
'views/agv_scheduling_views.xml',
'views/stock_lot_views.xml', 'views/stock_lot_views.xml',
'views/mrp_production_addional_change.xml', 'views/mrp_production_addional_change.xml',
'views/mrp_routing_workcenter_view.xml', 'views/mrp_routing_workcenter_view.xml',
@@ -32,7 +27,7 @@
'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',
], ],
'assets': { 'assets': {
@@ -42,9 +37,7 @@
'web.assets_backend': [ 'web.assets_backend': [
'sf_manufacturing/static/src/xml/kanban_change.xml', 'sf_manufacturing/static/src/xml/kanban_change.xml',
'sf_manufacturing/static/src/js/kanban_change.js', 'sf_manufacturing/static/src/js/kanban_change.js',
'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/js/workpiece_delivery_wizard_confirm.js',
] ]
}, },

View File

@@ -2,15 +2,13 @@
import logging import logging
import json import json
from datetime import datetime from datetime import datetime
from odoo.addons.sf_manufacturing.models.agv_scheduling import RepeatTaskException
from odoo import http from odoo import http
from odoo.http import request from odoo.http import request
class Manufacturing_Connect(http.Controller): class Manufacturing_Connect(http.Controller):
@http.route('/AutoDeviceApi/GetWoInfo', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/GetWoInfo', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
def get_Work_Info(self, **kw): def get_Work_Info(self, **kw):
""" """
@@ -27,8 +25,7 @@ class Manufacturing_Connect(http.Controller):
{'content': ret, 'name': 'AutoDeviceApi/GetWoInfo'}) {'content': ret, 'name': 'AutoDeviceApi/GetWoInfo'})
logging.info('RfidCode:%s' % ret['RfidCode']) logging.info('RfidCode:%s' % ret['RfidCode'])
if 'RfidCode' in ret: if 'RfidCode' in ret:
workorder = request.env['mrp.workorder'].sudo().search( workorder = request.env['mrp.workorder'].sudo().search([('rfid_code', '=', ret['RfidCode'])])
[('rfid_code', '=', ret['RfidCode']), ('state', '!=', 'rework')])
if workorder: if workorder:
for item in workorder: for item in workorder:
res['Datas'].append({ res['Datas'].append({
@@ -125,8 +122,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('RfidCode:%s' % ret['RfidCode']) logging.info('RfidCode:%s' % ret['RfidCode'])
if 'RfidCode' in ret: if 'RfidCode' in ret:
workorder = request.env['mrp.workorder'].sudo().search( workorder = request.env['mrp.workorder'].sudo().search(
[('routing_type', '=', '装夹预调'), ('rfid_code', '=', ret['RfidCode']), ('state', '!=', 'rework')], [('routing_type', '=', '装夹预调'), ('rfid_code', '=', ret['RfidCode'])], limit=1, order='id asc')
limit=1, order='id asc')
if workorder: if workorder:
for item in workorder: for item in workorder:
if item.material_center_point: if item.material_center_point:
@@ -147,7 +143,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('get_qcCheck error:%s' % e) logging.info('get_qcCheck error:%s' % e)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/FeedBackStart', type='json', auth='none', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/FeedBackStart', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
def button_Work_START(self, **kw): def button_Work_START(self, **kw):
""" """
@@ -166,8 +162,7 @@ class Manufacturing_Connect(http.Controller):
routing_type = ret['CraftId'] routing_type = ret['CraftId']
equipment_id = ret["DeviceId"] equipment_id = ret["DeviceId"]
workorder = request.env['mrp.workorder'].sudo().search( workorder = request.env['mrp.workorder'].sudo().search(
[('production_id', '=', production_id), ('routing_type', '=', routing_type), [('production_id', '=', production_id), ('routing_type', '=', routing_type)], limit=1)
('rfid_code', '!=', False), ('state', '!=', 'rework')], limit=1)
if not workorder: if not workorder:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '该工单不存在'} res = {'Succeed': False, 'ErrorCode': 202, 'Error': '该工单不存在'}
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@@ -195,7 +190,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('button_Work_START error:%s' % e) logging.info('button_Work_START error:%s' % e)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/FeedBackEnd', type='json', auth='none', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/FeedBackEnd', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
def button_Work_End(self, **kw): def button_Work_End(self, **kw):
""" """
@@ -208,14 +203,12 @@ class Manufacturing_Connect(http.Controller):
res = {'Succeed': True, 'Datas': ['工单已结束']} res = {'Succeed': True, 'Datas': ['工单已结束']}
datas = request.httprequest.data datas = request.httprequest.data
ret = json.loads(datas) ret = json.loads(datas)
logging.info('button_Work_End:%s' % ret)
request.env['center_control.interface.log'].sudo().create( request.env['center_control.interface.log'].sudo().create(
{'content': ret, 'name': 'AutoDeviceApi/FeedBackEnd'}) {'content': ret, 'name': 'AutoDeviceApi/FeedBackEnd'})
production_id = ret['BillId'] production_id = ret['BillId']
routing_type = ret['CraftId'] routing_type = ret['CraftId']
workorder = request.env['mrp.workorder'].sudo().search( workorder = request.env['mrp.workorder'].sudo().search(
[('production_id', '=', production_id), ('routing_type', '=', routing_type), [('production_id', '=', production_id), ('routing_type', '=', routing_type)], limit=1)
('rfid_code', '!=', False), ('state', '!=', 'rework')], limit=1)
if not workorder: if not workorder:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '该工单不存在'} res = {'Succeed': False, 'ErrorCode': 202, 'Error': '该工单不存在'}
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@@ -223,30 +216,28 @@ class Manufacturing_Connect(http.Controller):
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '该工单未开始'} res = {'Succeed': False, 'ErrorCode': 202, 'Error': '该工单未开始'}
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
# workorder.write({'date_finished': datetime.now()}) # workorder.write({'date_finished': datetime.now()})
if ret['IsComplete'] is True: workorder.button_finish()
workorder.write({'date_finished': datetime.now()}) # workorder.process_state = '待解除装夹'
# workorder.sudo().production_id.process_state = '待解除装夹'
# workorder.process_state = '待解除装夹' # 根据工单的实际结束时间修改排程单的结束时间、状态,同时修改销售订单的状态
# workorder.sudo().production_id.process_state = '待解除装夹' if workorder.date_finished:
request.env['sf.production.plan'].sudo().search([('production_id', '=', production_id)]).write(
# 根据工单的实际结束时间修改排程单的结束时间、状态,同时修改销售订单的状态 {'actual_end_time': workorder.date_finished,
# if workorder.date_finished: 'state': 'finished'})
# request.env['sf.production.plan'].sudo().search([('production_id', '=', production_id)]).write( production_obj = request.env['mrp.production'].sudo().search([('name', '=', production_id)])
# {'actual_end_time': workorder.date_finished, if production_obj:
# 'state': 'finished'}) production_obj.sudo().work_order_state = '已完成'
# production_obj = request.env['mrp.production'].sudo().search([('name', '=', production_id)]) production_obj.write({'state': 'completed'})
# if production_obj: # request.env['sale.order'].sudo().search(
# production_obj.sudo().work_order_state = '已完成' # [('name', '=', production_obj.origin)]).write({'schedule_status': 'to deliver'})
# production_obj.write({'state': 'done'})
# request.env['sale.order'].sudo().search(
# [('name', '=', production_obj.origin)]).write({'schedule_status': 'to deliver'})
except Exception as e: except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e} res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('button_Work_End error:%s' % e) logging.info('button_Work_End error:%s' % e)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/PartQualityInspect', type='json', auth='none', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/PartQualityInspect', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
def PartQualityInspect(self, **kw): def PartQualityInspect(self, **kw):
""" """
@@ -262,27 +253,39 @@ class Manufacturing_Connect(http.Controller):
request.env['center_control.interface.log'].sudo().create( request.env['center_control.interface.log'].sudo().create(
{'content': ret, 'name': 'AutoDeviceApi/PartQualityInspect'}) {'content': ret, 'name': 'AutoDeviceApi/PartQualityInspect'})
production_id = ret['BillId'] production_id = ret['BillId']
# routing_type = ret['CraftId'] routing_type = ret['CraftId']
workorder = request.env['mrp.workorder'].sudo().search( workorder = request.env['mrp.workorder'].sudo().search(
[('production_id', '=', production_id), ('routing_type', '=', 'CNC加工'), [('production_id', '=', production_id), ('routing_type', '=', routing_type)], limit=1)
('state', 'not in', ['rework', 'done', 'cancel'])], order='sequence asc',
limit=1)
if workorder: if workorder:
# workorder.test_results = ret['Quality'] # workorder.test_results = ret['Quality']
logging.info('制造订单:%s' % workorder.production_id.name) logging.info('制造订单:%s' % workorder.production_id.name)
if 'ReportPaht' in ret: if 'ReportPaht' in ret:
if ret['ReportPaht'].find('.pdf') != -1: download_state = request.env['mrp.workorder'].with_user(
download_state = request.env['mrp.workorder'].with_user( request.env.ref("base.user_admin")).download_reportfile_tmp(workorder,
request.env.ref("base.user_admin")).download_reportfile_tmp(workorder, ret['ReportPaht'])
ret['ReportPaht']) if download_state == 1:
if download_state is True: detection_ret = request.env['mrp.workorder'].with_user(
detection_ret = request.env['mrp.workorder'].with_user( request.env.ref("base.user_admin")).get_detection_file(workorder, ret['ReportPaht'])
request.env.ref("base.user_admin")).get_detection_file(workorder, ret['ReportPaht']) if detection_ret is True:
logging.info('detection_ret:%s' % detection_ret) stock_picking_type = request.env['stock.picking.type'].sudo().search(
if detection_ret is False: [('sequence_code', '=', 'SFP')])
res = {'Succeed': False, 'ErrorCode': 205, 'Error': '检测报告文件读取失败'} if stock_picking_type:
else: stock_picking = request.env['stock.picking'].sudo().search(
res = {'Succeed': False, 'ErrorCode': 204, 'Error': '检测报告文件从FTP拉取失败'} [('product_id', '=', workorder.product_id.id),
('origin', '=', workorder.production_id.origin),
('picking_type_id', '=', stock_picking_type.id)])
if stock_picking:
quality_check = request.env['quality.check'].sudo().search(
[('product_id', '=', workorder.product_id.id),
('picking_id', '=', stock_picking.id)])
if quality_check:
logging.info('质检单:%s' % quality_check.name)
quality_check.write({'report_pdf': workorder.detection_report})
elif download_state == 2:
res = {'Succeed': False, 'ErrorCode': 205,
'Error': 'ReportPaht中的工件号与制造订单%s不匹配请检查ReportPaht是否正确' % workorder.production_id.name}
else:
res = {'Succeed': False, 'ErrorCode': 204, 'Error': '检测报告文件从FTP拉取失败'}
else: else:
res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传ReportPaht字段'} res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传ReportPaht字段'}
else: else:
@@ -292,7 +295,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('PartQualityInspect error:%s' % e) logging.info('PartQualityInspect error:%s' % e)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/CMMProgDolod', type='json', auth='none', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/CMMProgDolod', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
def CMMProgDolod(self, **kw): def CMMProgDolod(self, **kw):
""" """
@@ -310,18 +313,18 @@ class Manufacturing_Connect(http.Controller):
if 'RfidCode' in ret: if 'RfidCode' in ret:
logging.info('RfidCode:%s' % ret['RfidCode']) logging.info('RfidCode:%s' % ret['RfidCode'])
workorder = request.env['mrp.workorder'].sudo().search( workorder = request.env['mrp.workorder'].sudo().search(
[('rfid_code', '=', ret['RfidCode']), ('routing_type', '=', 'CNC加工'), ('state', '!=', 'rework')]) [('rfid_code', '=', ret['RfidCode']), ('routing_type', '=', 'CNC加工')])
if workorder: if workorder:
for item in workorder.cmm_ids: for item in workorder.cmm_ids:
if item.program_create_date is not False: if item.program_date is not False:
program_create_date = item.program_create_date.strftime("%Y-%m-%d %H:%M:%S") program_date = item.program_date.strftime("%Y-%m-%d %H:%M:%S")
program_date_str = request.env['sf.sync.common'].sudo().get_add_time(program_create_date) program_date_str = request.env['sf.sync.common'].sudo().get_add_time(program_date)
res['Datas'].append({ res['Datas'].append({
'CraftId': workorder.id, 'CraftId': workorder.id,
'CraftKey': workorder.name, 'CraftKey': workorder.name,
'ProgramDate': '' if not item.program_create_date else program_date_str, 'ProgramDate': '' if not item.program_date else program_date_str,
'ProgramPath': item.program_path, 'ProgramPath': item.program_path,
'PostProcessing': item.program_name, 'PostProcessing': item.post_processing_name,
}) })
else: else:
res = {'Succeed': False, 'ErrorCode': 203, 'Error': '暂无工单及对应的CNC程序数据'} res = {'Succeed': False, 'ErrorCode': 203, 'Error': '暂无工单及对应的CNC程序数据'}
@@ -332,7 +335,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('CMMProgDolod error:%s' % e) logging.info('CMMProgDolod error:%s' % e)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/NCProgDolod', type='json', auth='none', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/NCProgDolod', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
def NCProgDolod(self, **kw): def NCProgDolod(self, **kw):
""" """
@@ -350,7 +353,7 @@ class Manufacturing_Connect(http.Controller):
if 'RfidCode' in ret: if 'RfidCode' in ret:
logging.info('RfidCode:%s' % ret['RfidCode']) logging.info('RfidCode:%s' % ret['RfidCode'])
workorder = request.env['mrp.workorder'].sudo().search( workorder = request.env['mrp.workorder'].sudo().search(
[('rfid_code', '=', ret['RfidCode']), ('routing_type', '=', 'CNC加工'), ('state', '!=', 'rework')]) [('rfid_code', '=', ret['RfidCode']), ('routing_type', '=', 'CNC加工')])
if workorder: if workorder:
for item in workorder.cnc_ids: for item in workorder.cnc_ids:
res['Datas'].append({ res['Datas'].append({
@@ -388,7 +391,7 @@ class Manufacturing_Connect(http.Controller):
ret = json.loads(datas) ret = json.loads(datas)
request.env['center_control.interface.log'].sudo().create( request.env['center_control.interface.log'].sudo().create(
{'content': ret, 'name': 'AutoDeviceApi/LocationChange'}) {'content': ret, 'name': 'AutoDeviceApi/LocationChange'})
logging.info('库位变更LocationChange_ret:%s' % ret) logging.info('LocationChange_ret===========:%s' % ret)
RfidCode = ret['RfidCode'] RfidCode = ret['RfidCode']
ChangeType = ret['ChangeType'] ChangeType = ret['ChangeType']
OldDeciveId = ret['OldDeciveId'] OldDeciveId = ret['OldDeciveId']
@@ -398,86 +401,40 @@ class Manufacturing_Connect(http.Controller):
OldDeciveStart = ret['OldDeciveStart'] OldDeciveStart = ret['OldDeciveStart']
OldDeciveEnd = ret['OldDeciveEnd'] OldDeciveEnd = ret['OldDeciveEnd']
if ChangeType == 'Part': temp_val_sn_id = None
temp_val_sn_id = None old_localtion = None
old_localtion = None # if ChangeType == 'Part' or ChangeType == 'Tool':
# if ChangeType == 'Part' or ChangeType == 'Tool': stock_lot_obj = request.env['stock.lot'].sudo().search(
stock_lot_obj = request.env['stock.lot'].sudo().search( [('rfid', '=', RfidCode)], limit=1)
[('rfid', '=', RfidCode)], limit=1) logging.info('stock_lot_obj===========:%s' % stock_lot_obj)
logging.info('stock_lot_obj===========:%s' % stock_lot_obj) if not stock_lot_obj:
if not stock_lot_obj: res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'}
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'} return json.JSONEncoder().encode(res)
return json.JSONEncoder().encode(res) if OldPosition:
if OldPosition: old_localtion = request.env['sf.shelf.location'].sudo().search(
old_localtion = request.env['sf.shelf.location'].sudo().search( [('barcode', '=', OldPosition)], limit=1)
[('barcode', '=', OldPosition)], limit=1) logging.info('old_localtion===========:%s' % old_localtion)
logging.info('old_localtion===========:%s' % old_localtion) new_localtion = request.env['sf.shelf.location'].sudo().search(
new_localtion = request.env['sf.shelf.location'].sudo().search( [('barcode', '=', NewPosition)], limit=1)
[('barcode', '=', NewPosition)], limit=1) logging.info('new_localtion===========:%s' % new_localtion)
logging.info('new_localtion===========:%s' % new_localtion) if not new_localtion:
if not new_localtion: res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'}
res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'} return json.JSONEncoder().encode(res)
return json.JSONEncoder().encode(res) if old_localtion:
if old_localtion: temp_val_sn_id = old_localtion.product_sn_id
temp_val_sn_id = old_localtion.product_sn_id logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id)
logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id) old_localtion.product_sn_id = None
old_localtion.product_sn_id = None new_localtion.product_sn_id = temp_val_sn_id
new_localtion.product_sn_id = temp_val_sn_id logging.info('====1======')
logging.info('====1======') else:
else: new_localtion.product_sn_id = stock_lot_obj.id
new_localtion.product_sn_id = stock_lot_obj.id logging.info('=====2======')
logging.info('=====2======')
elif ChangeType == 'Tool':
# 对功能刀具库位变更信息进行更改
def write_tool(DeciveId):
if 'Tool' in DeciveId:
shelfinfo = list(filter(lambda x: x.get('DeviceId') == DeciveId,
request.env['sf.shelf.location'].sudo().get_sf_shelf_location_info(
DeciveId)))
total_data = request.env['sf.shelf.location.datasync'].sudo().get_total_data()
for item in shelfinfo:
logging.info('货架已获取信息:%s' % item)
shelf_barcode = request.env['sf.shelf.location.datasync'].sudo().find_our_code(
total_data, item['Postion'])
location_id = request.env['sf.shelf.location'].sudo().search(
[('barcode', '=', shelf_barcode)],
limit=1)
if location_id:
# 如果是线边刀库信息,则对功能刀具移动生成记录
if 'Tool' in item['Postion']:
tool = request.env['sf.functional.cutting.tool.entity'].sudo().search(
[('rfid', '=', item['RfidCode']), ('functional_tool_status', '!=', '已拆除')])
tool.sudo().tool_in_out_stock_location(location_id)
if tool:
location_id.product_sn_id = tool.barcode_id.id
# 修改功能刀具状态
if item.get('State') == '报警':
if tool.functional_tool_status != item.get('State'):
tool.write({
'functional_tool_status': item['State']
})
else:
location_id.product_sn_id = False
if item['RfidCode']:
logging.info('Rfid为【%s】的功能刀具在系统中不存在!' % item['RfidCode'])
else:
equipment_id = request.env['maintenance.equipment'].sudo().search([('name', '=', DeciveId)])
if equipment_id:
equipment_id.sudo().register_equipment_tool()
else:
res_1 = {'Succeed': False, 'ErrorCode': 202, 'Error': f'设备【{DeciveId}】不存在'}
return json.JSONEncoder().encode(res_1)
if OldDeciveId:
write_tool(OldDeciveId)
elif NewDeciveId:
write_tool(NewDeciveId)
except Exception as e: except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e} res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('LocationChange error:%s' % e) logging.info('LocationChange error:%s' % e)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/AGVToProduct', type='json', auth='none', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/AGVToProduct', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
def AGVToProduct(self, **kw): def AGVToProduct(self, **kw):
""" """
@@ -496,60 +453,41 @@ class Manufacturing_Connect(http.Controller):
if 'DeviceId' in ret: if 'DeviceId' in ret:
logging.info('DeviceId:%s' % ret['DeviceId']) logging.info('DeviceId:%s' % ret['DeviceId'])
if 'IsComplete' in ret: if 'IsComplete' in ret:
rfid_codes = []
workorder_ids = []
if ret['IsComplete'] is True or ret['IsComplete'] is False: if ret['IsComplete'] is True or ret['IsComplete'] is False:
for i in range(1, 5): for i in range(1, 5):
logging.info('F-RfidCode:%s' % i) logging.info('F-RfidCode:%s' % i)
if f'RfidCode{i}' in ret: if f'RfidCode{i}' in ret:
rfid_code = ret[f'RfidCode{i}'] rfid_code = ret[f'RfidCode{i}']
logging.info('RfidCode:%s' % rfid_code) logging.info('RfidCode:%s' % rfid_code)
if rfid_code is not None and rfid_code != '': domain = [
rfid_codes.append(rfid_code) ('rfid_code', '=', rfid_code),
domain = [ ('routing_type', '=', 'CNC加工')
('rfid_code', '=', rfid_code), ]
('routing_type', '=', 'CNC加工'), ('state', '!=', 'rework') workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
] if workorder:
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc') for order in workorder:
if workorder: if order.production_id.production_line_state == '待上产线':
for order in workorder: logging.info(
workorder_ids.append(order.id) '制造订单产线状态:%s' % order.production_id.production_line_state)
if order.production_line_state == '上产线': order.production_id.write({'production_line_state': '上产线'})
logging.info( workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search([
'工单产线状态:%s' % order.production_line_state) ('rfid_code', '=', rfid_code), ('type', '=', '上产线'),
panel_workorder = request.env['mrp.workorder'].sudo().search( ('production_id', '=', order.production_id.id)])
[('rfid_code', '=', rfid_code), ('state', '!=', 'rework'), if workpiece_delivery.status == '待下发':
('processing_panel', '=', order.processing_panel)]) workpiece_delivery.write({'is_manual_work': True})
if panel_workorder: else:
panel_workorder.write({'production_line_state': '已上产线'}) res = {'Succeed': False, 'ErrorCode': 204,
# workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search( 'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
# [
# ('rfid_code', '=', rfid_code), ('type', '=', '上产线'),
# ('production_id', '=', order.production_id.id),
# ('workorder_id', '=', order.id),
# ('workorder_state', '=', 'done')])
# if workpiece_delivery.status == '待下发':
# workpiece_delivery.write({'is_manual_work': True})
# 下发
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
if ret['IsComplete'] is True:
# 向AGV任务调度下发运送空料架任务
workorders = request.env['mrp.workorder'].browse(workorder_ids)
request.env['sf.agv.scheduling'].add_scheduling(ret['DeviceId'], '运送空料架', workorders)
else: else:
res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'} res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'}
else: else:
res = {'Succeed': False, 'ErrorCode': 201, 'Error': '未传DeviceId字段'} res = {'Succeed': False, 'ErrorCode': 201, 'Error': '未传DeviceId字段'}
except RepeatTaskException as e:
logging.info('AGVToProduct error:%s' % e)
except Exception as e: except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)} res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('AGVToProduct error:%s' % e) logging.info('AGVToProduct error:%s' % e)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/AGVDownProduct', type='json', auth='none', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/AGVDownProduct', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
def AGVDownProduct(self, **kw): def AGVDownProduct(self, **kw):
""" """
@@ -568,8 +506,7 @@ class Manufacturing_Connect(http.Controller):
logging.info('ret:%s' % ret) logging.info('ret:%s' % ret)
if 'DeviceId' in ret: if 'DeviceId' in ret:
logging.info('DeviceId:%s' % ret['DeviceId']) logging.info('DeviceId:%s' % ret['DeviceId'])
# delivery_Arr = [] delivery_Arr = []
workorder_ids = []
if 'IsComplete' in ret: if 'IsComplete' in ret:
if ret['IsComplete'] is True or ret['IsComplete'] is False: if ret['IsComplete'] is True or ret['IsComplete'] is False:
for i in range(1, 5): for i in range(1, 5):
@@ -577,59 +514,42 @@ class Manufacturing_Connect(http.Controller):
if f'RfidCode{i}' in ret: if f'RfidCode{i}' in ret:
rfid_code = ret[f'RfidCode{i}'] rfid_code = ret[f'RfidCode{i}']
logging.info('RfidCode:%s' % rfid_code) logging.info('RfidCode:%s' % rfid_code)
if rfid_code is not None and rfid_code != '': domain = [
domain = [ ('rfid_code', '=', rfid_code),
('rfid_code', '=', rfid_code), ('routing_type', '=', 'CNC加工')
('routing_type', '=', 'CNC加工'), ('state', '!=', 'rework') ]
] workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc') if workorder:
if workorder: for order in workorder:
for order in workorder: if order.production_id.production_line_state == '已上产线':
workorder_ids.append(order.id) logging.info(
if order.production_line_state == '已上产线': '制造订单产线状态:%s' % order.production_id.production_line_state)
logging.info( order.production_id.write({'production_line_state': '已下产线'})
'工单产线状态:%s' % order.production_line_state) workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search([
panel_workorder = request.env['mrp.workorder'].sudo().search( ('rfid_code', '=', rfid_code), ('type', '=', '下产线'),
[('rfid_code', '=', rfid_code), ('state', '!=', 'rework'), ('production_id', '=', order.production_id.id)])
('processing_panel', '=', order.processing_panel)]) delivery_Arr.append(workpiece_delivery.id)
if panel_workorder: else:
panel_workorder.write({'production_line_state': '已下产线'}) res = {'Succeed': False, 'ErrorCode': 204,
workorder.write({'state': 'to be detected'}) 'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
# workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search( if delivery_Arr:
# [ logging.info('delivery_Arr:%s' % delivery_Arr)
# ('rfid_code', '=', rfid_code), ('type', '=', '下产线'), delivery_workpiece = request.env['sf.workpiece.delivery'].sudo().search(
# ('production_id', '=', order.production_id.id), [('id', 'in', delivery_Arr)])
# ('workorder_id', '=', order.id), if delivery_workpiece:
# ('workorder_state', '=', 'done')]) logging.info('开始向agv下发下产线任务')
# if workpiece_delivery: agv_site = request.env['sf.agv.site'].sudo().search([])
# delivery_Arr.append(workpiece_delivery.id) if agv_site:
else: has_site = agv_site.update_site_state()
res = {'Succeed': False, 'ErrorCode': 204, if has_site is True:
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']} is_free = delivery_workpiece._check_avgsite_state()
# if delivery_Arr: if is_free is True:
# logging.info('delivery_Arr:%s' % delivery_Arr) delivery_workpiece._delivery_avg()
# delivery_workpiece = request.env['sf.workpiece.delivery'].sudo().search( logging.info('agv下发下产线任务下发完成')
# [('id', 'in', delivery_Arr)])
# if delivery_workpiece:
# logging.info('开始向agv下发下产线任务')
# agv_site = request.env['sf.agv.site'].sudo().search([])
# if agv_site:
# has_site = agv_site.update_site_state()
# if has_site is True:
# is_free = delivery_workpiece._check_avgsite_state()
# if is_free is True:
# delivery_workpiece._delivery_avg()
# logging.info('agv下发下产线任务下发完成')
if ret['IsComplete'] is True:
# 向AGV任务调度下发下产线任务
workorders = request.env['mrp.workorder'].browse(workorder_ids)
request.env['sf.agv.scheduling'].add_scheduling(ret['DeviceId'], '下产线', workorders)
else: else:
res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'} res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'}
except RepeatTaskException as e:
logging.info('AGVToProduct error:%s' % e)
except Exception as e: except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)} res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('AGVDownProduct error:%s' % e) logging.info('AGVDownProduct error:%s' % e)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@@ -667,32 +587,3 @@ class Manufacturing_Connect(http.Controller):
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e} res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('AGVDownProduct error:%s' % e) logging.info('AGVDownProduct error:%s' % e)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@http.route('/AutoDeviceApi/AgvStationState', type='json', auth='public', methods=['GET', 'POST'], csrf=False,
cors="*")
def AGVStationState(self, **kw):
"""
中控推送接驳站状态
:param kw:
:return:
"""
logging.info('AGVStationState:%s' % kw)
try:
res = {'Succeed': True}
datas = request.httprequest.data
ret = json.loads(datas)
request.env['center_control.interface.log'].sudo().create(
{'content': ret, 'name': 'AutoDeviceApi/AGVStationState'})
logging.info('ret:%s' % ret)
ret = ret['param']
params = {}
for i in range(len(ret)):
if 'DeviceId' in ret[i] and 'AtHome' in ret[i]:
logging.info('DeviceId:%s, AtHome:%s' % (ret[i]['DeviceId'], ret[i]['AtHome']))
params[ret[i]['DeviceId']] = '占用' if ret[i]['AtHome'] else '空闲'
if params:
request.env['sf.agv.site'].update_site_state(params)
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': str(e)}
logging.info('AGVDownProduct error:%s' % e)
return json.JSONEncoder().encode(res)

View File

@@ -25,14 +25,15 @@ class Workpiece(http.Controller):
if 'reqCode' in ret: if 'reqCode' in ret:
if 'method' in ret: if 'method' in ret:
if ret['method'] == 'end': if ret['method'] == 'end':
# 找到对应的AGV调度任务 req_codes = ret['reqCode'].split(',')
agv_scheduling = request.env['sf.agv.scheduling'].sudo().search( for req_code in req_codes:
[('name', '=', ret['reqCode']), ('state', '=', '配送中')]) workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
if agv_scheduling: [('name', '=', req_code.strip()), ('task_completion_time', '=', False)])
agv_scheduling.finish_scheduling() if workpiece_delivery:
else: workpiece_delivery.write({'status': '已配送', 'task_completion_time': datetime.now()})
res = {'Succeed': False, 'ErrorCode': 203, else:
'Error': '该reqCode暂未查到对应的AGV任务记录'} res = {'Succeed': False, 'ErrorCode': 203,
'Error': '该reqCode暂未查到对应的工件配送记录'}
else: else:
res = {'Succeed': False, 'ErrorCode': 204, 'Error': '未传method字段'} res = {'Succeed': False, 'ErrorCode': 204, 'Error': '未传method字段'}
else: else:

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="0">
<record id="sequence_agv_scheduling" model="ir.sequence">
<field name="name">AGV调度</field>
<field name="code">sf.agv.scheduling</field>
<field name="prefix">B%(year)s%(month)s%(day)s</field>
<field name="padding">4</field>
<field name="number_next">1</field>
<field name="implementation">standard</field>
<field name="use_date_range">True</field>
<field name="date_range_period">day</field>
<field name="company_id" eval="False"/>
</record>
</data>
</odoo>

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="panel_zm" model="sf.processing.panel">
<field name="name">ZM</field>
</record>
<record id="panel_fm" model="sf.processing.panel">
<field name="name">FM</field>
</record>
<record id="panel_yc" model="sf.processing.panel">
<field name="name">YC</field>
</record>
<record id="panel_zc" model="sf.processing.panel">
<field name="name">ZC</field>
</record>
<record id="panel_qc" model="sf.processing.panel">
<field name="name">QC</field>
</record>
<record id="panel_hc" model="sf.processing.panel">
<field name="name">HC</field>
</record>
</data>
</odoo>

View File

@@ -1,16 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<data noupdate="1"> <data noupdate="1">
<record model="ir.cron" id="ir_cron_mrp_production">
<field name="name">返工且编程中的制造订单定时获取Cloud编程单状态</field>
<field name="model_id" ref="model_mrp_production"/>
<field name="state">code</field>
<field name="code">model._cron_get_programming_state()</field>
<field name="interval_number">3</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
</record>
<record id="sequence_routing_workcenter" model="ir.sequence"> <record id="sequence_routing_workcenter" model="ir.sequence">
<field name="name">工序编码规则</field> <field name="name">工序编码规则</field>
<field name="code">mrp.routing.workcenter</field> <field name="code">mrp.routing.workcenter</field>

View File

@@ -9,5 +9,3 @@ from . import stock
from . import res_user from . import res_user
from . import production_line_base from . import production_line_base
from . import agv_setting from . import agv_setting
from . import agv_scheduling
from . import res_config_setting

View File

@@ -1,282 +0,0 @@
import logging
import requests
from odoo import models, fields, api, _
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
class RepeatTaskException(UserError):
pass
class AgvScheduling(models.Model):
_name = 'sf.agv.scheduling'
_description = 'agv调度'
_order = 'id desc'
name = fields.Char('任务单号', index=True, copy=False)
def _get_agv_route_type_selection(self):
return self.env['sf.agv.task.route'].fields_get(['route_type'])['route_type']['selection']
agv_route_type = fields.Selection(selection=_get_agv_route_type_selection, string='任务类型', required=True)
agv_route_id = fields.Many2one('sf.agv.task.route', '任务路线')
start_site_id = fields.Many2one('sf.agv.site', '起点接驳站', required=True)
end_site_id = fields.Many2one('sf.agv.site', '终点接驳站', tracking=True)
site_state = fields.Selection([
('占用', '占用'),
('空闲', '空闲')], string='终点接驳站状态', default='占用')
state = fields.Selection([
('待下发', '待下发'),
('配送中', '配送中'),
('已配送', '已配送'),
('已取消', '已取消')], string='状态', default='待下发', tracking=True)
workorder_ids = fields.Many2many('mrp.workorder', 'sf_agv_scheduling_mrp_workorder_ref', string='关联工单')
task_create_time = fields.Datetime('任务创建时间')
task_delivery_time = fields.Datetime('任务下发时间')
task_completion_time = fields.Datetime('任务完成时间')
task_duration = fields.Char('任务时长', compute='_compute_task_duration')
@api.depends('agv_route_type')
def _compute_delivery_workpieces(self):
for record in self:
if record.agv_route_type == '运送空料架':
record.delivery_workpieces = '/'
else:
record.delivery_workpieces = ''.join(record.workorder_ids.mapped('production_id.name'))
delivery_workpieces = fields.Char('配送工件', compute=_compute_delivery_workpieces)
@api.model
def web_search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, count_limit=None):
domain = domain or []
new_domain = []
for item in domain:
if isinstance(item, list):
if item[0] == 'delivery_workpieces':
new_domain.append('&')
new_domain.append(['workorder_ids.production_id.name', item[1], item[2]])
new_domain.append(['agv_route_type', '!=', '运送空料架'])
continue
new_domain.append(item)
return super(AgvScheduling, self).web_search_read(new_domain, fields, offset, limit, order, count_limit)
@api.depends('task_completion_time', 'task_delivery_time')
def _compute_task_duration(self):
for rec in self:
if rec.task_completion_time and rec.task_delivery_time:
rec.task_duration = str(rec.task_completion_time - rec.task_delivery_time)
else:
rec.task_duration = ''
@api.model_create_multi
def create(self, vals_list):
# We generate a standard reference
for vals in vals_list:
vals['name'] = self.env['ir.sequence'].next_by_code('sf.agv.scheduling') or _('New')
return super().create(vals_list)
def add_scheduling(self, agv_start_site_name, agv_route_type, workorders):
""" add_scheduling(agv_start_site_id, agv_route_type, workorders) -> agv_scheduling
新增AGV调度
params:
agv_start_site_name: AGV起点接驳站名称
agv_route_type: AGV任务类型
workorders: 工单
"""
_logger.info('创建AGV调度任务\r\n起点为【%s】,任务类型为【%s】,工单为【%s' % (agv_start_site_name, agv_route_type, workorders))
if not workorders:
raise UserError(_('工单不能为空'))
agv_start_site = self.env['sf.agv.site'].sudo().search([('name', '=', agv_start_site_name)], limit=1)
if not agv_start_site:
raise UserError(_('不存在名称为【%s】的接驳站,请先创建!' % agv_start_site_name))
# 如果存在相同任务类型工单的AGV调度任务则提示错误
agv_scheduling = self.sudo().search([
('workorder_ids', 'in', workorders.ids),
('agv_route_type', '=', agv_route_type),
('state', 'in', ['待下发', '配送中'])
], limit=1)
if agv_scheduling:
# 计算agv_scheduling.workorder_ids与workorders的交集
repetitive_workorders = agv_scheduling.workorder_ids & workorders
raise RepeatTaskException(
'制造订单号【%s】已存在于【%s】AGV调度任务请勿重复下发' %
(','.join(repetitive_workorders.mapped('production_id.name')), agv_scheduling.name)
)
vals = {
'start_site_id': agv_start_site.id,
'agv_route_type': agv_route_type,
'workorder_ids': workorders.ids,
# 'workpiece_delivery_ids': deliveries.mapped('id') if deliveries else [],
'task_create_time': fields.Datetime.now()
}
# 如果只有唯一任务路线,则自动赋予终点接驳站跟任务名称
agv_routes = self.env['sf.agv.task.route'].sudo().search([
('route_type', '=', agv_route_type),
('start_site_id', '=', agv_start_site.id)
])
if not agv_routes:
raise UserError(_('不存在起点为【%s】的【%s】任务路线,请先创建!' % (agv_start_site_name, agv_route_type)))
idle_route = None
if len(agv_routes) == 1:
idle_route = agv_routes[0]
vals.update({'end_site_id': idle_route.end_site_id.id, 'agv_route_id': idle_route.id})
else:
# 判断终点接驳站是否为空闲
idle_routes = agv_routes.filtered(lambda r: r.end_site_id.state == '空闲')
if idle_routes:
# 将空闲的路线按照终点接驳站名称排序
idle_routes = sorted(idle_routes, key=lambda r: r.end_site_id.name)
idle_route = idle_routes[0]
vals.update({'end_site_id': idle_route.end_site_id.id, 'agv_route_id': idle_route.id})
try:
scheduling = self.env['sf.agv.scheduling'].sudo().create(vals)
# 触发空闲接驳站状态更新,触发新任务下发
if idle_route and idle_route.end_site_id.state == '空闲':
scheduling.dispatch_scheduling(idle_route)
except Exception as e:
_logger.error('添加AGV调度任务失败: %s', e)
raise UserError(_('添加AGV调度任务失败: %s', e))
return scheduling
def on_site_state_change(self, agv_site_id, agv_site_state):
"""
响应AGV接驳站站点状态变化
params:
agv_site_id: 接驳站ID
agv_site_state: 站点状态('空闲', '占用'
"""
if agv_site_state == '空闲':
# 查询终点接驳站为agv_site_id的AGV路线
task_routes = self.env['sf.agv.task.route'].sudo().search([('end_site_id', '=', agv_site_id)])
agv_scheduling = self.env['sf.agv.scheduling'].sudo().search(
[('state', '=', '待下发'), ('agv_route_type', 'in', task_routes.mapped('route_type'))],
order='id asc',
limit=1
)
task_route = task_routes.filtered(
lambda r: r.start_site_id == agv_scheduling.start_site_id and r.start_site_id == agv_scheduling.start_site_id
)
if task_route:
# 下发AGV调度任务并修改接驳站状态为占用
agv_scheduling.dispatch_scheduling(task_route)
def _delivery_avg(self):
config = self.env['res.config.settings'].get_values()
position_code_arr = [{
'positionCode': self.start_site_id.name,
'code': '00'
}, {
'positionCode': self.end_site_id.name,
'code': '00'
}]
res = {'reqCode': self.name, 'reqTime': '', 'clientCode': '', 'tokenCode': '',
'taskTyp': 'F01', 'ctnrTyp': '', 'ctnrCode': '', 'wbCode': config['wbcode'],
'positionCodePath': position_code_arr,
'podCode': '',
'podDir': '', 'materialLot': '', 'priority': '', 'taskCode': '', 'agvCode': '', 'materialLot': '',
'data': ''}
try:
logging.info('AGV请求路径:%s' % config['agv_rcs_url'])
logging.info('AGV-json:%s' % res)
headers = {'Content-Type': 'application/json'}
ret = requests.post((config['agv_rcs_url']), json=res, headers=headers)
ret = ret.json()
logging.info('config-ret:%s' % ret)
if ret['code'] == 0:
return True
else:
raise UserError(ret['message'])
except Exception as e:
logging.info('config-e:%s' % e)
raise UserError("工件配送请求agv失败:%s" % e)
def button_cancel(self):
# 弹出二次确认窗口后执行
for rec in self:
if rec.state != '待下发':
raise UserError('只有待下发状态的AGV调度任务才能取消')
rec.state = '已取消'
def finish_scheduling(self):
"""
完成调度任务
"""
for rec in self:
if rec.state != '配送中':
return False
_logger.info('AGV任务调度完成任务%s' % rec)
rec.state = '已配送'
rec.task_completion_time = fields.Datetime.now()
def dispatch_scheduling(self, agv_task_route):
"""
下发调度任务
params:
agv_route sf.agv.task.route对象
"""
for rec in self:
if rec.state != '待下发':
return False
_logger.info('AGV任务调度下发调度任务路线为%s' % agv_task_route)
rec.state = '配送中'
rec.task_delivery_time = fields.Datetime.now()
rec.site_state = '空闲'
rec.end_site_id = agv_task_route.end_site_id.id
rec.agv_route_id = agv_task_route.id
is_agv_task_dispatch = self.env['ir.config_parameter'].sudo().get_param('is_agv_task_dispatch')
if is_agv_task_dispatch:
rec._delivery_avg()
# 更新接驳站状态
rec.env['sf.agv.site'].update_site_state({rec.end_site_id.name: '占用'}, False)
def write(self, vals):
if vals.get('state', False):
if vals['state'] == '已取消':
self.env['sf.workpiece.delivery'].search([('agv_scheduling_id', '=', self.id)]).write({'status': '待下发'})
elif vals['state'] == '已配送':
self.env['sf.workpiece.delivery'].search([('agv_scheduling_id', '=', self.id)]).write({
'status': '已配送',
'feeder_station_destination_id': self.end_site_id.id,
'route_id': self.agv_route_id.id,
'task_completion_time': fields.Datetime.now()
})
elif vals['state'] == '配送中':
self.env['sf.workpiece.delivery'].search([('agv_scheduling_id', '=', self.id)]).write({
'feeder_station_destination_id': self.end_site_id.id,
'route_id': self.agv_route_id.id,
'task_delivery_time': fields.Datetime.now()
})
return super().write(vals)
class ResMrpWorkOrder(models.Model):
_inherit = 'mrp.workorder'
agv_scheduling_ids = fields.Many2many(
'sf.agv.scheduling',
'sf_agv_scheduling_mrp_workorder_ref',
string='AGV调度',
domain=[('state', '!=', '已取消')])
def get_down_product_agv_scheduling(self):
"""
获取关联的制造订单下产线的agv任务
"""
self.ensure_one()
workorder_ids = self.production_id.workorder_ids
cnc_workorder = workorder_ids.filtered(
lambda w: w.routing_type == 'CNC加工' and w.state == 'done' and w.processing_panel == self.processing_panel
)
if cnc_workorder:
agv_schedulingss = cnc_workorder.agv_scheduling_ids
return agv_schedulingss.filtered(lambda a: a.state == '已配送' and a.agv_route_type == '下产线')
else:
return None

Some files were not shown because too many files have changed in this diff Show More