Compare commits

..

6 Commits

380 changed files with 92309 additions and 22472 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

@@ -6,6 +6,6 @@ import { patch } from "web.utils";
patch(WebClient.prototype, "kolpolok_custom_title_and_favicon.WebClient", { patch(WebClient.prototype, "kolpolok_custom_title_and_favicon.WebClient", {
setup() { setup() {
this._super(); this._super();
// this.title.setParts({ zopenerp: "JIKIMO" }); this.title.setParts({ zopenerp: "JIKIMO" });
}, },
}); });

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

@@ -5,9 +5,9 @@
<!-- 修改页面头部图标及文字 --> <!-- 修改页面头部图标及文字 -->
<template id="favicon_icon" inherit_id="web.layout" name="Web layout"> <template id="favicon_icon" inherit_id="web.layout" name="Web layout">
<!-- change the title with reliance partner --> <!-- change the title with reliance partner -->
<!-- <xpath expr="//head//title" position="before"> <xpath expr="//head//title" position="before">
<title t-esc="'JIKIMO'"/> <title t-esc="'JIKIMO'"/>
</xpath> --> </xpath>
<!-- change the default favicon icon with --> <!-- change the default favicon icon with -->
<xpath expr="//head//link[@rel='shortcut icon']" position="replace"> <xpath expr="//head//link[@rel='shortcut icon']" position="replace">
<link type="image/x-icon" rel="shortcut icon" href="/jikimo_frontend/static/src/img/jikimo-logo.ico"/> <link type="image/x-icon" rel="shortcut icon" href="/jikimo_frontend/static/src/img/jikimo-logo.ico"/>
@@ -16,7 +16,7 @@
<!-- hide 登录页面 powerd by odoo 及管理数据库 --> <!-- hide 登录页面 powerd by odoo 及管理数据库 -->
<template id="login_page_layout" inherit_id="web.login_layout" name="Login Page Layout"> <template id="login_page_layout" inherit_id="web.login_layout" name="Login Page Layout">
<!-- <xpath expr="//div[@class='card-body']/div[last()]" position="replace"></xpath> --> <xpath expr="//div[@class='card-body']//div[last()]" position="replace"></xpath>
</template> </template>
<!-- 隐藏odoo版本信息 --> <!-- 隐藏odoo版本信息 -->

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 533 B

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/系统工单.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

@@ -27,7 +27,7 @@ class MrpWorkcenter(models.Model):
class MrpProductionWorkcenterLine(models.Model): class MrpProductionWorkcenterLine(models.Model):
_name = 'mrp.workorder' _name = 'mrp.workorder'
_inherit = ['mrp.workorder', 'barcodes.barcode_events_mixin', 'mail.thread', 'mail.activity.mixin'] _inherit = ['mrp.workorder', 'barcodes.barcode_events_mixin']
quality_point_ids = fields.Many2many('quality.point', compute='_compute_quality_point_ids', store=True) quality_point_ids = fields.Many2many('quality.point', compute='_compute_quality_point_ids', store=True)
quality_point_count = fields.Integer('Steps', compute='_compute_quality_point_count') quality_point_count = fields.Integer('Steps', compute='_compute_quality_point_count')
@@ -47,17 +47,14 @@ class MrpProductionWorkcenterLine(models.Model):
is_last_lot = fields.Boolean('Is Last lot', compute='_compute_is_last_lot') is_last_lot = fields.Boolean('Is Last lot', compute='_compute_is_last_lot')
is_first_started_wo = fields.Boolean('Is The first Work Order', compute='_compute_is_last_unfinished_wo') is_first_started_wo = fields.Boolean('Is The first Work Order', compute='_compute_is_last_unfinished_wo')
is_last_unfinished_wo = fields.Boolean('Is Last Work Order To Process', compute='_compute_is_last_unfinished_wo', is_last_unfinished_wo = fields.Boolean('Is Last Work Order To Process', compute='_compute_is_last_unfinished_wo', store=False)
store=False)
lot_id = fields.Many2one(related='current_quality_check_id.lot_id', readonly=False) lot_id = fields.Many2one(related='current_quality_check_id.lot_id', readonly=False)
move_id = fields.Many2one(related='current_quality_check_id.move_id', readonly=False) move_id = fields.Many2one(related='current_quality_check_id.move_id', readonly=False)
move_line_id = fields.Many2one(related='current_quality_check_id.move_line_id', readonly=False) move_line_id = fields.Many2one(related='current_quality_check_id.move_line_id', readonly=False)
move_line_ids = fields.One2many(related='move_id.move_line_ids') move_line_ids = fields.One2many(related='move_id.move_line_ids')
quality_state = fields.Selection(related='current_quality_check_id.quality_state', string="Quality State", quality_state = fields.Selection(related='current_quality_check_id.quality_state', string="Quality State", readonly=False)
readonly=False)
qty_done = fields.Float(related='current_quality_check_id.qty_done', readonly=False) qty_done = fields.Float(related='current_quality_check_id.qty_done', readonly=False)
test_type_id = fields.Many2one('quality.point.test_type', 'Test Type', test_type_id = fields.Many2one('quality.point.test_type', 'Test Type', related='current_quality_check_id.test_type_id')
related='current_quality_check_id.test_type_id')
test_type = fields.Char(related='test_type_id.technical_name') test_type = fields.Char(related='test_type_id.technical_name')
user_id = fields.Many2one(related='current_quality_check_id.user_id', readonly=False) user_id = fields.Many2one(related='current_quality_check_id.user_id', readonly=False)
worksheet_page = fields.Integer('Worksheet page') worksheet_page = fields.Integer('Worksheet page')
@@ -68,8 +65,7 @@ class MrpProductionWorkcenterLine(models.Model):
def _compute_quality_point_ids(self): def _compute_quality_point_ids(self):
for workorder in self: for workorder in self:
quality_points = workorder.operation_id.quality_point_ids quality_points = workorder.operation_id.quality_point_ids
quality_points = quality_points.filtered( quality_points = quality_points.filtered(lambda qp: not qp.product_ids or workorder.production_id.product_id in qp.product_ids)
lambda qp: not qp.product_ids or workorder.production_id.product_id in qp.product_ids)
workorder.quality_point_ids = quality_points workorder.quality_point_ids = quality_points
@api.depends('operation_id') @api.depends('operation_id')
@@ -95,8 +91,7 @@ class MrpProductionWorkcenterLine(models.Model):
@api.depends('check_ids') @api.depends('check_ids')
def _compute_finished_product_check_ids(self): def _compute_finished_product_check_ids(self):
for wo in self: for wo in self:
wo.finished_product_check_ids = wo.check_ids.filtered( wo.finished_product_check_ids = wo.check_ids.filtered(lambda c: c.finished_product_sequence == wo.qty_produced)
lambda c: c.finished_product_sequence == wo.qty_produced)
def write(self, values): def write(self, values):
res = super().write(values) res = super().write(values)
@@ -143,8 +138,7 @@ class MrpProductionWorkcenterLine(models.Model):
self.finished_lot_id = self.env['stock.lot'].create({ self.finished_lot_id = self.env['stock.lot'].create({
'product_id': self.product_id.id, 'product_id': self.product_id.id,
'company_id': self.company_id.id, 'company_id': self.company_id.id,
'name': self.env['stock.lot']._get_next_serial(self.company_id, self.product_id) or self.env[ 'name': self.env['stock.lot']._get_next_serial(self.company_id, self.product_id) or self.env['ir.sequence'].next_by_code('stock.lot.serial'),
'ir.sequence'].next_by_code('stock.lot.serial'),
}) })
def _create_subsequent_checks(self): def _create_subsequent_checks(self):
@@ -158,7 +152,7 @@ class MrpProductionWorkcenterLine(models.Model):
""" """
# Create another quality check if necessary # Create another quality check if necessary
next_check = self.current_quality_check_id.next_check_id next_check = self.current_quality_check_id.next_check_id
if next_check.component_id != self.current_quality_check_id.product_id or \ if next_check.component_id != self.current_quality_check_id.product_id or\
next_check.point_id != self.current_quality_check_id.point_id: next_check.point_id != self.current_quality_check_id.point_id:
# TODO: manage reservation here # TODO: manage reservation here
@@ -285,8 +279,7 @@ class MrpProductionWorkcenterLine(models.Model):
if self.current_quality_check_id: if self.current_quality_check_id:
team = self.current_quality_check_id.team_id team = self.current_quality_check_id.team_id
else: else:
team = self.env['quality.alert.team'].search( team = self.env['quality.alert.team'].search(['|', ('company_id', '=', self.company_id.id), ('company_id', '=', False)], limit=1)
['|', ('company_id', '=', self.company_id.id), ('company_id', '=', False)], limit=1)
return { return {
'type': 'ir.actions.act_window', 'type': 'ir.actions.act_window',
'res_model': 'quality.check', 'res_model': 'quality.check',
@@ -327,8 +320,7 @@ class MrpProductionWorkcenterLine(models.Model):
production = wo.production_id production = wo.production_id
move_raw_ids = wo.move_raw_ids.filtered(lambda m: m.state not in ('done', 'cancel')) move_raw_ids = wo.move_raw_ids.filtered(lambda m: m.state not in ('done', 'cancel'))
move_finished_ids = wo.move_finished_ids.filtered( move_finished_ids = wo.move_finished_ids.filtered(lambda m: m.state not in ('done', 'cancel') and m.product_id != wo.production_id.product_id)
lambda m: m.state not in ('done', 'cancel') and m.product_id != wo.production_id.product_id)
previous_check = self.env['quality.check'] previous_check = self.env['quality.check']
for point in wo.quality_point_ids: for point in wo.quality_point_ids:
# Check if we need a quality control for this point # Check if we need a quality control for this point
@@ -350,13 +342,11 @@ class MrpProductionWorkcenterLine(models.Model):
if point.test_type == 'register_byproducts': if point.test_type == 'register_byproducts':
moves = move_finished_ids.filtered(lambda m: m.product_id == point.component_id) moves = move_finished_ids.filtered(lambda m: m.product_id == point.component_id)
if not moves: if not moves:
moves = production.move_finished_ids.filtered( moves = production.move_finished_ids.filtered(lambda m: not m.operation_id and m.product_id == point.component_id)
lambda m: not m.operation_id and m.product_id == point.component_id)
elif point.test_type == 'register_consumed_materials': elif point.test_type == 'register_consumed_materials':
moves = move_raw_ids.filtered(lambda m: m.product_id == point.component_id) moves = move_raw_ids.filtered(lambda m: m.product_id == point.component_id)
if not moves: if not moves:
moves = production.move_raw_ids.filtered( moves = production.move_raw_ids.filtered(lambda m: not m.operation_id and m.product_id == point.component_id)
lambda m: not m.operation_id and m.product_id == point.component_id)
else: else:
check = self.env['quality.check'].create(values) check = self.env['quality.check'].create(values)
previous_check.next_check_id = check previous_check.next_check_id = check
@@ -373,10 +363,8 @@ class MrpProductionWorkcenterLine(models.Model):
processed_move |= moves processed_move |= moves
# Generate quality checks associated with unreferenced components # Generate quality checks associated with unreferenced components
moves_without_check = ((move_raw_ids | move_finished_ids) - processed_move).filtered(lambda move: ( moves_without_check = ((move_raw_ids | move_finished_ids) - processed_move).filtered(lambda move: (move.has_tracking != 'none' and not move.raw_material_production_id.use_auto_consume_components_lots) or move.operation_id)
move.has_tracking != 'none' and not move.raw_material_production_id.use_auto_consume_components_lots) or move.operation_id) quality_team_id = self.env['quality.alert.team'].search(['|', ('company_id', '=', wo.company_id.id), ('company_id', '=', False)], limit=1).id
quality_team_id = self.env['quality.alert.team'].search(
['|', ('company_id', '=', wo.company_id.id), ('company_id', '=', False)], limit=1).id
for move in moves_without_check: for move in moves_without_check:
values = { values = {
'production_id': production.id, 'production_id': production.id,
@@ -424,8 +412,7 @@ class MrpProductionWorkcenterLine(models.Model):
backorder = False backorder = False
# Trigger the backorder process if we produce less than expected # Trigger the backorder process if we produce less than expected
if float_compare(self.qty_producing, self.qty_remaining, if float_compare(self.qty_producing, self.qty_remaining, precision_rounding=self.product_uom_id.rounding) == -1 and self.is_first_started_wo:
precision_rounding=self.product_uom_id.rounding) == -1 and self.is_first_started_wo:
backorder = self.production_id._split_productions()[1:] backorder = self.production_id._split_productions()[1:]
for workorder in backorder.workorder_ids: for workorder in backorder.workorder_ids:
if workorder.product_tracking == 'serial': if workorder.product_tracking == 'serial':
@@ -436,8 +423,7 @@ class MrpProductionWorkcenterLine(models.Model):
else: else:
if self.operation_id: if self.operation_id:
backorder = (self.production_id.procurement_group_id.mrp_production_ids - self.production_id).filtered( backorder = (self.production_id.procurement_group_id.mrp_production_ids - self.production_id).filtered(
lambda p: p.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_id).state not in ( lambda p: p.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_id).state not in ('cancel', 'done')
'cancel', 'done')
)[:1] )[:1]
else: else:
index = list(self.production_id.workorder_ids).index(self) index = list(self.production_id.workorder_ids).index(self)
@@ -456,8 +442,7 @@ class MrpProductionWorkcenterLine(models.Model):
wo.current_quality_check_id._update_component_quantity() wo.current_quality_check_id._update_component_quantity()
if not self.env.context.get('no_start_next'): if not self.env.context.get('no_start_next'):
if self.operation_id: if self.operation_id:
return backorder.workorder_ids.filtered( return backorder.workorder_ids.filtered(lambda wo: wo.operation_id == self.operation_id).open_tablet_view()
lambda wo: wo.operation_id == self.operation_id).open_tablet_view()
else: else:
index = list(self.production_id.workorder_ids).index(self) index = list(self.production_id.workorder_ids).index(self)
return backorder.workorder_ids[index].open_tablet_view() return backorder.workorder_ids[index].open_tablet_view()
@@ -481,8 +466,7 @@ class MrpProductionWorkcenterLine(models.Model):
def open_tablet_view(self): def open_tablet_view(self):
self.ensure_one() self.ensure_one()
if not self.is_user_working and self.working_state != 'blocked' and self.state in ( if not self.is_user_working and self.working_state != 'blocked' and self.state in ('ready', 'waiting', 'progress', 'pending'):
'ready', 'waiting', 'progress', 'pending'):
self.button_start() self.button_start()
action = self.env["ir.actions.actions"]._for_xml_id("mrp_workorder.tablet_client_action") action = self.env["ir.actions.actions"]._for_xml_id("mrp_workorder.tablet_client_action")
action['target'] = 'fullscreen' action['target'] = 'fullscreen'
@@ -537,8 +521,7 @@ class MrpProductionWorkcenterLine(models.Model):
data = { data = {
'mrp.workorder': self.read(self._get_fields_for_tablet(), load=False)[0], 'mrp.workorder': self.read(self._get_fields_for_tablet(), load=False)[0],
'quality.check': self.check_ids._get_fields_for_tablet(sorted_check_list), 'quality.check': self.check_ids._get_fields_for_tablet(sorted_check_list),
'operation': self.operation_id.read(self.operation_id._get_fields_for_tablet())[ 'operation': self.operation_id.read(self.operation_id._get_fields_for_tablet())[0] if self.operation_id else {},
0] if self.operation_id else {},
'working_state': self.workcenter_id.working_state, 'working_state': self.workcenter_id.working_state,
'views': { 'views': {
'workorder': self.env.ref('mrp_workorder.mrp_workorder_view_form_tablet').id, 'workorder': self.env.ref('mrp_workorder.mrp_workorder_view_form_tablet').id,
@@ -570,8 +553,7 @@ class MrpProductionWorkcenterLine(models.Model):
return { return {
'duration': self.duration, 'duration': self.duration,
'position': bisect_left(last30op, self.duration), 'position': bisect_left(last30op, self.duration), # which position regarded other workorders ranked by duration
# which position regarded other workorders ranked by duration
'quality_score': score, 'quality_score': score,
'show_rainbow': show_rainbow, 'show_rainbow': show_rainbow,
} }

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

@@ -27,13 +27,6 @@
</field> </field>
</page> </page>
</page> </page>
<xpath expr="//sheet" position="after">
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="activity_ids"/>
<field name="message_ids" options="{'post_refresh': 'recipients'}"/>
</div>
</xpath>
</field> </field>
</record> </record>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 702 B

View File

@@ -1024,7 +1024,7 @@
<menuitem <menuitem
id="menu_quality_root" id="menu_quality_root"
name="Quality" name="Quality"
web_icon="quality_control,static/description/质量.png" web_icon="quality_control,static/description/icon.svg"
sequence="150" sequence="150"
groups="quality.group_quality_user"/> groups="quality.group_quality_user"/>

View File

@@ -1,3 +1,2 @@
pystrich pystrich
cpca cpca
pycryptodome==3.20

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

@@ -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

@@ -321,7 +321,7 @@ class ToolInventory(models.Model):
prefix = fields.Char('前缀') prefix = fields.Char('前缀')
postfix = fields.Char('后缀') postfix = fields.Char('后缀')
diameter = fields.Float('直径(mm)') diameter = fields.Float('直径(mm)')
angle = fields.Float('R角(mm)',default=0) angle = fields.Float('R角(mm)')
tool_length = fields.Float('刀具总长(mm)') tool_length = fields.Float('刀具总长(mm)')
blade_length = fields.Float('避空长/刃长(mm)') blade_length = fields.Float('避空长/刃长(mm)')
knife_head_name = fields.Char('刀头名称') knife_head_name = fields.Char('刀头名称')
@@ -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

@@ -21,9 +21,8 @@ class ToolMaterialsBasicParameters(models.Model):
neck_length = fields.Float('颈部长度(mm)') neck_length = fields.Float('颈部长度(mm)')
handle_diameter = fields.Float('柄部直径(mm)') handle_diameter = fields.Float('柄部直径(mm)')
handle_length = fields.Float('柄部长度(mm)') handle_length = fields.Float('柄部长度(mm)')
blade_tip_diameter = fields.Float('刀尖直径(mm)') blade_tip_diameter = fields.Integer('刀尖直径(mm)')
blade_tip_working_size = fields.Char('刀尖倒角度)', size=20) blade_tip_working_size = fields.Char('刀尖处理尺寸(R半径mm/倒角度)', size=20)
tip_r_size = fields.Float('刀尖R角(mm)',default=0)
blade_tip_taper = fields.Integer('刀尖锥度(°)') blade_tip_taper = fields.Integer('刀尖锥度(°)')
blade_diameter = fields.Float('刃部直径(mm)') blade_diameter = fields.Float('刃部直径(mm)')
blade_length = fields.Float('刃部长度(mm)') blade_length = fields.Float('刃部长度(mm)')
@@ -38,7 +37,7 @@ class ToolMaterialsBasicParameters(models.Model):
width = fields.Float('宽度(mm)') width = fields.Float('宽度(mm)')
cutting_blade_length = fields.Float('切削刃长(mm)') cutting_blade_length = fields.Float('切削刃长(mm)')
relief_angle = fields.Integer('后角(°)') relief_angle = fields.Integer('后角(°)')
blade_tip_circular_arc_radius = fields.Char('刀尖圆弧半径(mm)', size=20,default='0') blade_tip_circular_arc_radius = fields.Char('刀尖圆弧半径(mm)', size=20)
inscribed_circle_diameter = fields.Float('内接圆直径IC/D(mm)') inscribed_circle_diameter = fields.Float('内接圆直径IC/D(mm)')
install_aperture_diameter = fields.Float('安装孔直径(mm)') install_aperture_diameter = fields.Float('安装孔直径(mm)')
chip_breaker_groove = fields.Selection([('', ''), ('单面', '单面'), ('双面', '双面')], chip_breaker_groove = fields.Selection([('', ''), ('单面', '单面'), ('双面', '双面')],

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
@@ -242,8 +242,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
242
243
244

View File

@@ -1,62 +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"),
"O-CMD.FLUSHED": () => customClickOnButton(".jikimo_button_flushed"),
};
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

@@ -159,6 +159,9 @@ td.o_required_modifier {
display:inline; display:inline;
} }
.diameter{ .diameter{
display: flex !important;
justify-content: flex-start !important;
align-items: center !important;
} }
.o_address_format { .o_address_format {
display: flex !important; display: flex !important;

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

@@ -15,7 +15,6 @@
<field name="handle_length"/> <field name="handle_length"/>
<field name="blade_tip_diameter"/> <field name="blade_tip_diameter"/>
<field name="blade_tip_working_size"/> <field name="blade_tip_working_size"/>
<field name="tip_r_size"/>
<field name="blade_tip_taper"/> <field name="blade_tip_taper"/>
<field name="blade_diameter"/> <field name="blade_diameter"/>
<field name="blade_length"/> <field name="blade_length"/>
@@ -96,7 +95,6 @@
<field name="handle_length"/> <field name="handle_length"/>
<field name="blade_tip_diameter"/> <field name="blade_tip_diameter"/>
<field name="blade_tip_working_size"/> <field name="blade_tip_working_size"/>
<field name="tip_r_size"/>
<field name="blade_tip_taper"/> <field name="blade_tip_taper"/>
<field name="blade_diameter"/> <field name="blade_diameter"/>
<field name="blade_length"/> <field name="blade_length"/>
@@ -141,7 +139,6 @@
</group> </group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')]}"> <group attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')]}">
<field name="blade_tip_working_size"/> <field name="blade_tip_working_size"/>
<field name="tip_r_size"/>
<field name="blade_tip_diameter" class="diameter"/> <field name="blade_tip_diameter" class="diameter"/>
<field name="blade_tip_taper"/> <field name="blade_tip_taper"/>
<field name="blade_helix_angle"/> <field name="blade_helix_angle"/>

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>
@@ -222,7 +222,6 @@
<field name="handle_diameter" class="diameter"/> <field name="handle_diameter" class="diameter"/>
<field name="handle_length"/> <field name="handle_length"/>
<field name="blade_tip_working_size" class="du"/> <field name="blade_tip_working_size" class="du"/>
<field name="tip_r_size"/>
<field name="blade_tip_diameter" class="diameter"/> <field name="blade_tip_diameter" class="diameter"/>
<field name="blade_tip_taper" class="du"/> <field name="blade_tip_taper" class="du"/>
<field name="blade_helix_angle" class="du"/> <field name="blade_helix_angle" class="du"/>
@@ -556,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"/>
@@ -578,7 +577,7 @@
</field> </field>
</record> </record>
<record model="ir.ui.view" id="view_cutting_tool_inventory_search"> <record model="ir.ui.view" id="view_cutting_tool_material_search">
<field name="name">sf.tool.inventory.search</field> <field name="name">sf.tool.inventory.search</field>
<field name="model">sf.tool.inventory</field> <field name="model">sf.tool.inventory</field>
<field name="arch" type="xml"> <field name="arch" type="xml">

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,51 +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" % traceback_error)
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):
@@ -81,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
@@ -229,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>
@@ -37,11 +32,9 @@
options="{'no_create': True}" options="{'no_create': True}"
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}" attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"
placeholder="请选择"/> placeholder="请选择"/>
<field name="brand_id" options="{'no_create': True}" placeholder="请选择"
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_model_id" placeholder="请选择" class="custom_required" <field name="cutting_tool_model_id" placeholder="请选择" class="custom_required"
options="{'no_create': True}" options="{'no_create': True}"
domain="[('cutting_tool_material_id','=',cutting_tool_material_id),('brand_id', '=', brand_id)]" domain="[('cutting_tool_material_id','=',cutting_tool_material_id)]"
context="{'default_cutting_tool_material_id': cutting_tool_material_id}" context="{'default_cutting_tool_material_id': cutting_tool_material_id}"
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"> attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}">
</field> </field>
@@ -55,10 +48,10 @@
<field name="fixture_material_id" <field name="fixture_material_id"
attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}" attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}"
placeholder="请选择" options="{'no_create': True}"/> placeholder="请选择" options="{'no_create': True}"/>
<field name="fixture_model_id" string="型号名称" placeholder="请选择" options="{'no_create': True}" <field name="fixture_model_id" string="型号" placeholder="请选择" options="{'no_create': True}"
attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}" attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}"
domain="[('fixture_material_id','=',fixture_material_id)]"/> domain="[('fixture_material_id','=',fixture_material_id)]"/>
<field name="specification_fixture_id" string="物料号" placeholder="请选择" <field name="specification_fixture_id" string="规格" placeholder="请选择"
options="{'no_create': True}" options="{'no_create': True}"
attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}" attrs="{'invisible': [('categ_type', '!=', '夹具')],'required': [('categ_type', '=', '夹具')]}"
domain="[('fixture_model_id','=',fixture_model_id)]"/> domain="[('fixture_model_id','=',fixture_model_id)]"/>
@@ -93,8 +86,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"
@@ -104,16 +96,6 @@
</group> </group>
</page> </page>
</xpath> </xpath>
<xpath expr="//field[@name='name']" position="attributes">
<attribute name="attrs">{'readonly': ['|',('id','!=',False),('categ_type', '=',
'刀具')], 'required': True}
</attribute>
</xpath>
<!-- <xpath expr="//field[@name='default_code']" position="attributes">-->
<!-- <attribute name="attrs">{'readonly': [('categ_type', '=', '刀具')], 'invisible':-->
<!-- [('product_variant_count', '>' , 1)]}-->
<!-- </attribute>-->
<!-- </xpath>-->
</field> </field>
</record> </record>
@@ -191,8 +173,6 @@
attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_blade_tip_working_size" <field name="cutting_tool_blade_tip_working_size"
attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_blade_tip_r_size"
attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_blade_tip_diameter" string="刀尖直径(mm)" class="diameter" <field name="cutting_tool_blade_tip_diameter" string="刀尖直径(mm)" class="diameter"
attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_blade_tip_taper" string="刀尖锥度(°)" <field name="cutting_tool_blade_tip_taper" string="刀尖锥度(°)"
@@ -313,7 +293,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)]}"/>
@@ -476,8 +456,7 @@
<tree editable="bottom"> <tree editable="bottom">
<!-- <field name="cutting_speed"--> <!-- <field name="cutting_speed"-->
<!-- attrs="{'readonly': [('materials_type_id','!=',False)]}"/>--> <!-- attrs="{'readonly': [('materials_type_id','!=',False)]}"/>-->
<field name="materials_type_id" options="{'no_create': True}" <field name="materials_type_id" options="{'no_create': True}" placeholder="请选择"/>
placeholder="请选择"/>
<field name="blade_diameter"/> <field name="blade_diameter"/>
<field name="feed_per_tooth"/> <field name="feed_per_tooth"/>
</tree> </tree>

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': ['base', '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,28 +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']:
hr_employee = self.sudo().search([('work_email', '=', employee_info['work_email'])])
hr_employee.write({'we_id': employee_info['we_id']})
if hr_employee.user_id:
hr_employee.user_id.write({'we_employee_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

@@ -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,169 +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)
class WorkCenterBarcode(models.Model): class WorkCenterBarcode(models.Model):
@@ -298,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="status"/> --> <field name="signed"/>
<field name="run_status"/> <field name="status"/>
<field name="run_time"/> <field name="time_on"/>
<field name="system_date"/> <field name="time_on_now"/>
<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

@@ -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

@@ -1,41 +1,30 @@
# -*-coding:utf-8-*- # -*-coding:utf-8-*-
from odoo import fields, models, api from odoo import fields, models
class SfMaintenanceLogs(models.Model): class SfMaintenanceLogs(models.Model):
_name = 'sf.maintenance.logs' _name = 'sf.maintenance.logs'
_description = '设备故障日志' _description = '设备故障日志'
_order = 'alarm_time desc'
code = fields.Char(string='编码', readonly=True) code = fields.Char(string='编码')
name = fields.Char(string='名称', compute='_compute_name') 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)
@api.depends('code')
def _compute_name(self):
for record in self:
if record.code:
record.name = self.env['maintenance.equipment'].sudo().search([('code', '=', record.code), ('active', '=', True)]).name
record.maintenance_equipment_id = self.env['maintenance.equipment'].sudo().search([('code', '=', record.code), ('active', '=', True)]).id
else:
record.name = ''

View File

@@ -1,46 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import re
import json
import datetime
import requests
from odoo import api, fields, models, _ from odoo import api, fields, models, _
from odoo.exceptions import UserError
def convert_to_seconds(time_str):
# 修改正则表达式,使 H、M、S 部分可选
if time_str is None:
return 0
pattern = r"(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?"
match = re.match(pattern, time_str)
if match:
# 提取各时间单位如果某个单位缺失则默认设为0
hours = int(match.group(1)) if match.group(1) else 0
minutes = int(match.group(2)) if match.group(2) else 0
seconds = int(match.group(3)) if match.group(3) else 0
# 计算总秒数
total_seconds = hours * 3600 + minutes * 60 + seconds
if total_seconds == 0:
# return None
pattern = r"(?:(\d+)小时)?(?:(\d+)分钟)?(?:(\d+)秒)?"
match = re.match(pattern, time_str)
if match:
# 提取各时间单位如果某个单位缺失则默认设为0
hours = int(match.group(1)) if match.group(1) else 0
minutes = int(match.group(2)) if match.group(2) else 0
seconds = int(match.group(3)) if match.group(3) else 0
# 计算总秒数
total_seconds = hours * 3600 + minutes * 60 + seconds
return total_seconds
else:
return None
return total_seconds
class SfMaintenanceEquipmentOEE(models.Model): class SfMaintenanceEquipmentOEE(models.Model):
@@ -48,227 +7,23 @@ 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', '=', '已注册')]")
equipment_code = fields.Char('设备编码', related='equipment_id.code', store=True)
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)')
online_time = fields.Char('开机时长(小时)', reaonly='True') equipment_time = fields.Float('时长(h)')
done_nums = fields.Integer('累计加工总件数')
offline_time = fields.Char('关机时长(小时)', reaonly='True') utilization_rate = fields.Char('开动率')
idle_nums = fields.Integer('待机次数', reaonly='True') fault_time = fields.Float('故障停机总时长(h)')
# 待机时长 fault_nums = fields.Integer('故障次数')
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')
# 设备故障日志
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='运行日志')
day_logs_detail = fields.Html('日运行日志详情')
history_logs_detail = fields.Html('历史运行日志详情')
begin_time = fields.Date('开始时间')
end_time = fields.Date('结束时间')
# 获取日志详情
def get_day_logs(self):
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
print(base_url)
config = self.env['ir.config_parameter'].sudo()
# url = 'http://172.16.10.112:8069/api/logs/list'
# url_time = 'http://localhost:9069/api/RunningTimeDetail'
url = base_url + '/api/logs/list'
url_time = base_url + '/api/RunningTimeDetail'
machine_list = [self.equipment_code]
begin_time = datetime.datetime.now().strftime('%Y-%m-%d') + ' 00:00:00'
end_time = datetime.datetime.now().strftime('%Y-%m-%d') + ' 23:59:59'
# 请求的数据
data = {
"machine_list": str(machine_list),
"begin_time": begin_time,
"end_time": end_time
}
data_time = {
"machine_list": str(machine_list)
}
print(data)
# 发送POST请求
response = requests.post(url, json={}, data=data)
response_time = requests.post(url_time, json={}, data=data_time)
# print(response.json()) # 输出服务器返回的响应
print(response_time.json())
if response_time.status_code == 200:
result_time = response_time.json()
real_dict = result_time['data'][self.equipment_code]
print('=', result_time)
if result_time['status'] == 1:
self.online_time = round((convert_to_seconds(real_dict['power_on_time']) - convert_to_seconds(
real_dict['power_on_24_time'])) / 3600, 2)
self.work_time = round(
(convert_to_seconds(real_dict['cut_time']) - convert_to_seconds(real_dict['cut_24_time'])) / 3600,
2)
self.offline_time = 24 - (float(self.online_time) if self.online_time else 0)
self.idle_time = float(self.online_time) - float(
self.work_time) if self.online_time and self.work_time else 0
self.idle_rate = round(
float(self.idle_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.work_rate = round(
float(self.work_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.fault_time = (float(real_dict['alarm_last_24_time']) if real_dict[
'alarm_last_24_time'] else 0) / 3600
self.fault_rate = round(
float(self.fault_time) / (float(self.online_time) if self.online_time else 1) * 100, 2)
self.fault_nums = real_dict['alarm_last_24_nums']
self.idle_nums = real_dict['idle_count']
if response.status_code == 200:
result = response.json()
print('============', result)
if result['status'] == 1:
logs_list = result['data'][self.equipment_code]
logs_detail = ''
log_state = ''
for log in logs_list:
if log['state'] != log_state:
print('loooooooooooooooooooogs', log)
production_name = log['production_name'] if log['production_name'] else ' '
logs_detail += '<tr><td>' + log['time'] + '</td><td>' + log[
'state'] + '</td><td>' + production_name + '</td></tr>'
log_state = log['state']
# self.day_logs_detail = '<table><tr><th>时间</th><th>事件/状态</th><th>加工工单</th></tr>' + logs_detail + '</table>'
self.day_logs_detail = '''
<table border="1" style="border-collapse: collapse; width: 100%; text-align: center;">
<tr style="background-color: #f2f2f2;">
<th style="padding: 8px; border: 1px solid #ddd;">时间</th>
<th style="padding: 8px; border: 1px solid #ddd;">事件/状态</th>
<th style="padding: 8px; border: 1px solid #ddd;">加工工单</th>
</tr>
{logs_detail}
</table>
'''.format(logs_detail=logs_detail)
else:
self.day_logs_detail = '获取日志失败'
else:
self.day_logs_detail = '获取日志失败'
# 获取历史日志详情
def get_history_logs(self):
config = self.env['ir.config_parameter'].sudo()
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
# url = 'http://172.16.10.112:8069/api/logs/list'
url = base_url + '/api/logs/list'
url_time = base_url + '/api/RunningTimeDetail'
machine_list = [self.equipment_code]
if not self.begin_time:
raise UserError('请选择开始时间')
if not self.end_time:
raise UserError('请选择结束时间')
begin_time = self.begin_time.strftime('%Y-%m-%d') + ' 00:00:00'
end_time = self.end_time.strftime('%Y-%m-%d') + ' 23:59:59'
# 请求的数据
data = {
"machine_list": str(machine_list),
"begin_time": begin_time,
"end_time": end_time
}
print(data)
# 发送POST请求
response = requests.post(url, json={}, data=data)
print(response.json()) # 输出服务器返回的响应
if response.status_code == 200:
result = response.json()
print('============', result)
if result['status'] == 1:
logs_list = result['data'][self.equipment_code]
logs_detail = ''
log_state = ''
for log in logs_list:
if log['state'] != log_state:
production_name = log['production_name'] if log['production_name'] else ' '
logs_detail += '<tr><td>' + log['time'] + '</td><td>' + log[
'state'] + '</td><td>' + production_name + '</td></tr>'
log_state = log['state']
# self.day_logs_detail = '<table><tr><th>时间</th><th>事件/状态</th><th>加工工单</th></tr>' + logs_detail + '</table>'
self.history_logs_detail = '''
<table border="1" style="border-collapse: collapse; width: 100%; text-align: center;">
<tr style="background-color: #f2f2f2;">
<th style="padding: 8px; border: 1px solid #ddd;">时间</th>
<th style="padding: 8px; border: 1px solid #ddd;">事件/状态</th>
<th style="padding: 8px; border: 1px solid #ddd;">加工工单</th>
</tr>
{logs_detail}
</table>
'''.format(logs_detail=logs_detail)
else:
self.history_logs_detail = '获取日志失败'
else:
self.history_logs_detail = '获取日志失败'
# 下载历史日志
def download_history_logs(self):
config = self.env['ir.config_parameter'].sudo()
url = 'http://172.16.10.112:8069/api/logs/list'
machine_list = [self.equipment_code]
if not self.begin_time:
raise UserError('请选择开始时间')
if not self.end_time:
raise UserError('请选择结束时间')
begin_time = self.begin_time.strftime('%Y-%m-%d') + ' 00:00:00'
end_time = self.end_time.strftime('%Y-%m-%d') + ' 23:59:59'
# 请求的数据
data = {
"machine_list": str(machine_list),
"begin_time": begin_time,
"end_time": end_time
}
print(data)
# 发送POST请求
response = requests.post(url, json={}, data=data)
print(response.json()) # 输出服务器返回的响应
if response.status_code == 200:
result = response.json()
print('============', result)
if result['status'] == 1:
logs_list = result['data'][self.equipment_code]
logs_detail = ''
for log in logs_list:
production_name = log['production_name'] if log['production_name'] else ' '
# todo 下载日志
else:
self.history_logs_detail = '下载日志失败'
else:
self.history_logs_detail = '下载日志失败'
def name_get(self): def name_get(self):
result = [] result = []
@@ -283,57 +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')

Binary file not shown.

Before

Width:  |  Height:  |  Size: 858 B

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

@@ -8,13 +8,12 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree> <tree>
<field name="equipment_id"/> <field name="equipment_id"/>
<field name="online_time"/> <field name="equipment_time"/>
<field name="work_time"/> <field name="run_time"/>
<field name="work_rate"/> <field name="done_nums"/>
<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>
@@ -37,102 +36,32 @@
<group> <group>
<group> <group>
<group> <field name="type_id" readonly="1"/>
<field name="equipment_id" domain="[('name','ilike','加工中心')]"/> <field name="equipment_time"/>
<field name="type_id"/> <field name="run_time"/>
<field name="state"/> <field name="done_nums"/>
<field name="equipment_code"/> <field name="utilization_rate"/>
</group> <field name="fault_time"/>
<field name="fault_nums"/>
</group> </group>
<group> <group>
<group> <field name="machine_tool_picture" widget="image" readonly="1"/>
<!-- <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="idle_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>
</group> </group>
<notebook> <notebook>
<page string="24H日志详情"> <page string="运行日志">
<group> <field name="oee_logs">
<button name="get_day_logs" type="object" string="查看24H日志" t-attf-style="white-space:nowrap;"/> <tree create="1" edit="1" delete="1" editable="bottom">
</group> <field name = 'run_time'/>
<field name="day_logs_detail" readonly="1" widget="html"/> <field name = 'state'/>
<!-- <field name="page_num"/> --> <field name = 'workorder_id'/>
<!-- <group> --> <field name = 'time'/>
<!-- <group> --> <field name = 'color' widget="color"/>
<!-- <button name="previous_day_logs" type="object" string="上一页" t-attf-style="white-space:nowrap;"/> --> </tree>
<!-- </group> --> </field>
<!-- <group> -->
<!-- <button name="next_day_logs" type="object" string="下一页" t-attf-style="white-space:nowrap;"/> -->
<!-- </group> -->
<!-- </group> -->
<!-- <field name="day_logs_detail"/> -->
<!-- <field name="day_logs_detail" widget="html" nolabel="1"/> -->
<!-- <field name="day_logs_detail" widget="html" nolabel="1" class="oe_form_field oe_form_field_html"/> -->
<!-- <field name="day_logs_detail" widget="html" nolabel="1" class="oe_form_field oe_form_field_html" options='{"class": "o_form_readonly"}'/> -->
<!-- <field name="day_logs_detail" widget="html" nolabel="1" class="oe_form_field oe_form_field_html" options='{"class": "o_form_readonly", "readonly": true, "style": "width: 100%; height: 400px;"}'/> -->
<!-- <group> -->
<!-- <div class="oe_html_field"> -->
<!-- <div id="pagination_day_logs"> -->
<!-- <button id="prev_page_day_logs" disabled="true">Previous</button> -->
<!-- <button id="next_page_day_logs">Next</button> -->
<!-- </div> -->
<!-- </div> -->
<!-- </group> -->
</page> </page>
<!-- <page string="历史日志详情"> --> </notebook>
<!-- <group> -->
<!-- <group> -->
<!-- <group> -->
<!-- <field name="begin_time"/> -->
<!-- </group> -->
<!-- <group> -->
<!-- <field name="end_time"/> -->
<!-- </group> -->
<!-- </group> -->
<!-- <group> -->
<!-- <group> -->
<!-- <button name="get_history_logs" type="object" string="查看历史日志" t-attf-style="white-space:nowrap;"/> -->
<!-- </group> -->
<!-- <group> -->
<!-- <button name="download_history_logs" type="object" string="下载历史日志" t-attf-style="white-space:nowrap;"/> -->
<!-- </group> -->
<!-- </group> -->
<!-- </group> -->
<!-- <field name="history_logs_detail"/> -->
<!-- </page> -->
</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="name"/> <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>
@@ -37,38 +39,31 @@
<sheet> <sheet>
<div class="oe_title"> <div class="oe_title">
<h1> <h1>
<field name="name" readonly="1"/> <field name="code" readonly="1"/>
</h1> </h1>
</div> </div>
<group> <group>
<group> <group>
<field name="name"/>
<field name="code"/> <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,6 +100,7 @@
</field> </field>
</record> </record>
<!-- Action --> <!-- Action -->
<record id="action_maintenance_logs" model="ir.actions.act_window"> <record id="action_maintenance_logs" model="ir.actions.act_window">

View File

@@ -1230,9 +1230,5 @@
action="hr_equipment_action1" action="hr_equipment_action1"
sequence="0"/> sequence="0"/>
<menuitem
id="maintenance.menu_maintenance_title"
web_icon="sf_maintenance,static/description/维护.png"/>
</odoo> </odoo>

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',
] ]
}, },

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