From e6060b9bab2f7bbdb6b73e0eb89d04fd4dbde2b6 Mon Sep 17 00:00:00 2001 From: "qihao.gong@jikimo.com" Date: Tue, 4 Jul 2023 17:30:50 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BB=B4=E4=BF=9D?= =?UTF-8?q?=E6=A0=87=E5=87=86=E7=BB=B4=E4=BF=9D=E9=A1=B9=E7=9B=AE=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E4=B8=BAOne2many=E5=AF=B9=E8=B1=A1=20=E5=B9=B6?= =?UTF-8?q?=E4=B8=8E=E8=AE=BE=E5=A4=87=EF=BC=8C=E7=BB=B4=E4=BF=9D=E8=AE=A1?= =?UTF-8?q?=E5=88=92=E5=85=B3=E8=81=94=EF=BC=8C=E4=BF=AE=E6=94=B9=E5=8E=9F?= =?UTF-8?q?=E7=94=9F=E7=BB=B4=E4=BF=9D=E8=AE=A1=E5=88=92=E6=96=B9=E6=B3=95?= =?UTF-8?q?=20=E6=A0=B9=E6=8D=AE=E4=BF=9D=E5=85=BB=E5=92=8C=E6=A3=80?= =?UTF-8?q?=E4=BF=AE=E7=94=9F=E6=88=90=E4=B8=8D=E5=90=8C=E7=9A=84=E7=BB=B4?= =?UTF-8?q?=E4=BF=9D=E8=AE=A1=E5=88=92=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sf_equipment_maintenance_standards.py | 12 +- sf_maintenance/models/sf_maintenance.py | 182 +++++++++++++++++- .../models/sf_maintenance_requests.py | 4 +- sf_maintenance/security/ir.model.access.csv | 1 + .../equipment_maintenance_standards_views.xml | 78 ++++---- .../views/maintenance_request_views.xml | 8 +- sf_manufacturing/__manifest__.py | 2 +- sf_mrs_connect/models/sync_common.py | 6 +- 8 files changed, 241 insertions(+), 52 deletions(-) diff --git a/sf_maintenance/models/sf_equipment_maintenance_standards.py b/sf_maintenance/models/sf_equipment_maintenance_standards.py index 35f25911..2544adb4 100644 --- a/sf_maintenance/models/sf_equipment_maintenance_standards.py +++ b/sf_maintenance/models/sf_equipment_maintenance_standards.py @@ -24,8 +24,7 @@ class SfEquipmentSaintenanceStandards(models.Model): created_user_id = fields.Many2one('res.users', string='创建人', default=lambda self: self.env.user) maintenance_equipment_category_id = fields.Many2one('maintenance.equipment.category', string='设备类别') maintenance_equipment_ids = fields.Many2many('maintenance.equipment', 'sf_maintenance_equipment_ids', string='设备') - maintenance_projects = fields.Char('维保项目') - maintenance_standards = fields.Char('维保标准') + maintenance_standards_ids = fields.One2many('maintenance.standards', 'equipment_maintenance_standards_id', string='维保项目') eq_maintenance_ids = fields.One2many('maintenance.equipment', 'eq_maintenance_id', string='保养设备') overhaul_ids = fields.One2many('maintenance.equipment', 'overhaul_id', string='检修设备') @@ -37,7 +36,14 @@ class SfEquipmentSaintenanceStandards(models.Model): if record.maintenance_type == '检修': record.write({'overhaul_ids': [(6, 0, record.maintenance_equipment_ids.ids)]}) - +class SfSaintenanceStandards(models.Model): + _name = 'maintenance.standards' + _description = '维保项目' + + name = fields.Char('维保项目') + maintenance_standards = fields.Char('维保标准') + equipment_maintenance_standards_id = fields.Many2one('equipment.maintenance.standards', string='设备维保标准') + maintenance_request_id = fields.Many2one('maintenance.request', string='设备维保计划') diff --git a/sf_maintenance/models/sf_maintenance.py b/sf_maintenance/models/sf_maintenance.py index 6c2f1dcd..594c3bce 100644 --- a/sf_maintenance/models/sf_maintenance.py +++ b/sf_maintenance/models/sf_maintenance.py @@ -4,10 +4,12 @@ import base64 from odoo import api, fields, models, SUPERUSER_ID, _ from odoo.exceptions import UserError import logging +from datetime import date, datetime, timedelta import requests import json from odoo.addons.sf_base.commons.common import Common + class SfMaintenanceEquipmentCategory(models.Model): _inherit = 'maintenance.equipment.category' _description = '设备类别' @@ -20,6 +22,7 @@ class SfMaintenanceEquipment(models.Model): _description = '设备' crea_url = "/api/machine_tool/create" + def get_no(self): partner = self.env['maintenance.equipment'].sudo().search( [('MTcode', '!=', '')], @@ -33,19 +36,23 @@ class SfMaintenanceEquipment(models.Model): num = "%04d" % m return num - equipment_maintenance_standards_ids = fields.Many2many('equipment.maintenance.standards', 'sf_maintenance_equipment_ids', string='设备维保标准') - eq_maintenance_id =fields.Many2one('equipment.maintenance.standards', string='设备保养标准', domain="[('maintenance_type','=','保养')]") + equipment_maintenance_standards_ids = fields.Many2many('equipment.maintenance.standards', + 'sf_maintenance_equipment_ids', string='设备维保标准') + eq_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备保养标准', + domain="[('maintenance_type','=','保养')]") overhaul_date = fields.Date(string='下次预防检修') overhaul_period = fields.Integer(string='预防检修频次') overhaul_duration = fields.Float(string='检修时长') - overhaul_id = fields.Many2one('equipment.maintenance.standards', string='设备检修标准', domain="[('maintenance_type','=','检修')]") + overhaul_id = fields.Many2one('equipment.maintenance.standards', string='设备检修标准', + domain="[('maintenance_type','=','检修')]") @api.onchange('eq_maintenance_id', 'overhaul_id') def _compute_equipment_maintenance_standards_ids(self): for record in self: if record.eq_maintenance_id and record.overhaul_id: - record.equipment_maintenance_standards_ids = [(6, 0, [record.eq_maintenance_id.id, record.overhaul_id.id])] + record.equipment_maintenance_standards_ids = [ + (6, 0, [record.eq_maintenance_id.id, record.overhaul_id.id])] break if record.eq_maintenance_id: record.equipment_maintenance_standards_ids = [(6, 0, [record.eq_maintenance_id.id])] @@ -56,8 +63,6 @@ class SfMaintenanceEquipment(models.Model): else: record.equipment_maintenance_standards_ids = False - - MTcode = fields.Char("编码", default=get_no) created_user = fields.Many2one('res.users', string='创建人', default=lambda self: self.env.user) equipment_type = fields.Selection([('机床', '机床')], related='category_id.equipment_type') @@ -279,7 +284,6 @@ class SfMaintenanceEquipment(models.Model): 'tool_diameter_max': item.tool_diameter_max, 'machine_tool_category': item.machine_tool_category.code, - } machine_tool_list.append(val) # kw = machine_tool_list @@ -293,4 +297,168 @@ class SfMaintenanceEquipment(models.Model): else: raise UserError("没有注册机床信息") + # 修改原生方法,生成维保日期 + @api.depends('effective_date', 'period', 'maintenance_ids.request_date', 'maintenance_ids.close_date', + 'overhaul_period') + def _compute_next_maintenance(self): + date_now = fields.Date.context_today(self) + equipments = self.filtered(lambda x: x.period > 0) + if equipments: + for equipment in equipments: + next_maintenance_todo = self.env['maintenance.request'].search([ + ('equipment_id', '=', equipment.id), + ('sf_maintenance_type', '=', '保养'), + ('stage_id.done', '!=', True), + ('close_date', '=', False)], order="request_date asc", limit=1) + last_maintenance_done = self.env['maintenance.request'].search([ + ('equipment_id', '=', equipment.id), + ('sf_maintenance_type', '=', '保养'), + ('stage_id.done', '=', True), + ('close_date', '!=', False)], order="close_date desc", limit=1) + if next_maintenance_todo and last_maintenance_done: + next_date = next_maintenance_todo.request_date + date_gap = next_maintenance_todo.request_date - last_maintenance_done.close_date + # If the gap between the last_maintenance_done and the next_maintenance_todo one is bigger than 2 times the period and next request is in the future + # We use 2 times the period to avoid creation too closed request from a manually one created + if date_gap > timedelta(0) and date_gap > timedelta( + days=equipment.period) * 2 and next_maintenance_todo.request_date > date_now: + # If the new date still in the past, we set it for today + if last_maintenance_done.close_date + timedelta(days=equipment.period) < date_now: + next_date = date_now + else: + next_date = last_maintenance_done.close_date + timedelta(days=equipment.period) + elif next_maintenance_todo: + next_date = next_maintenance_todo.request_date + date_gap = next_maintenance_todo.request_date - date_now + # If next maintenance to do is in the future, and in more than 2 times the period, we insert an new request + # We use 2 times the period to avoid creation too closed request from a manually one created + if date_gap > timedelta(0) and date_gap > timedelta(days=equipment.period) * 2: + next_date = date_now + timedelta(days=equipment.period) + elif last_maintenance_done: + next_date = last_maintenance_done.close_date + timedelta(days=equipment.period) + # If when we add the period to the last maintenance done and we still in past, we plan it for today + if next_date < date_now: + next_date = date_now + else: + next_date = equipment.effective_date + timedelta(days=equipment.period) + equipment.next_action_date = next_date + else: + self.next_action_date = False + overhaul_equipments = self.filtered(lambda x: x.overhaul_period > 0) + if overhaul_equipments: + for equipment in overhaul_equipments: + next_maintenance_todo = self.env['maintenance.request'].search([ + ('equipment_id', '=', equipment.id), + ('sf_maintenance_type', '=', '检修'), + ('stage_id.done', '!=', True), + ('close_date', '=', False)], order="request_date asc", limit=1) + last_maintenance_done = self.env['maintenance.request'].search([ + ('equipment_id', '=', equipment.id), + ('sf_maintenance_type', '=', '检修'), + ('stage_id.done', '=', True), + ('close_date', '!=', False)], order="close_date desc", limit=1) + if next_maintenance_todo and last_maintenance_done: + next_date = next_maintenance_todo.request_date + date_gap = next_maintenance_todo.request_date - last_maintenance_done.close_date + # If the gap between the last_maintenance_done and the next_maintenance_todo one is bigger than 2 times the period and next request is in the future + # We use 2 times the period to avoid creation too closed request from a manually one created + if date_gap > timedelta(0) and date_gap > timedelta( + days=equipment.overhaul_period) * 2 and next_maintenance_todo.request_date > date_now: + # If the new date still in the past, we set it for today + if last_maintenance_done.close_date + timedelta(days=equipment.overhaul_period) < date_now: + next_date = date_now + else: + next_date = last_maintenance_done.close_date + timedelta(days=equipment.overhaul_period) + elif next_maintenance_todo: + next_date = next_maintenance_todo.request_date + date_gap = next_maintenance_todo.request_date - date_now + # If next maintenance to do is in the future, and in more than 2 times the period, we insert an new request + # We use 2 times the period to avoid creation too closed request from a manually one created + if date_gap > timedelta(0) and date_gap > timedelta(days=equipment.overhaul_period) * 2: + next_date = date_now + timedelta(days=equipment.overhaul_period) + elif last_maintenance_done: + next_date = last_maintenance_done.close_date + timedelta(days=equipment.overhaul_period) + # If when we add the period to the last maintenance done and we still in past, we plan it for today + if next_date < date_now: + next_date = date_now + else: + next_date = equipment.effective_date + timedelta(days=equipment.overhaul_period) + equipment.overhaul_date = next_date + else: + self.overhaul_date = False + # 拼接维保请求字符串 + def _prepare_maintenance_request_vals(self, date): + self.ensure_one() + return { + 'name': _('Preventive Maintenance - %s', self.name), + 'request_date': date, + 'schedule_date': date, + 'category_id': self.category_id.id, + 'equipment_id': self.id, + 'maintenance_type': 'preventive', + 'owner_user_id': self.owner_user_id.id, + 'user_id': self.technician_user_id.id, + 'maintenance_team_id': self.maintenance_team_id.id, + 'duration': self.maintenance_duration, + 'company_id': self.company_id.id or self.env.company.id, + 'equipment_maintenance_id': self.eq_maintenance_id.id, + 'sf_maintenance_type': '保养' + + } + + # 拼接维保请求字符串 + + def _prepare_maintenance_request_vals1(self, date): + self.ensure_one() + return { + 'name': _('Preventive Maintenance - %s', self.name), + 'request_date': date, + 'schedule_date': date, + 'category_id': self.category_id.id, + 'equipment_id': self.id, + 'maintenance_type': 'preventive', + 'owner_user_id': self.owner_user_id.id, + 'user_id': self.technician_user_id.id, + 'maintenance_team_id': self.maintenance_team_id.id, + 'duration': self.maintenance_duration, + 'company_id': self.company_id.id or self.env.company.id, + 'equipment_maintenance_id': self.overhaul_id.id, + 'sf_maintenance_type': '检修' + } + + # 创建维保请求 + def _create_new_request(self, date): + self.ensure_one() + vals = self._prepare_maintenance_request_vals(date) + maintenance_requests = self.env['maintenance.request'].create(vals) + return maintenance_requests + + def _create_new_request1(self, date): + self.ensure_one() + vals = self._prepare_maintenance_request_vals1(date) + maintenance_requests = self.env['maintenance.request'].create(vals) + return maintenance_requests + + # 生成维保请求定时器 + @api.model + def _cron_generate_requests(self): + """ + Generates maintenance request on the next_action_date or today if none exists + """ + for equipment in self.search([('period', '>', 0)]): + next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False), + ('equipment_id', '=', equipment.id), + ('maintenance_type', '=', 'preventive'), + ('request_date', '=', equipment.next_action_date), + ('sf_maintenance_type', '=', '保养')]) + if not next_requests: + equipment._create_new_request(equipment.next_action_date) + for equipment in self.search([('overhaul_period', '>', 0)]): + next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False), + ('equipment_id', '=', equipment.id), + ('maintenance_type', '=', 'preventive'), + ('request_date', '=', equipment.overhaul_date), + ('sf_maintenance_type', '=', '检修')]) + if not next_requests: + equipment._create_new_request1(equipment.overhaul_date) diff --git a/sf_maintenance/models/sf_maintenance_requests.py b/sf_maintenance/models/sf_maintenance_requests.py index 3508abcc..36cf2479 100644 --- a/sf_maintenance/models/sf_maintenance_requests.py +++ b/sf_maintenance/models/sf_maintenance_requests.py @@ -26,8 +26,8 @@ class SfMaintenanceEquipmentCategory(models.Model): record.equipment_maintenance_id = False - maintenance_projects = fields.Char(string='维保项目', related='equipment_maintenance_id.maintenance_projects') - maintenance_standards = fields.Char(string='维保标准', related='equipment_maintenance_id.maintenance_standards') + + maintenance_standards = fields.One2many('maintenance.standards','maintenance_request_id', string='维保标准', related='equipment_maintenance_id.maintenance_standards_ids') @api.constrains('equipment_maintenance_id') def _check_equipment_maintenance_id(self): diff --git a/sf_maintenance/security/ir.model.access.csv b/sf_maintenance/security/ir.model.access.csv index 06e231b9..05ee33a2 100644 --- a/sf_maintenance/security/ir.model.access.csv +++ b/sf_maintenance/security/ir.model.access.csv @@ -2,5 +2,6 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_equipment_maintenance_standards,equipment_maintenance_standards,model_equipment_maintenance_standards,base.group_user,1,1,1,1 access_sf_maintenance_logs,sf_maintenance_logs,model_sf_maintenance_logs,base.group_user,1,1,1,1 access_maintenance_equipment,maintenance_equipment,model_maintenance_equipment,base.group_user,1,1,1,1 +access_maintenance_standards,maintenance_standards,model_maintenance_standards,base.group_user,1,1,1,1 diff --git a/sf_maintenance/views/equipment_maintenance_standards_views.xml b/sf_maintenance/views/equipment_maintenance_standards_views.xml index f4b90fa6..7263a135 100644 --- a/sf_maintenance/views/equipment_maintenance_standards_views.xml +++ b/sf_maintenance/views/equipment_maintenance_standards_views.xml @@ -2,31 +2,42 @@ - - equipment.maintenance.standards.form - equipment.maintenance.standards - -
- - - - - - - - - - - - + + equipment.maintenance.standards.form + equipment.maintenance.standards + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + +
+ +
+
+ + equipment.maintenance.standards.tree equipment.maintenance.standards @@ -36,9 +47,7 @@ - - - + @@ -50,7 +59,7 @@ equipment.maintenance.standards - + @@ -58,14 +67,11 @@ - - - 设备维保标准 ir.actions.act_window @@ -79,12 +85,12 @@ - +
\ No newline at end of file diff --git a/sf_maintenance/views/maintenance_request_views.xml b/sf_maintenance/views/maintenance_request_views.xml index d711702d..e1e934d9 100644 --- a/sf_maintenance/views/maintenance_request_views.xml +++ b/sf_maintenance/views/maintenance_request_views.xml @@ -17,8 +17,12 @@ - - + + + + + + diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py index b13036ef..5e61bb27 100644 --- a/sf_manufacturing/__manifest__.py +++ b/sf_manufacturing/__manifest__.py @@ -16,7 +16,7 @@ 'security/group_security.xml', 'security/ir.model.access.csv', 'report/tray_report.xml', - 'views/mrp_maintenance_views.xml', + # 'views/mrp_maintenance_views.xml', 'views/mrp_routing_workcenter_view.xml', 'views/mrp_workcenter_views.xml', 'views/mrp_workorder_view.xml', diff --git a/sf_mrs_connect/models/sync_common.py b/sf_mrs_connect/models/sync_common.py index f101530b..4926726e 100644 --- a/sf_mrs_connect/models/sync_common.py +++ b/sf_mrs_connect/models/sync_common.py @@ -787,6 +787,10 @@ class MachineToolType(models.Model): result = json.loads(r['result']) if result['status'] == 1: for item in result['machine_tool_type_all_list']: + if item.get('machine_tool_picture'): + image = base64.b64decode(item['machine_tool_picture']) + else: + image = '' brand = self.env['sf.machine_tool.type'].search( [("code", '=', item['code'])]) if not brand: @@ -811,7 +815,7 @@ class MachineToolType(models.Model): [('code', '=', item['control_system_id'])]).id, "active": item['active'], 'brand_id': self.env['sf.machine.brand'].search([('code', '=', item['brand_id'])]).id, - 'machine_tool_picture': base64.b64decode(item['machine_tool_picture']), + 'machine_tool_picture':image, "heightened_way": item['heightened_way'], "workpiece_load": item['workpiece_load'], "lead_screw": item['lead_screw'], From f685c9a3d45bc040cb1f31f74b92f5b718b9e6e0 Mon Sep 17 00:00:00 2001 From: yuxianghui <1608204036@qq.com> Date: Tue, 4 Jul 2023 17:37:20 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E6=A8=A1=E5=9D=97=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=97=A5=E5=8E=86=E8=AE=BE=E7=BD=AE=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=EF=BC=88=E5=B7=B2=E5=AE=8C=E6=88=90=EF=BC=8C=E6=89=8B?= =?UTF-8?q?=E5=8A=A8=E8=BE=93=E5=85=A5=E6=97=B6=E9=97=B4=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=9C=80=E4=BC=98=E5=8C=96=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_plan_management/__init__.py | 1 + sf_plan_management/__manifest__.py | 34 +++++++++++ sf_plan_management/models/__init__.py | 1 + sf_plan_management/models/base.py | 59 ++++++++++++++++++ .../security/ir.model.access.csv | 8 +++ sf_plan_management/views/menu_view.xml | 21 +++++++ sf_plan_management/views/paln_base_view.xml | 61 +++++++++++++++++++ 7 files changed, 185 insertions(+) create mode 100644 sf_plan_management/__init__.py create mode 100644 sf_plan_management/__manifest__.py create mode 100644 sf_plan_management/models/__init__.py create mode 100644 sf_plan_management/models/base.py create mode 100644 sf_plan_management/security/ir.model.access.csv create mode 100644 sf_plan_management/views/menu_view.xml create mode 100644 sf_plan_management/views/paln_base_view.xml diff --git a/sf_plan_management/__init__.py b/sf_plan_management/__init__.py new file mode 100644 index 00000000..9a7e03ed --- /dev/null +++ b/sf_plan_management/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/sf_plan_management/__manifest__.py b/sf_plan_management/__manifest__.py new file mode 100644 index 00000000..9a8af0cd --- /dev/null +++ b/sf_plan_management/__manifest__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +{ + 'name': '机企猫智能工厂 计划管理', + 'version': '1.0', + 'summary': '智能工厂计划管理', + 'sequence': 1, + 'description': """ +在本模块,定义了计划管理的清单和原型 + """, + 'category': 'sf', + 'website': 'https://www.sf.jikimo.com', + 'depends': [], + 'data': [ + 'security/ir.model.access.csv', + 'views/paln_base_view.xml', + 'views/menu_view.xml' + ], + 'demo': [ + ], + 'assets': { + + 'web.assets_qweb': [ + ], + 'web.assets_backend':[ + ] + + + }, + 'license': 'LGPL-3', + 'installable': True, + 'application': False, + 'auto_install': False, +} diff --git a/sf_plan_management/models/__init__.py b/sf_plan_management/models/__init__.py new file mode 100644 index 00000000..cf50d1cc --- /dev/null +++ b/sf_plan_management/models/__init__.py @@ -0,0 +1 @@ +from . import base \ No newline at end of file diff --git a/sf_plan_management/models/base.py b/sf_plan_management/models/base.py new file mode 100644 index 00000000..242a67bc --- /dev/null +++ b/sf_plan_management/models/base.py @@ -0,0 +1,59 @@ +from odoo import models, fields, api +import re + + +class WorkLogSetting(models.Model): + _name = 'sf.work.log.setting' + _description = '工作日历设置' + + input1 = fields.Char(string='Input 1') + input2 = fields.Char(string='Input 2') + + name = fields.Char(string='工作日历名称') + # start_time = fields.Char(string='日开始时间') + start_time = fields.Datetime(string='日开始时间') + end_time = fields.Char(string='日结束时间') + duration = fields.Char(string='时长') + day_off = fields.Char(string='休息日') + + user_defined_working_shift_status = fields.Boolean(string='自定义班次', default=False) + working_shift = fields.Char(string='班次') + working_shift_char = fields.Char(string='班次') + working_shift_select = fields.Selection([('0', '早班00:00-08:00'), + ('1', '白班08:00-16:00'), + ('2', '晚班16:00-24:00'), + ('3', '长白班08:00-20:00'), + ('4', '长晚班20:00-08:00')], string='班次') + + status = fields.Boolean(string='状态', default=True) + update_person = fields.Char(string='更新人', default=lambda self: self.env.user.name) + update_time = fields.Datetime(string='更新时间', default=lambda self: fields.Datetime.now()) + + # @api.onchange('working_shift_char') + # def _onchange_working_shift_char(self): + # pattern = re.compile(r'^(([0-9]|1[0-9]|2[0-3]):[0-5][0-9])|24:00$') + # if self.start_time and not pattern.match(self.start_time): + # raise models.ValidationError('输入的日开始时间不正确,请重新输入!') + + @api.onchange('working_shift_char', 'working_shift_select') + def _onchange_working_shift(self): + for record in self: + if record.working_shift_select: + record.working_shift = record.working_shift_select + else: + record.working_shift = record.working_shift_char + + # @api.onchange('start_time') + # def _onchange_start_time(self): + # pattern = re.compile(r'^(([0-9]|1[0-9]|2[0-3]):[0-5][0-9])|24:00$') + # if self.start_time and not pattern.match(self.start_time): + # raise models.ValidationError('输入的日开始时间不正确,请重新输入!') + + @api.onchange('end_time') + def _onchange_end_time(self): + pattern = re.compile(r'^(([0-9]|1[0-9]|2[0-3]):[0-5][0-9])|24:00$') + for record in self: + if record.end_time and not pattern.match(record.end_time): + raise models.ValidationError('输入的日结束时间不正确,请重新输入!') + + diff --git a/sf_plan_management/security/ir.model.access.csv b/sf_plan_management/security/ir.model.access.csv new file mode 100644 index 00000000..d2e97991 --- /dev/null +++ b/sf_plan_management/security/ir.model.access.csv @@ -0,0 +1,8 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_sf_work_log_setting,sf.work.log.setting,model_sf_work_log_setting,base.group_user,1,1,1,1 + + + + + + diff --git a/sf_plan_management/views/menu_view.xml b/sf_plan_management/views/menu_view.xml new file mode 100644 index 00000000..3c1345f3 --- /dev/null +++ b/sf_plan_management/views/menu_view.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/sf_plan_management/views/paln_base_view.xml b/sf_plan_management/views/paln_base_view.xml new file mode 100644 index 00000000..0d8ea30b --- /dev/null +++ b/sf_plan_management/views/paln_base_view.xml @@ -0,0 +1,61 @@ + + + + + 工作日历设置 + sf.work.log.setting + + + + + + + + + + + + + + + + + 工作日历设置 + sf.work.log.setting + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + 工作日历设置 + sf.work.log.setting + tree,form + +
\ No newline at end of file From 0d7c269c3bb7c4e2ea9c849d5943f8cac67155cd Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Tue, 4 Jul 2023 20:05:59 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E7=BB=A7=E6=89=BF=E5=8E=9F=E7=94=9F?= =?UTF-8?q?=E5=BA=93=E5=AD=98=E6=A8=A1=E5=9D=97=EF=BC=8C=E4=B8=BA=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E6=A8=A1=E5=9E=8B=E5=A2=9E=E5=8A=A0=E5=BA=93=E5=8C=BA?= =?UTF-8?q?=E5=BA=93=E4=BD=8D=E7=AD=89=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_warehouse/__init__.py | 3 + sf_warehouse/__manifest__.py | 35 +++++++ sf_warehouse/models/__init__.py | 2 + sf_warehouse/models/model.py | 113 ++++++++++++++++++++++ sf_warehouse/security/ir.model.access.csv | 19 ++++ sf_warehouse/static/src/change.scss | 11 +++ sf_warehouse/views/view.xml | 38 ++++++++ 7 files changed, 221 insertions(+) create mode 100644 sf_warehouse/__init__.py create mode 100644 sf_warehouse/__manifest__.py create mode 100644 sf_warehouse/models/__init__.py create mode 100644 sf_warehouse/models/model.py create mode 100644 sf_warehouse/security/ir.model.access.csv create mode 100644 sf_warehouse/static/src/change.scss create mode 100644 sf_warehouse/views/view.xml diff --git a/sf_warehouse/__init__.py b/sf_warehouse/__init__.py new file mode 100644 index 00000000..815c355c --- /dev/null +++ b/sf_warehouse/__init__.py @@ -0,0 +1,3 @@ +# -*-coding:utf-8-*- +from . import models + diff --git a/sf_warehouse/__manifest__.py b/sf_warehouse/__manifest__.py new file mode 100644 index 00000000..6ad297c8 --- /dev/null +++ b/sf_warehouse/__manifest__.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +{ + 'name': '机企猫智能工厂 库存管理', + 'version': '1.0', + 'summary': '智能工厂库存管理', + 'sequence': 1, + 'description': """ +在本模块,升级了odoo原生的库存模块 + """, + 'category': 'sf', + 'website': 'https://www.sf.jikimo.com', + 'depends': ['stock', ], + 'data': [ + #'security/group_security.xml', + # 'security/ir.model.access.csv', + 'views/view.xml', + ], + 'demo': [ + ], + 'assets': { + + 'web.assets_qweb': [ + ], + 'web.assets_backend':[ + # 'sf_tool_management/static/src/change.scss' + ] + + + }, + 'license': 'LGPL-3', + 'installable': True, + 'application': False, + 'auto_install': False, +} diff --git a/sf_warehouse/models/__init__.py b/sf_warehouse/models/__init__.py new file mode 100644 index 00000000..833a0ba1 --- /dev/null +++ b/sf_warehouse/models/__init__.py @@ -0,0 +1,2 @@ +from . import model + diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py new file mode 100644 index 00000000..1cfc3cde --- /dev/null +++ b/sf_warehouse/models/model.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +from odoo import fields, models, api +from odoo.exceptions import ValidationError + + +class SfLocation(models.Model): + _inherit = 'stock.location' + + # 重写字段定义 + name = fields.Char('Location Name', required=True, size=20) + barcode = fields.Char('Barcode', copy=False, required=True, size=15) + + # 仓库类别(selection:仓库、库区、库位、货位) + location_type = fields.Selection([ + ('仓库', '仓库'), + ('库区', '库区'), + ('库位', '库位'), + ('货位', '货位') + ], string='仓库类别') + # 仓库类型(分类:成品库、坯料库、原材料库、刀具库、线边料库、线边刀库) + location_category = fields.Selection([ + ('成品库', '成品库'), + ('坯料库', '坯料库'), + ('原材料库', '原材料库'), + ('刀具库', '刀具库'), + ('线边料库', '线边料库'), + ('线边刀库', '线边刀库') + ], string='仓库类型') + # 库区类型(selection:拣货区、存货区、收货区、退货区、次品区) + area_type = fields.Selection([ + ('拣货区', '拣货区'), + ('存货区', '存货区'), + ('收货区', '收货区'), + ('退货区', '退货区'), + ('次品区', '次品区') + ], string='库区类型') + # 货架独有字段:通道、方向、货架高度(m)、货架层数、层数容量 + channel = fields.Char(string='通道') + direction = fields.Selection([ + ('R', 'R'), + ('L', 'L') + ], string='方向') + shelf_height = fields.Float(string='货架高度(m)') + shelf_layer = fields.Integer(string='货架层数') + layer_capacity = fields.Integer(string='层数容量') + + # 货位独有字段:货位状态、产品(关联产品对象)、产品序列号(关联产品序列号对象) + location_status = fields.Selection([ + ('空闲', '空闲'), + ('占用', '占用'), + ('禁用', '禁用') + ], string='货位状态', default='空闲') + product_id = fields.Many2one('product.template', string='产品') + # product_sn_id = fields.Many2one('product.serial.number', string='产品序列号') + + # 添加SQL约束 + _sql_constraints = [ + ('name_uniq', 'unique(name)', '位置名称必须唯一!'), + ] + + hide_location_type = fields.Boolean(compute='_compute_hide_what', string='隐藏仓库') + hide_area = fields.Boolean(compute='_compute_hide_what', string='隐藏库区') + hide_shelf = fields.Boolean(compute='_compute_hide_what', string='隐藏货架') + hide_location = fields.Boolean(compute='_compute_hide_what', string='隐藏货位') + + @api.depends('location_type') + def _compute_hide_what(self): + """ + 根据仓库类别,隐藏不需要的字段 + :return: + """ + for record in self: + record.hide_location_type = False + record.hide_area = False + record.hide_shelf = False + record.hide_location = False + if record.location_type and record.location_type == '仓库': + record.hide_location_type = True + elif record.location_type and record.location_type == '库区': + record.hide_area = True + elif record.location_type and record.location_type == '库位': + record.hide_shelf = True + elif record.location_type and record.location_type == '货位': + record.hide_location = True + else: + pass + + # # 添加Python约束 + # @api.constrains('name', 'barcode') + # def _check_len(self): + # for rec in self: + # if len(rec.name) > 20: + # raise ValidationError("Location Name length must be less equal than 20!") + # if len(rec.barcode) > 15: + # raise ValidationError("Barcode length must be less equal than 15!") + + @api.model + def default_get(self, fields): + res = super(SfLocation, self).default_get(fields) + if 'barcode' in fields and 'barcode' not in res: + # 这里是你生成barcode的代码 + res['barcode'] = self.generate_barcode() # 假设你有一个方法generate_barcode来生成barcode + return res + + def generate_barcode(self): + # 这里是你生成barcode的代码 + # 这只是一个示例,你需要根据你的实际需求来编写这个方法 + last_location = self.search([], order='id desc', limit=1) + if last_location: + last_barcode = int(last_location.barcode or 0) + return str(last_barcode + 1).zfill(8) + else: + return '00000001' diff --git a/sf_warehouse/security/ir.model.access.csv b/sf_warehouse/security/ir.model.access.csv new file mode 100644 index 00000000..6cb8bc16 --- /dev/null +++ b/sf_warehouse/security/ir.model.access.csv @@ -0,0 +1,19 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_sf_functional_cutting_tool_entity,sf.functional.cutting.tool.entity,model_sf_functional_cutting_tool_entity,base.group_user,1,1,1,1 +access_sf_cam_work_order_program_knife_plan,sf.cam.work.order.program.knife.plan,model_sf_cam_work_order_program_knife_plan,base.group_user,1,1,1,1 +access_sf_machine_table_tool_changing_apply,sf.machine.table.tool.changing.apply,model_sf_machine_table_tool_changing_apply,base.group_user,1,1,1,1 + + +access_sf_tool_change_requirement_information,sf.tool.change.requirement.information,model_sf_tool_change_requirement_information,base.group_user,1,1,1,1 +access_sf_tool_transfer_request_information,sf.tool.transfer.request.information,model_sf_tool_transfer_request_information,base.group_user,1,1,1,1 +access_sf_apply_for_tooling,sf.apply.for.tooling,model_sf_apply_for_tooling,base.group_user,1,1,1,1 + +access_sf_functional_tool_assembly,sf.functional.tool.assembly,model_sf_functional_tool_assembly,base.group_user,1,1,1,1 +access_sf_functional_tool_assembly_order,sf.functional.tool.assembly.order,model_sf_functional_tool_assembly_order,base.group_user,1,1,1,1 +access_sf_delivery_of_cargo_from_storage,sf.delivery.of.cargo.from.storage,model_sf_delivery_of_cargo_from_storage,base.group_user,1,1,1,1 +access_sf_tool_material_search,sf.tool.material.search,model_sf_tool_material_search,base.group_user,1,1,1,1 + + + + + diff --git a/sf_warehouse/static/src/change.scss b/sf_warehouse/static/src/change.scss new file mode 100644 index 00000000..40fdcc8e --- /dev/null +++ b/sf_warehouse/static/src/change.scss @@ -0,0 +1,11 @@ +.modal-content .o_cp_buttons { + display:none +} + +.modal-content .o_control_panel { + display:none +} + +.modal-content .o_list_button { + +} \ No newline at end of file diff --git a/sf_warehouse/views/view.xml b/sf_warehouse/views/view.xml new file mode 100644 index 00000000..cefa513e --- /dev/null +++ b/sf_warehouse/views/view.xml @@ -0,0 +1,38 @@ + + + + stock.location.form.sf.inherit + stock.location + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 3e6130da150ed3a4aed243d9763e91fe51f4515f Mon Sep 17 00:00:00 2001 From: "qihao.gong@jikimo.com" Date: Wed, 5 Jul 2023 14:32:22 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E7=BB=B4=E4=BF=9D=E8=AE=A1=E5=88=92?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=A1=AE=E8=AE=A4=E7=BB=B4=E4=BF=9D=E8=AE=A1?= =?UTF-8?q?=E5=88=92=E5=92=8C=E6=A0=87=E8=AE=B0=E5=B7=B2=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E6=8C=89=E9=92=AE=EF=BC=8C=E5=A4=84=E7=90=86=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E7=94=9F=E6=88=90=E7=BB=B4=E4=BF=9D=E8=AE=A1=E5=88=92=E7=9A=84?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E6=8A=A5=E9=94=99=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_maintenance/models/sf_maintenance.py | 2 +- sf_maintenance/models/sf_maintenance_requests.py | 6 ++++++ sf_maintenance/views/maintenance_request_views.xml | 6 +++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/sf_maintenance/models/sf_maintenance.py b/sf_maintenance/models/sf_maintenance.py index 594c3bce..c5a31fb6 100644 --- a/sf_maintenance/models/sf_maintenance.py +++ b/sf_maintenance/models/sf_maintenance.py @@ -421,7 +421,7 @@ class SfMaintenanceEquipment(models.Model): 'owner_user_id': self.owner_user_id.id, 'user_id': self.technician_user_id.id, 'maintenance_team_id': self.maintenance_team_id.id, - 'duration': self.maintenance_duration, + 'duration': self.overhaul_duration, 'company_id': self.company_id.id or self.env.company.id, 'equipment_maintenance_id': self.overhaul_id.id, 'sf_maintenance_type': '检修' diff --git a/sf_maintenance/models/sf_maintenance_requests.py b/sf_maintenance/models/sf_maintenance_requests.py index 36cf2479..1de354fe 100644 --- a/sf_maintenance/models/sf_maintenance_requests.py +++ b/sf_maintenance/models/sf_maintenance_requests.py @@ -35,6 +35,12 @@ class SfMaintenanceEquipmentCategory(models.Model): if not record.equipment_maintenance_id: raise UserError(_("设备维保标准不能为空,请选择后再保存")) + def confirm_maintenance(self): + self.write({'stage_id': 2}) + + def confirm_maintenance_done(self): + self.write({'stage_id': 3}) + diff --git a/sf_maintenance/views/maintenance_request_views.xml b/sf_maintenance/views/maintenance_request_views.xml index e1e934d9..cd5498c1 100644 --- a/sf_maintenance/views/maintenance_request_views.xml +++ b/sf_maintenance/views/maintenance_request_views.xml @@ -7,6 +7,10 @@ maintenance.request + +