Commit 57791b52 by 夏超

[fix] 玖姿返修报废功能产品化

parent 03796666
...@@ -16,13 +16,10 @@ ...@@ -16,13 +16,10 @@
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'views/inherit_roke_mes_stock_picking_views.xml', 'views/inherit_roke_mes_stock_picking_views.xml',
'views/inherit_roke_production_task.xml', 'views/inherit_roke_production_task.xml',
'views/inherit_repair_view.xml',
'views/button_js.xml', 'views/button_js.xml',
'views/iniherit_work_order_view.xml', 'views/iniherit_work_order_view.xml',
'views/roke_work_log_views.xml', 'views/roke_work_log_views.xml',
'views/iniherit_work_center_view.xml', 'views/iniherit_work_center_view.xml',
'wizard/inherit_roke_create_work_record_wizard_view.xml',
'views/inherit_roke_scrap_order_view.xml'
], ],
'qweb': [ 'qweb': [
"static/src/xml/roke_craft_design.xml", "static/src/xml/roke_craft_design.xml",
......
from . import inherit_production from . import inherit_production
from . import inherit_product_task
from . import roke_work_order from . import roke_work_order
from urllib import parse
from odoo import models, fields, api, http, SUPERUSER_ID, _
from odoo.addons.roke_workstation_api.controllers.product_task import RokeWorkstationProductionTask
from odoo.addons.roke_workstation_api.controllers.product_task import RokeWorkstationTaskDispatch
import logging
import math
_logger = logging.getLogger(__name__)
class JzjxInheritRokeWorkstationProductionTask(RokeWorkstationProductionTask):
@http.route('/roke/workstation/product_task/machine_get_list', type='json', auth='user', csrf=False, cors="*")
def product_task_machine_get_list(self):
"""
获取当前用户权限下所有任务的数据
workstation_id: int 工位ID
limit: int 条数
page: int 页数
"""
_self = http.request
workstation_id = _self.jsonrequest.get("workstation_id", False)
limit = _self.jsonrequest.get("limit", 20)
page = _self.jsonrequest.get("page", 1)
if not workstation_id:
return {"code": 1, "message": f"入参错误! “工位ID”为必传数据。", "data": []}
workstation = _self.env["roke.work.center"].search(
[("id", "=", workstation_id)])
if not workstation:
return {"code": 1, "message": "校验错误! 未找到该工位数据。", "data": []}
user_id = _self.env['roke.employee'].search(
[('user_id', '=', http.request.uid)], limit=1)
process_ids = _self.env['roke.process'].search(
[('workstation_ids', '=', workstation_id)])
# process_list = list(set(process_ids.ids) & set(user_id.process_ids.ids))
process_list = process_ids.ids
if not process_ids:
return {"code": 0, "message": "获取成功!", "data": [], "process_ids": [], "count": 0}
domain = [
("task_id.workshop_id", "=", workstation.workshop_id.id),
("process_id", "in", process_list),
("state", "in", ["未完工", "暂停"])
]
work_order = _self.env["roke.work.order"].search(domain)
sql = f"""
SELECT id, type, create_date
FROM (
{f'''SELECT roke_production_task.id, 'task' as "type", roke_production_task.create_date
FROM roke_production_task LEFT JOIN roke_work_order on roke_work_order.task_id = roke_production_task.id
WHERE roke_work_order.id in ({" , ".join([f"{v}" for v in work_order.ids])})
and roke_production_task.state in ('未完工', '暂停')
union all''' if work_order.ids else ""}
SELECT id, 'work' as "type", create_date
FROM roke_work_order
WHERE type in ('返修', '补件')
and process_id in ({" , ".join([f"{v}" for v in process_list])})
and state = '未完工'
and task_id is null
) as task_repair_work
ORDER BY create_date desc
LIMIT {limit}
offset {(page - 1) * limit}
"""
_self.env.cr.execute(sql)
results = _self.env.cr.dictfetchall()
count_sql = f"""
SELECT count(id)
FROM (
{f'''SELECT roke_production_task.id
FROM roke_production_task LEFT JOIN roke_work_order on roke_work_order.task_id = roke_production_task.id
WHERE roke_work_order.id in ({" , ".join([f"{v}" for v in work_order.ids])})
and roke_production_task.state in ('未完工', '暂停')
union all''' if work_order.ids else ""}
SELECT id
FROM roke_work_order
WHERE type = '返修'
and process_id in ({" , ".join([f"{v}" for v in process_list])})
and state = '未完工'
and repair_task_id is not null
) as task_repair_work
"""
_self.env.cr.execute(count_sql)
task_count = _self.env.cr.dictfetchall()[0].get("count", 0)
ids_list = []
task_id_list = []
work_id_list = []
for v in results:
data_type = v.get("type", '')
data_id = v.get("id", 0)
ids_list.append([data_id, data_type])
if data_type == 'task':
task_id_list.append(data_id)
if data_type == 'work':
work_id_list.append(data_id)
task_ids = _self.env["roke.production.task"].search([("id", "in", task_id_list)])
work_ids = _self.env["roke.work.order"].search([("id", "in", work_id_list)])
task_data_dict = {}
for v in task_ids:
task_data_dict[str(v.id)] = {
"id": v.id,
"code": v.code,
"state": v.state,
"partner": {"id": v.customer_id.id or None, "name": v.customer_id.name or ""},
"plan_qty": v.plan_qty or 0,
"product": {"id": v.product_id.id or None, "name": v.product_id.name or ""},
"priority": v.priority,
"planned_start_time": v.plan_start_date.strftime('%Y-%m-%d') if v.plan_start_date else "",
"plan_date": v.plan_date.strftime('%Y-%m-%d') if v.plan_date else "",
"specification": v.product_id.specification or "",
"model": v.product_id.model or "",
"order_type": "task",
"type": ""
}
work_data_dict = {}
for v in work_ids:
work_data_dict[str(v.id)] = {
"id": v.id,
"code": v.code,
"state": v.state,
"partner": {"id": v.customer_id.id or None, "name": v.customer_id.name or ""},
"plan_qty": v.plan_qty or 0,
"product": {"id": v.product_id.id or None, "name": v.product_id.name or ""},
"priority": v.priority,
"planned_start_time": v.planned_start_time.strftime('%Y-%m-%d') if v.planned_start_time else "",
"plan_date": v.plan_date.strftime('%Y-%m-%d') if v.plan_date else "",
"specification": v.product_id.specification or "",
"model": v.product_id.model or "",
"order_type": "work",
"type": v.type
}
data = []
for v in ids_list:
l_id = v[0]
l_type = v[1]
if l_type == "task":
task_data = task_data_dict.get(str(l_id), False)
if not task_data:
continue
data.append(task_data)
if l_type == "work":
work_data = work_data_dict.get(str(l_id), False)
if not work_data:
continue
data.append(work_data)
return {"code": 0, "message": "获取成功!", "data": data, "process_ids": process_list, "count": task_count}
class InheritRokeWorkstationTaskDispatch(RokeWorkstationTaskDispatch):
@http.route('/roke/workstation/product_task/get_document_list', type='json', auth='none', csrf=False, cors="*")
def product_task_get_document_list(self):
_self = http.request
work_order_id = _self.jsonrequest.get("work_order_id", False)
if not work_order_id:
return {"code": 1, "message": f"入参错误!工单ID为必传数据。!", "data": []}
work_order = _self.env["roke.work.order"].sudo().search([("id", "=", work_order_id)])
if not work_order:
res = super(InheritRokeWorkstationTaskDispatch, self).product_task_get_document_list()
return res
if work_order.type == "返修":
repair_order_line = _self.env["roke.repair.order.line"].sudo().search([
("repair_work_order_id", "=", work_order.id)
], limit=1)
if not repair_order_line:
res = super(InheritRokeWorkstationTaskDispatch, self).product_task_get_document_list()
return res
_self.jsonrequest["work_order_id"] = work_order.repair_wr_id.work_order_id.ids
elif work_order.type == "补件":
scrap_order_line = _self.env["roke.scrap.order.line"].sudo().search([
("scrap_work_order_ids", "=", work_order.id)
], limit=1)
if not scrap_order_line:
res = super(InheritRokeWorkstationTaskDispatch, self).product_task_get_document_list()
return res
task_id = scrap_order_line.order_id.wr_id.work_order_id.task_id or \
scrap_order_line.order_id.wr_id.work_order_id.repair_task_id
work_order_ids = task_id.work_order_ids
new_work_order_id = 0
for v in work_order_ids:
if work_order.process_id.id != v.process_id.id:
continue
new_work_order_id = v.id
break
_self.jsonrequest["work_order_id"] = new_work_order_id
res = super(InheritRokeWorkstationTaskDispatch, self).product_task_get_document_list()
if work_order.type == "返修":
scrap_order_line = _self.env["roke.repair.order.line"].sudo().search([
("repair_work_order_id", "=", work_order.id)
], limit=1)
record_id = scrap_order_line.wr_id
elif work_order.type == "补件":
scrap_order_line = _self.env["roke.scrap.order.line"].sudo().search([("scrap_work_order_ids", "=", work_order.id)],
limit=1)
record_id = scrap_order_line.wr_id
else:
return res
attachment_ids = _self.env['ir.attachment'].sudo().search([
("res_model", "=", "roke.work.record"), ("res_id", "=", record_id.id)
])
base_url = _self.env['ir.config_parameter'].sudo().get_param('web.base.url')
for attachment in attachment_ids:
if not attachment.access_token:
attachment.generate_access_token()
name = f"{attachment.name}"
if attachment.mimetype == "application/pdf":
# pdf 预览
content_url = parse.quote(
"/web/content/%s?access_token=%s" % (str(attachment.id), attachment.sudo().access_token))
url = f"{base_url}/web/static/lib/pdfjs/web/viewer.html?file={content_url}"
res["data"].append({
"id": attachment.id,
"name": name,
"mimetype": attachment.mimetype,
"type": "url",
"data": url
})
else:
if attachment.index_content == 'image':
url = f"{base_url}/web/image/{attachment.id}?access_token={attachment.access_token}" \
f"&unique={str(fields.Datetime.now().timestamp())}"
res["data"].append({
"id": attachment.id,
"name": name,
"mimetype": attachment.mimetype,
"type": "url",
"data": url
})
else:
url = f"{base_url}/web/content/{attachment.id}?access_token={attachment.access_token}" \
f"&unique={str(fields.Datetime.now().timestamp())}"
res["data"].append({
"id": attachment.id,
"name": name,
"mimetype": attachment.mimetype,
"type": "url",
"data": url,
})
return res
...@@ -4,7 +4,6 @@ import os ...@@ -4,7 +4,6 @@ import os
from jinja2 import FileSystemLoader, Environment from jinja2 import FileSystemLoader, Environment
from odoo import models, fields, api, http, SUPERUSER_ID, _ from odoo import models, fields, api, http, SUPERUSER_ID, _
from odoo.addons.roke_mes_quality.controller.inherit_production import InheritProduction
from odoo.addons.roke_mes_production.controller.work_report import WorkReportKanban from odoo.addons.roke_mes_production.controller.work_report import WorkReportKanban
import logging import logging
import math import math
...@@ -12,113 +11,8 @@ import math ...@@ -12,113 +11,8 @@ import math
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class JzjxInheritProduction(InheritProduction):
def _get_work_record_values(self, wo, values):
"""
获取创建工单需要的数据:报工采集结果
scrap_qty:报废数
repair_qty:返修数
scrap_list:报废明细---->[{"reason_id": 报废原因ID, "qty": 报废数量}]
repair_list:返修明细---->[{"reason_id": 返修原因ID, "qty": 返修数量}]
:param wo: 工单
:param values: 入参
:return:
"""
res = super(JzjxInheritProduction, self)._get_work_record_values(wo, values)
repair_process_id = values.get('process_id', False) # 工序
scrap_list, _ = values.get("scrap_list", []), values.get("repair_list", [])
if repair_process_id:
res.update({"repair_process_id": repair_process_id})
no_scrap_detail_ids = []
for scrap in scrap_list:
scrap_qty = float(scrap.get("qty", 0))
if scrap_qty:
continue
no_scrap_detail_ids.append((0, 0, {
'reason_id': int(scrap.get("reason_id")),
'qty': scrap_qty,
'note': scrap.get("note")
}))
res.update({
"scrap_detail_ids": res.get("scrap_detail_ids", []) + no_scrap_detail_ids,
})
return res
def check_join_in_data(self, values):
work_order_id = values.get('work_order_id', False) # 工单ID
product_id = values.get('product_id', False) # 产品
process_id = values.get('process_id', False) # 工序
finish_qty = float(values.get('finish_qty') or 0) # 合格数量
unqualified_qty = float(values.get('unqualified_qty') or 0) # 不合格数量
work_hours = float(values.get('work_hours') or 0) # 工时数
employee_list = values.get('employee_list', []) # 人员分配:[{'employee_id':1, 'weighted': 1}]
repair_qty = values.get('repair_qty', False) # 人员分配:[{'employee_id':1, 'weighted': 1}]
# 校验入参工单ID、产品、工序、人员列表、不合格数和报废数、返修数
if not work_order_id and (not product_id or not process_id):
return {"state": "error", "msgs": "无工单ID时表示无工单报工,必须入参产品ID和工序ID"}
if not employee_list or type(employee_list) not in (list, tuple):
return {"state": "error", "msgs": "请选择人员"}
if (repair_qty and repair_qty < 0) or (float(finish_qty) < 0 or float(unqualified_qty) < 0):
return {"state": "error", "msgs": "合格数或不合格数不得小于0"}
# 判断是否能获取到辅计量数据
aux_list = values.get('aux_list', []) # 合格数量辅计量数据
unaux_list = values.get('unaux_list', []) # 不合格辅计量数据
if aux_list or unaux_list:
finish_aux_list = [aux.get('aux_qty', 0) for aux in aux_list if aux.get('aux_qty', 0) > 0]
unqualified_aux_list = [aux.get('aux_qty', 0) for aux in unaux_list if aux.get('aux_qty', 0) > 0]
if not float(finish_qty) and not float(unqualified_qty) and not float(
work_hours) and not finish_aux_list and not unqualified_aux_list:
return {"state": "error", "msgs": "合格数或不合格数或工时数不可同时为0"}
else:
if not repair_qty and not float(finish_qty) and not float(unqualified_qty) and not float(work_hours):
return {"state": "error", "msgs": "合格数或不合格数或工时数不可同时为0"}
return False
class JzjxRokeRefixAutoWorkOrder(http.Controller): class JzjxRokeRefixAutoWorkOrder(http.Controller):
@http.route('/roke/config/get_refix_auto_work_order', type='json', auth='none', csrf=False, cors="*")
def get_refix_auto_work_order(self):
_self = http.request
refix_params = _self.env['ir.config_parameter'].sudo().get_param("refix_auto_work_order")
return {"code": 0, "message": "成功!", "state": refix_params == "True" or refix_params is True}
@http.route('/roke/work_record/get_image_data', type='json', auth='user', csrf=False, cors="*")
def work_record_get_image_data(self):
"""
获取返修/报废工单的反馈图片
"""
_self = http.request
work_order_id = _self.jsonrequest.get("work_order_id", 0)
if not work_order_id:
return {"code": 1, "message": "入参错误!工单ID为必传参数。", "data": []}
work_order = _self.env["roke.work.order"].search([("id", "=", work_order_id)])
if not work_order:
return {"code": 1, "message": "校验失败!未找到该工单数据。", "data": []}
if work_order.type == "返修":
scrap_order_line = _self.env["roke.repair.order.line"].search([
("repair_work_order_id", "=", work_order.id)
], limit=1)
record_id = scrap_order_line.wr_id
elif work_order.type == "补件":
scrap_order_line = _self.env["roke.scrap.order.line"].search([("scrap_work_order_ids", "=", work_order.id)],
limit=1)
record_id = scrap_order_line.wr_id
else:
return {"code": 1, "message": "校验失败!该工单不是返修/报废工单。", "data": []}
data_list = []
attachment = _self.env['ir.attachment'].search([
("res_model", "=", "roke.work.record"), ("res_id", "=", record_id.id)
])
for v in attachment:
if not v.access_token:
v.generate_access_token()
url = f"/web/image/{v.id}?access_token={v.access_token}&unique={str(fields.Datetime.now().timestamp())}"
data_list.append(url)
return {"code": 0, "message": "获取成功!", "type": work_order.type, "data": data_list,
"note": record_id.note or ""}
@http.route('/roke/mes/work_time/get', type='json', auth="user", csrf=False, cors='*') @http.route('/roke/mes/work_time/get', type='json', auth="user", csrf=False, cors='*')
def get_work_time(self): def get_work_time(self):
""" """
......
...@@ -24,43 +24,11 @@ class InheritRokeWorkstationWorkOrder(RokeWorkstationWorkOrder): ...@@ -24,43 +24,11 @@ class InheritRokeWorkstationWorkOrder(RokeWorkstationWorkOrder):
继承父级获取工单信息接口,添加返修单/补件单获取上级报工工单的所有工艺信息数据和工艺详情信息数据 继承父级获取工单信息接口,添加返修单/补件单获取上级报工工单的所有工艺信息数据和工艺详情信息数据
""" """
_self = http.request _self = http.request
work_order_id = _self.jsonrequest.get("work_order_id", 0)
res = super(InheritRokeWorkstationWorkOrder, self).workstation_work_order() res = super(InheritRokeWorkstationWorkOrder, self).workstation_work_order()
work_order = _self.env["roke.work.order"].search([("id", "=", work_order_id)])
next_work_order = _self.env["roke.work.order"].search([("id", "=", res.get("data", {}).get("id", 0))]) next_work_order = _self.env["roke.work.order"].search([("id", "=", res.get("data", {}).get("id", 0))])
res.get("data", {}).update({ res.get("data", {}).update({
"next_process_name": next_work_order.next_wo_id.process_id.name or "" "next_process_name": next_work_order.next_wo_id.process_id.name or ""
}) })
if not work_order_id or not work_order:
return res
if work_order.type == "返修":
repair_order_line = _self.env["roke.repair.order.line"].search([
("repair_work_order_id", "=", work_order.id)
], limit=1)
if not repair_order_line:
return res
res.get("data", {}).update({
"routing_id": work_order.repair_wr_id.work_order_id.task_id.routing_id.id,
"routing_line_id": work_order.repair_wr_id.work_order_id.routing_line_id.id
})
elif work_order.type == "补件":
scrap_order_line = _self.env["roke.scrap.order.line"].search([("scrap_work_order_ids", "=", work_order.id)],
limit=1)
if not scrap_order_line:
return res
task_id = scrap_order_line.order_id.wr_id.work_order_id.task_id or \
scrap_order_line.order_id.wr_id.work_order_id.repair_task_id
routing_id = task_id.routing_id
line_id = 0
for v in routing_id.line_ids:
if work_order.process_id.id != v.process_id.id:
continue
line_id = v.id
break
res.get("data", {}).update({
"routing_id": routing_id.id,
"routing_line_id": line_id
})
return res return res
...@@ -222,101 +190,6 @@ class RokeWorkstationWorkOrderModel(http.Controller): ...@@ -222,101 +190,6 @@ class RokeWorkstationWorkOrderModel(http.Controller):
return {"code": 0, "message": "工序信息添加成功", "data": {"routing_id": routing_obj.id}} return {"code": 0, "message": "工序信息添加成功", "data": {"routing_id": routing_obj.id}}
@http.route('/roke/workstation/work_record/workstation_work_record', type='json', auth='user', csrf=False, cors="*")
def get_workstation_work_record(self):
"""
获取工单的不良报工记录
"""
_self = http.request
work_order_id = _self.jsonrequest.get("work_order_id", 0)
limit = _self.jsonrequest.get("limit", 20)
page = _self.jsonrequest.get("page", 1)
if not work_order_id:
return {"code": 1, "message": f"入参错误! “工单ID”为必传数据。", "data": []}
record_ids = _self.env["roke.work.record"].search([
("unqualified_qty", "!=", 0),
("work_order_id", "=", work_order_id)
], order="create_date desc", limit=limit, offset=(page - 1) * limit)
data = []
for v in record_ids:
scrap_name_list = v.scrap_line_ids.reason_id.mapped("name")
data.append({
"id": v.id,
"scrap_name": (scrap_name_list and scrap_name_list[0]) or "",
"unqualified_qty": v.unqualified_qty or 0,
"scrap_qty": sum(v.scrap_line_ids.mapped("qty")),
"repair_qty": sum(v.repair_line_ids.mapped("qty")),
"is_rfe": v.scrap_line_ids.order_id.is_rfe,
"work_time": pytz_conversion(_self, v.work_time.strftime('%Y-%m-%d %H:%M'))
})
return {"code": 0, "message": f"获取成功!", "data": data}
@http.route('/roke/workstation/work_record/get_workstation_work_process', type='json', auth='user', csrf=False, cors="*")
def get_workstation_work_process(self):
"""
获取工单的任务内的工序
"""
_self = http.request
work_order_id = _self.jsonrequest.get("work_order_id", 0)
if not work_order_id:
return {"code": 1, "message": f"入参错误! “工单ID”为必传数据。", "data": []}
work_order = _self.env["roke.work.order"].search([("id", "=", work_order_id)])
if not work_order_id:
return {"code": 1, "message": f"校验错误! 没找到对应的工单。", "data": []}
data = []
work_order_ids = work_order.task_id.work_order_ids or work_order.repair_task_id.work_order_ids
for v in work_order_ids:
data.append({
"id": v.process_id.id or 0,
"name": v.process_id.name or ""
})
return {"code": 0, "message": f"获取成功!", "data": data}
@http.route('/roke/workstation/scrap_order/get_workstation_work_process', type='json', auth='user', csrf=False,
cors="*")
def scrap_order_get_workstation_work_process(self):
"""
生成补件工单
"""
_self = http.request
work_record_id = _self.jsonrequest.get("work_record_id", 0)
process_list = _self.jsonrequest.get("process_list", [])
if not work_record_id:
return {"code": 1, "message": f"入参错误! “报工记录ID”为必传数据。"}
if not process_list:
return {"code": 1, "message": f"入参错误! “工序”为必传数据。"}
work_record = _self.env["roke.work.record"].search([("id", "=", work_record_id)])
if not work_record_id:
return {"code": 1, "message": f"校验错误! 没找到对应的报工记录。"}
work_order_ids = []
index = 1
# qty = 0
for v in process_list:
plan_qty = v.get("qty", 0)
# qty = plan_qty if qty == 0 or qty > plan_qty else qty
process_id = v.get("id", 0)
work_order_ids.append((0, 0, {
"process_id": process_id,
"product_id": work_record.work_order_id.product_id.id,
"plan_qty": plan_qty,
"sequence": index,
"planned_start_time": work_record.work_order_id.planned_start_time,
"plan_date": work_record.work_order_id.plan_date,
"repair_task_id": work_record.pt_id.id or work_record.work_order_id.repair_task_id.id,
"repair_wr_id": work_record.work_order_id.repair_wr_id.id or work_record.id,
"type": "补件"
}))
index += 1
for v in work_record.scrap_line_ids:
v.write({
"scrap_work_order_ids": work_order_ids,
# "replenish_qty": v.replenish_qty + qty, # 零部件问题: 导致已补数量没法计算
"is_rfe": True
})
break
work_record.scrap_line_ids.order_id.write({"is_rfe": True})
return {"code": 0, "message": f"补件工单创建成功!"}
@http.route('/roke/workstation/craft_design/workstation_work_process_check_work_order', type='json', auth='user', @http.route('/roke/workstation/craft_design/workstation_work_process_check_work_order', type='json', auth='user',
csrf=False, cors="*") csrf=False, cors="*")
def workstation_work_process_check_work_order(self): def workstation_work_process_check_work_order(self):
......
...@@ -2,7 +2,4 @@ from . import inherit_roke_work_order ...@@ -2,7 +2,4 @@ from . import inherit_roke_work_order
from . import inherit_production_task from . import inherit_production_task
from . import inherit_workcenter from . import inherit_workcenter
from . import work_log from . import work_log
from . import inherit_res_config_settings
from . import inheirt_roke_repair_order
from . import inherit_roke_scrap_order
from . import inherit_roke_routing from . import inherit_roke_routing
import logging
from . import generator
from odoo import models, fields, api, _
_logger = logging.getLogger(__name__)
class JzjxInheritRepairOrder(models.Model):
_inherit = "roke.repair.order"
is_refix_auto_work_order = fields.Boolean(string="是否自动生产返修单")
class JzjxInheritRepairOrderLine(models.Model):
_inherit = "roke.repair.order.line"
repair_work_order_id = fields.Many2one("roke.work.order", string="返修工单")
is_refix_auto_work_order = fields.Boolean(string="是否自动生产返修单")
scrap_id = fields.Many2one("roke.scrap.reason", string="报废原因", ondelete='restrict')
from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError
class JzjxInheritConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
refix_auto_work_order = fields.Boolean(string="返修自动生产工单", default=False)
@api.model
def get_values(self):
res = super(JzjxInheritConfigSettings, self).get_values()
refix_auto_work_order = self.env['ir.config_parameter'].sudo().get_param("refix_auto_work_order")
res.update(
refix_auto_work_order=refix_auto_work_order
)
return res
def set_values(self):
super(JzjxInheritConfigSettings, self).set_values()
self.env['ir.config_parameter'].sudo().set_param('refix_auto_work_order', self.refix_auto_work_order)
def get_refix_params(self):
return self.refix_auto_work_order
...@@ -6,61 +6,6 @@ from odoo import api, models, fields ...@@ -6,61 +6,6 @@ from odoo import api, models, fields
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class InheritRokeRoutingModel(models.Model):
_inherit = "roke.routing"
routing_task_id = fields.Many2one("roke.production.task")
def _get_check_vals(self, check):
data = {
"sequence": check.sequence,
"name": check.name,
"description": check.description,
"input_type": check.input_type,
"standard_value": check.standard_value,
"upper_value": check.upper_value,
"lower_value": check.lower_value,
}
check_option = []
for v in check.select_item_ids:
check_option.append((0, 0, {
"sequence": v.sequence,
"value": v.value
}))
data.update({
"select_item_ids": check_option
})
return data
def get_routing_line_value(self, line):
"""
获取工艺明细内容
:param process:
:return:
"""
res = super(InheritRokeRoutingModel, self).get_routing_line_value(line)
check_ids = []
for v in line.check_ids:
check_ids.append((0, 0, self._get_check_vals(v)))
res.update({
"scrap_reason_ids": [(6, 0, line.scrap_reason_ids.ids)],
"check_ids": check_ids,
"document_ids": [(6, 0, line.document_ids.ids)]
})
return res
def _get_standard_item_vals(self, standard_item):
"""
作业规范
"""
res = super(InheritRokeRoutingModel, self)._get_standard_item_vals(standard_item)
res.update({
"description": standard_item.description or "",
"sequence": standard_item.sequence,
})
return res
class InheritRokeRoutingLineModel(models.Model): class InheritRokeRoutingLineModel(models.Model):
_inherit = "roke.routing.line" _inherit = "roke.routing.line"
......
import logging
from . import generator
from odoo import models, fields, api, _
_logger = logging.getLogger(__name__)
class JzjxInheritScrapOrder(models.Model):
_inherit = "roke.scrap.order"
is_rfe = fields.Boolean(string="是否工单补件")
class JzjxInheritScrapOrderLine(models.Model):
_inherit = "roke.scrap.order.line"
scrap_work_order_ids = fields.Many2many("roke.work.order", string="补件工单")
is_rfe = fields.Boolean(string="是否工单补件")
...@@ -7,8 +7,6 @@ class InheritWorkOrder(models.Model): ...@@ -7,8 +7,6 @@ class InheritWorkOrder(models.Model):
document_ids = fields.Many2many(related="task_id.document_ids", string="作业指导") document_ids = fields.Many2many(related="task_id.document_ids", string="作业指导")
task_file_ids = fields.Many2many(related="task_id.file_ids") task_file_ids = fields.Many2many(related="task_id.file_ids")
repair_task_id = fields.Many2one('roke.production.task', string="上级任务")
repair_wr_id = fields.Many2one('roke.work.record', string="原始返修报工单")
next_wo_id = fields.Many2one("roke.work.order", string="下道工单", store=True, compute="_compute_next_work_order") next_wo_id = fields.Many2one("roke.work.order", string="下道工单", store=True, compute="_compute_next_work_order")
...@@ -33,38 +31,6 @@ class InheritWorkOrder(models.Model): ...@@ -33,38 +31,6 @@ class InheritWorkOrder(models.Model):
else: else:
v.next_wo_id = next_wo[0].id v.next_wo_id = next_wo[0].id
def write(self, vals):
id_dict = {}
for v in self:
id_dict[str(v.id)] = {"state": v.state, "old_finish_qty": v.finish_qty}
res = super(InheritWorkOrder, self).write(vals)
for v in self:
old_dict = id_dict.get(str(v.id), "")
old_state = old_dict.get("state", "")
old_finish_qty = old_dict.get("old_finish_qty", 0)
if "state" not in vals.keys():
return res
state = vals.get("state", "")
if state in ["已完工", "强制完成"]:
repair_order_id = self.env["roke.repair.order.line"].sudo().search([
("repair_work_order_id", "=", self.id)], limit=1)
if repair_order_id:
repair_order_id.write({
"state": "返修完成",
"execute_qty": repair_order_id.execute_qty + v.finish_qty
})
repair_order_id.order_id.write({"state": "返修完成"})
if state == "未完工" and old_state in ["暂停", "强制完工", "已完工"]:
repair_order_id = self.env["roke.repair.order.line"].sudo().search([
("repair_work_order_id", "=", self.id)], limit=1)
if repair_order_id:
repair_order_id.write({
"state": "返修中",
"execute_qty": repair_order_id.execute_qty + v.finish_qty - old_finish_qty
})
repair_order_id.order_id.write({"state": "返修中"})
return res
def _get_production_multiple(self, previous): def _get_production_multiple(self, previous):
""" """
获取当前生产倍数 获取当前生产倍数
...@@ -113,28 +79,3 @@ class InheritWorkOrder(models.Model): ...@@ -113,28 +79,3 @@ class InheritWorkOrder(models.Model):
else: else:
previous_multiple = previous.routing_line_id.multiple previous_multiple = previous.routing_line_id.multiple
return (multiple / previous_multiple) if previous_multiple else 0 return (multiple / previous_multiple) if previous_multiple else 0
class InheritRokeWorkRecordModel(models.Model):
_inherit = "roke.work.record"
def withdraw_work_order(self, work_order):
if not work_order.task_id and not work_order.record_ids and work_order.type == "生产":
# 无生产任务且当前工单下无其它报工记录时时,撤回直接删除工单
work_order.unlink()
def withdraw(self):
"""
撤回报工
:return:
"""
for v in self:
for repair in v.repair_line_ids:
if repair.repair_work_order_id.record_ids:
raise ValidationError("返修明细中的返修工单已报工,无法撤销报工!")
repair.repair_work_order_id.unlink()
for scrap in v.scrap_line_ids:
if scrap.scrap_work_order_ids.record_ids:
raise ValidationError("返修明细中的返修工单已报工,无法撤销报工!")
scrap.scrap_work_order_ids.unlink()
super(InheritRokeWorkRecordModel, self).withdraw()
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>工艺设</title> <title>工艺设</title>
<!-- 禁止界面缩放 --> <!-- 禁止界面缩放 -->
<meta content="width=device-width,initial-scale=1.0, maximum-scale=1.0,user-scalable=0" name="viewport" /> <meta content="width=device-width,initial-scale=1.0, maximum-scale=1.0,user-scalable=0" name="viewport" />
<!-- 引入本地文件--Vue、axios、element-ui的样式文件、element-ui的JS文件--> <!-- 引入本地文件--Vue、axios、element-ui的样式文件、element-ui的JS文件-->
...@@ -105,6 +105,22 @@ ...@@ -105,6 +105,22 @@
<span v-else>[[scope.row.content]]</span> <span v-else>[[scope.row.content]]</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="上限值" align="center">
<template slot-scope="scope">
<el-input-number style="width: 100%;" v-if="isEdit" size="medium"
v-model="scope.row.upper_value" :min="0">
</el-input-number>
<span v-else>[[scope.row.upper_value]]</span>
</template>
</el-table-column>
<el-table-column label="下限值" align="center">
<template slot-scope="scope">
<el-input-number style="width: 100%;" v-if="isEdit" size="medium"
v-model="scope.row.lower_value" :min="0">
</el-input-number>
<span v-else>[[scope.row.lower_value]]</span>
</template>
</el-table-column>
<el-table-column label="参数说明" align="center"> <el-table-column label="参数说明" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input v-if="isEdit" size="medium" type="textarea" autosize <el-input v-if="isEdit" size="medium" type="textarea" autosize
...@@ -450,9 +466,17 @@ ...@@ -450,9 +466,17 @@
<el-form-item label="参数名称:" prop="standard_title" required> <el-form-item label="参数名称:" prop="standard_title" required>
<el-input v-model="standardsForm.standard_title" placeholder="请填写参数名称"></el-input> <el-input v-model="standardsForm.standard_title" placeholder="请填写参数名称"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="值:" prop="standard_content" required> <el-form-item label="标准值:" prop="standard_content" required>
<el-input v-model="standardsForm.standard_content" placeholder="请填写值"></el-input> <el-input v-model="standardsForm.standard_content" placeholder="请填写值"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="标准下限:" prop="lower_value">
<el-input-number v-model="standardsForm.lower_value" :precision="2" placeholder="请填写标准下限"
:min="0"></el-input-number>
</el-form-item>
<el-form-item label="标准上限:" prop="upper_value">
<el-input-number v-model="standardsForm.upper_value" :precision="2" placeholder="请填写标准上限"
:min="0"></el-input-number>
</el-form-item>
<el-form-item label="参数说明:" prop="standard_description"> <el-form-item label="参数说明:" prop="standard_description">
<el-input type="textarea" :autosize="{ minRows: 2}" v-model="standardsForm.standard_description" <el-input type="textarea" :autosize="{ minRows: 2}" v-model="standardsForm.standard_description"
placeholder="请填写参数说明"> placeholder="请填写参数说明">
...@@ -619,7 +643,13 @@ ...@@ -619,7 +643,13 @@
activeIndex: "工艺参数", // 当前选中的导航菜单 activeIndex: "工艺参数", // 当前选中的导航菜单
isEdit: false, // 是否为编辑状态 isEdit: false, // 是否为编辑状态
standardsDialogShow: false, // 工艺参数添加弹窗状态 standardsDialogShow: false, // 工艺参数添加弹窗状态
standardsForm: {}, // 新建工艺参数表单数据 standardsForm: {
standard_title: '', // 参数名称
standard_content: '', // 参数值
lower_value: 0, // 下限值
upper_value: 0, // 上线值
standard_description: '', // 参数说明
}, // 新建工艺参数表单数据
// 添加工艺参数 必填效验 // 添加工艺参数 必填效验
standardsRules: { standardsRules: {
standard_title: [{ required: true, trigger: 'blur', message: '请输入参数名称' }], standard_title: [{ required: true, trigger: 'blur', message: '请输入参数名称' }],
...@@ -1880,7 +1910,13 @@ ...@@ -1880,7 +1910,13 @@
this.multipleSelection = [] this.multipleSelection = []
} else if (type == '添加工艺参数') { } else if (type == '添加工艺参数') {
this.standardsDialogShow = false this.standardsDialogShow = false
this.standardsForm = {} this.standardsForm = {
standard_title: '',
standard_content: '',
lower_value: 0,
upper_value: 0,
standard_description: '',
}
} else if (type == '添加设备检查项') { } else if (type == '添加设备检查项') {
this.checksDialogShow = false this.checksDialogShow = false
this.checksForm = { this.checksForm = {
...@@ -2086,6 +2122,8 @@ ...@@ -2086,6 +2122,8 @@
standard_title: this.standardsForm.standard_title, standard_title: this.standardsForm.standard_title,
standard_content: this.standardsForm.standard_content, standard_content: this.standardsForm.standard_content,
standard_description: this.standardsForm.standard_description, standard_description: this.standardsForm.standard_description,
lower_value: this.standardsForm.lower_value,
upper_value: this.standardsForm.upper_value,
} }
this.loading = true this.loading = true
this.requestApi("/roke/workstation/standard/add", config).then(result => { this.requestApi("/roke/workstation/standard/add", config).then(result => {
......
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="inherit_view_roke_repair_order_form_view" model="ir.ui.view">
<field name="name">inherit.roke.repair.order.form</field>
<field name="model">roke.repair.order</field>
<field name="inherit_id" ref="roke_mes_quality.view_roke_repair_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='line_ids']/tree//field[@name='wr_id']" position="after">
<field name="repair_work_order_id" options="{'no_create': True}"/>
<field name="scrap_id" options="{'no_create': True}"/>
</xpath>
<xpath expr="//field[@name='line_ids']/tree//button[@name='execute_repair']" position="replace">
<field name="is_refix_auto_work_order" invisible="1"/>
<button name="execute_repair" type="object" string="执行返修" class="oe_highlight"
attrs="{'invisible': ['|', ('allow_qty', '&lt;=', 0), ('is_refix_auto_work_order', '=', True)]}"/>
</xpath>
<xpath expr="//button[@name='multi_execute_repair']" position="replace">
<field name="is_refix_auto_work_order" invisible="1"/>
<button name="multi_execute_repair" type="object" string="批量执行返修" class="oe_highlight"
attrs="{'invisible': ['|', ('state', 'in', ['取消', '待确认', '返修完成']), '|',
('can_repair', '!=', True), ('is_refix_auto_work_order', '=', True)]}"/>
</xpath>
</field>
</record>
<record id="inherit_view_roke_repair_order_line_form" model="ir.ui.view">
<field name="name">inherit.roke.repair.order.line.form</field>
<field name="model">roke.repair.order.line</field>
<field name="inherit_id" ref="roke_mes_quality.view_roke_repair_order_line_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='product_id']" position="after">
<field name="repair_work_order_id" options="{'no_create': True}"/>
<field name="scrap_id" options="{'no_create': True}"/>
</xpath>
<xpath expr="//button[@name='execute_repair']" position="replace">
<field name="is_refix_auto_work_order" invisible="1"/>
<button name="execute_repair" type="object" string="执行返修" class="oe_highlight"
attrs="{'invisible': ['|', ('allow_qty', '&lt;=', 0), ('is_refix_auto_work_order', '=', True)]}"/>
</xpath>
</field>
</record>
<record id="inherit_view_roke_repair_order_line_tree" model="ir.ui.view">
<field name="name">inherit.roke.repair.order.line.tree</field>
<field name="model">roke.repair.order.line</field>
<field name="inherit_id" ref="roke_mes_quality.view_roke_repair_order_line_tree"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='execute_repair']" position="replace">
<field name="scrap_id"/>
<field name="is_refix_auto_work_order" invisible="1"/>
<button name="execute_repair" type="object" string="执行返修" class="oe_highlight"
attrs="{'invisible': ['|', ('allow_qty', '&lt;=', 0), ('is_refix_auto_work_order', '=', True)]}"/>
</xpath>
</field>
</record>
</odoo>
\ No newline at end of file
...@@ -48,25 +48,4 @@ ...@@ -48,25 +48,4 @@
</xpath> </xpath>
</field> </field>
</record> </record>
<record id="jzjx_inherit_config_settings_form" model="ir.ui.view">
<field name="name">jzjx.inherit.config.settings.form.view</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="roke_mes_production.roke_mes_production_inherit_config_settings_form_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='production_setting_main']" position="inside">
<div class="col-12 col-lg-6 o_setting_box" title="返修自动生成工单" id="refix_auto_work_order">
<div class="o_setting_left_pane">
<field name="refix_auto_work_order"/>
</div>
<div class="o_setting_right_pane">
<label for="refix_auto_work_order"/>
<div class="text-muted">
勾选后,自动生成工单,将返修前置工单和当前生成工单绑定在返修单中。
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo> </odoo>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="inherit_view_roke_repair_order_form" model="ir.ui.view">
<field name="name">inherit.roke.scrap.order.line.form</field>
<field name="model">roke.scrap.order.line</field>
<field name="inherit_id" ref="roke_mes_quality.view_roke_scrap_order_line_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='eplenish_pt_ids']" position="after">
<page string="补件工单" name="scrap_work_order_ids">
<field name="scrap_work_order_ids" readonly="1"/>
</page>
</xpath>
</field>
</record>
<record id="inherit_view_roke_scrap_order_form" model="ir.ui.view">
<field name="name">inherit.roke.scrap.order.form</field>
<field name="model">roke.scrap.order</field>
<field name="inherit_id" ref="roke_mes_quality.view_roke_scrap_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='line_ids']/tree//button[@name='execute_replenish']" position="replace">
<field name="is_rfe" invisible="1"/>
<field name="allow_replenish_qty" invisible="1"/>
<button name="execute_replenish" type="object" string="执行补件" class="oe_highlight"
attrs="{'invisible': ['|', ('allow_replenish_qty', '&lt;=', 0), '|', ('state', 'in', ['取消', '待确认']), ('is_rfe', '=', True)]}"/>
</xpath>
<xpath expr="//button[@name='multi_execute_replenish']" position="replace">
<field name="is_rfe" invisible="1"/>
<button name="multi_execute_replenish" type="object" string="批量执行补件" class="oe_highlight"
attrs="{'invisible': ['|', ('state', 'in', ['取消', '待确认']), '|', ('can_replenish', '!=', True), ('is_rfe', '=', True)]}"/>
</xpath>
</field>
</record>
<record id="inherit_view_roke_scrap_order_line_tree" model="ir.ui.view">
<field name="name">inherit.roke.scrap.order.line.tree</field>
<field name="model">roke.scrap.order.line</field>
<field name="inherit_id" ref="roke_mes_quality.view_roke_scrap_order_line_tree"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='execute_replenish']" position="replace">
<field name="is_rfe" invisible="1"/>
<button name="execute_replenish" type="object" string="执行补件" class="oe_highlight"
attrs="{'invisible': ['|', ('allow_replenish_qty', '&lt;=', 0), '|', ('state', 'in', ['取消', '待确认']), ('is_rfe', '=', True)]}"/>
</xpath>
</field>
</record>
</odoo>
from . import inherit_roke_create_work_record_wizard
import datetime
import math
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
from odoo.tools.float_utils import float_round
import logging
_logger = logging.getLogger(__name__)
def _get_pd(env, index="Production"):
return env["decimal.precision"].precision_get(index)
def float_to_time(hours):
""" 将小时数转换为时间对象. """
if hours == 24.0:
return datetime.time.max.replace(microsecond=0)
fractional, integral = math.modf(hours)
return datetime.time(int(integral), int(float_round(60 * fractional, precision_digits=0)), 0)
class InheritRokeCreateWorkRecordWizard(models.TransientModel):
_inherit = "roke.create.work.record.wizard"
repair_process_id = fields.Many2one("roke.process", string="工序")
repair_qty = fields.Float(string="返修数", digits='Production', default=0)
def create_other_order(self, new_record):
"""
创建报废单、返修单
生产返修工单
:return:
"""
res = super(InheritRokeCreateWorkRecordWizard, self).create_other_order(new_record)
repair = res.get("repair", False)
refix_params = self.env['ir.config_parameter'].sudo().get_param("refix_auto_work_order")
if repair and self.repair_qty and (refix_params == "True" or refix_params is True) and self.repair_process_id:
repair.is_refix_auto_work_order = refix_params == "True" or refix_params is True
for v in repair.line_ids:
repair_work_order_id = self.env["roke.work.order"].create({
"process_id": self.repair_process_id.id,
"product_id": new_record.work_order_id.product_id.id,
"plan_qty": v.qty,
"sequence": 1,
"planned_start_time": new_record.work_order_id.planned_start_time,
"plan_date": new_record.work_order_id.plan_date,
"repair_task_id": new_record.pt_id.id or repair.wo_id.repair_task_id.id,
"repair_wr_id": repair.wo_id.repair_wr_id.id or new_record.id,
"repair_line_id": v.id,
"type": "返修"
})
scrap_id = self.scrap_detail_ids.reason_id.ids[0] if self.scrap_detail_ids and \
self.scrap_detail_ids.reason_id else False
data = {
"scrap_id": scrap_id,
"repair_work_order_id": repair_work_order_id,
"is_refix_auto_work_order": refix_params == "True" or refix_params is True
}
if repair_work_order_id.wo_start_state == '已开工':
data.update({"state": "返修中"})
repair.write({"state": "返修中"})
v.write(data)
return res
@api.onchange("unqualified_qty")
def _onchange_unqualified_qty(self):
"""不合格数默认为报废数"""
return {"value": {"scrap_qty": self.unqualified_qty}}
@api.onchange("scrap_qty")
def _onchange_scrap_qty(self):
"""
1.报废数大于不合格数时:设置报废数等于不合格数;返修数等于0
2.报废数加返修数大于不合格数时:设置返修数等于不合格数减报废数
:return:
"""
if self.scrap_qty > self.unqualified_qty:
return {"value": {"scrap_qty": self.unqualified_qty}}
@api.onchange("repair_qty")
def _onchange_repair_qty(self):
"""
1.返修数大于不合格数时:设置返修数等于不合格数;报废数等于0
2.返修数加报废数大于不合格数时:设置报废数等于不合格数减返修数
:return:
"""
... # 去掉返修和报废的逻辑关系
def check_create_value(self):
"""
检查完成数、不合格数、工时数
:return:
"""
if not self.finish_qty and not self.unqualified_qty and not self.work_hours and not self.repair_qty:
return False
else:
return True
def confirm(self, center=False):
"""
生成报工记录
:return:
"""
if self.work_order_id.wo_start_state == "未开工":
raise ValidationError("当前工单未开工,禁止报工")
if self.work_order_id.wo_child_type == "main" and self.work_order_id.child_wo_ids:
raise ValidationError("主工序工单禁止报工")
if self.work_order_id.state in ["暂停", "强制完工"]:
raise ValidationError("工单({})状态是{}不允许报工".format(self.work_order_id.code, self.work_order_id.state))
if not self.check_create_value():
raise ValidationError("完成数,不合格数,工时不能同时为空或0")
if self.multi and not self.allot_ids:
raise ValidationError("请填写报工人员。")
# 校验在此之前的工序报工数
if self.work_order_id.wo_child_type == "child" and self.work_order_id.main_wo_id:
previous = self.work_order_id._get_child_previous()
else:
previous = self.work_order_id._get_previous()
ConfigParameter = self.sudo().env['ir.config_parameter']
report_qty = self.finish_qty # 待校验的报工数
wait_qty = previous.finish_qty * self.work_order_id._get_production_multiple(previous)\
if previous and self.env.user.company_id.freedom_work != "允许" else self.wait_qty
if self.env.user.company_id.complete_basis != "合格数":
report_qty = round(report_qty + self.unqualified_qty, _get_pd(self.env)) # 待校验的报工数
else:
if self.env.user.company_id.freedom_work != "允许" and previous and previous.finish_qty <= 0:
raise ValidationError(f"前工序合格数为0,禁止报工。(如想取消该限制,请联系系统管理员将“自由报工”选项设置为“允许”)")
exceed_plan = self.env.user.company_id.exceed_plan
exceed_plan_qty = float(ConfigParameter.get_param('exceed.plan.qty', default=0)) if exceed_plan == "允许" else 0
if exceed_plan != "允许" or (exceed_plan == "允许" and exceed_plan_qty):
_logger.error(f"报工数量:{str(report_qty)} 计划 : {self.plan_qty} 剩余 : {self.wait_qty} 剩余二 :{str(wait_qty)}, {exceed_plan_qty}")
if report_qty > wait_qty + exceed_plan_qty:
raise ValidationError(f"报工数量:{str(report_qty)} 不可大于可报数量:{str(wait_qty)}。"
f"(如想取消该限制,请联系系统管理员将“超计划报工”选项设置为“允许”)")
# 校验报工时间是否超出班组报工时间限制
teams = self.team_id or self.allot_ids.employee_id.team_id or self.employee_id.team_id
restrict_date_team = teams.filtered(lambda team: team.restrict_work_date)
if restrict_date_team and not self.env.user.has_group("base.group_system"):
today = fields.Date.context_today(self)
last_days = min(restrict_date_team.mapped("last_days"))
after_days = max(restrict_date_team.mapped("after_days"))
last_time = datetime.datetime.combine(today - datetime.timedelta(days=last_days), float_to_time(max(restrict_date_team.mapped("last_time"))))
after_time = datetime.datetime.combine(today + datetime.timedelta(days=after_days), float_to_time(max(restrict_date_team.mapped("after_time"))))
work_time = self.work_time + datetime.timedelta(hours=8)
if work_time < last_time or work_time > after_time:
raise ValidationError("报工时间错误,当前人员可报工时间范围:%s 到 %s。" % (str(last_time), str(after_time)))
# 校验在此之前的工序报工数
if previous and self.env.user.company_id.freedom_work != "允许":
self._check_freedom_work()
# 创建报工记录
employee_ids, allot_list = self._get_employee_allot()
new_record = self.env["roke.work.record"]
try:
new_record = self.env["roke.work.record"].create(self._get_work_record_dict(employee_ids, allot_list))
self.create_other_order(new_record)
self.write({"wr_id": new_record.id})
# 工单完工
self.work_order_id.finish_report_work_order(self.finish_qty, self.unqualified_qty, self.work_hours, finish_time=self.work_time, wr_id=new_record.id)
# 工装生命周期扣除by:duqinglin
if new_record.work_center_id and new_record.process_id.is_press:
qty = new_record.unqualified_qty + new_record.finish_qty
for tool in new_record.work_center_id.tool_ids:
if tool.type_id.name != '模具':
continue
user_freq = math.ceil(qty / tool.once_qty)
tool.write({'use_record': [(0, 0, {'use_life_cycle': user_freq,
'use_users': self.employee_id.user_id.id,
'equipment_id': tool.equipment_id.id,
'use_type': '报工'})]})
tool.used_life_cycle = tool.used_life_cycle + user_freq
tool.residue_life_cycle = tool.standard_life_cycle - tool.used_life_cycle
except Exception as e:
_logger.error("!!!!!报工向导类报错!!!!!")
_logger.error(e)
if new_record:
_logger.error(new_record)
try:
new_record.withdraw()
except Exception as withdraw_error:
new_record.unlink()
raise e
return {'type': 'ir.actions.act_window_close'}
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="repair_view_quality_inherit_create_work_record_wizard_form" model="ir.ui.view">
<field name="name">repair.view.quality.inherit.create.wr.wizard.form</field>
<field name="model">roke.create.work.record.wizard</field>
<field name="inherit_id" ref="roke_mes_quality.view_quality_inherit_create_work_record_wizard_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='repair_qty']" position="replace">
<div name="repair_qty" class="o_row">
<field name="repair_qty"/>
<span>
<field name="uom_id"/>
</span>
</div>
</xpath>
<xpath expr="//label[@for='repair_qty']" position="replace">
<label for="repair_qty"/>
</xpath>
</field>
</record>
<record id="repair_view_roke_quality_inherit_multi_submit_wr_form_view" model="ir.ui.view">
<field name="name">repair.view.roke.quality.inherit.multi.submit.wr.form</field>
<field name="model">roke.multi.submit.work.record</field>
<field name="inherit_id" ref="roke_mes_quality.view_roke_quality_inherit_multi_submit_wr_form_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='line_ids']/tree//field[@name='repair_qty']" position="replace">
<field name="repair_qty" optional="show" sum="返修数量" decoration-warning="1"/>
</xpath>
<xpath expr="//field[@name='line_ids']/tree//field[@name='repair_reason_id']" position="replace">
<field name="repair_reason_id" optional="show" decoration-warning="1"/>
</xpath>
<xpath expr="//field[@name='line_ids']/form//field[@name='repair_qty']" position="replace">
<field name="repair_qty" optional="show" sum="返修数量" decoration-warning="1"/>
</xpath>
<xpath expr="//field[@name='line_ids']/form//field[@name='repair_reason_id']" position="replace">
<field name="repair_reason_id" optional="show" decoration-warning="1"/>
</xpath>
</field>
</record>
</odoo>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment