Commit a1bdf5d3 by 夏超

[add] 新增东联项目功能

parent 57791b52
import datetime
import json
import os
from jinja2 import FileSystemLoader, Environment
from odoo import models, fields, api, http, SUPERUSER_ID, _
from odoo.addons.roke_mes_production.controller.work_report import WorkReportKanban
import logging
import math
_logger = logging.getLogger(__name__)
class JzjxRokeRefixAutoWorkOrder(http.Controller):
@http.route('/roke/mes/work_time/get', type='json', auth="user", csrf=False, cors='*')
def get_work_time(self):
"""
获取工时树
:return:
"""
uid = http.request.uid or http.request.session.uid
if not uid:
return {"code": 1, "message": "当前位置尚未登录,请先登录", "work_hours": 0}
start_record = http.request.env(user=SUPERUSER_ID)['roke.work.start.record'].search([
("user_id", "=", uid),
("state", "=", "工作中")
], limit=1)
if not start_record:
return {"code": 1, "message": "未开工,请先开工。", "work_hours": 0}
delta = datetime.datetime.now() - start_record.start_time
work_hours = round(delta.total_seconds() / 3600, 2)
return {"code": 0, "message": "获取成功!", "work_hours": work_hours}
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
templateloader = FileSystemLoader(searchpath=BASE_DIR + "/static/src/html/view")
env = Environment(loader=templateloader)
class JzjxRokeWorkReportKanban(WorkReportKanban):
@http.route('/roke/work/report/work_order_report', type='http', auth='public', csrf=False)
def work_order_report(self):
"""工单报工"""
values = {}
# 修改Jinja2 分隔符
env.variable_start_string = '[['
env.variable_end_string = ']]'
template = env.get_template('zdy_gdbg.html')
html = template.render(values)
return html
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="fscut_app_app_id" model="ir.config_parameter">
<field name="key">fscut.app_id</field>
<field name="value">op191458064d64e10d</field>
</record>
<record id="fscut_app_secret" model="ir.config_parameter">
<field name="key">fscut.app_secret</field>
<field name="value">64a9af1225e0e10ad20d532d8037a211ea679345313969fe8f277fa78f85e92d</field>
</record>
</data>
</odoo>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="ir_cron_sync_user_devices" model="ir.cron">
<field name="name">获取机床列表</field>
<field name="model_id" ref="model_roke_work_center"/>
<field name="state">code</field>
<field name="code">model.get_user_devices()</field>
<field name="interval_number">1</field>
<field name="interval_type">months</field>
<field name="numbercall">-1</field>
<field name="doall" eval="True"/>
<field name="active" eval="False" />
</record>
<record id="ir_cron_sync_work_logs" model="ir.cron">
<field name="name">获取机床加工记录</field>
<field name="model_id" ref="model_roke_work_center"/>
<field name="state">code</field>
<field name="code">
# 默认取当前时间前十分钟的加工记录。
# 如果需要取其它时间的价格记录,请入参开始/结束时间(格式“年-月-日 时:分:秒”);
# 如果需求取当前时间的前20分钟的加工记录,那么入参时间间隔time_interval(单位分钟)。
# 比如:model.get_work_logs(start_time="2024-01-01 0:00:00", end_time="2024-01-01 8:00:00") 或 model.get_work_logs(time_interval=20)
model.get_work_logs()
</field>
<field name="interval_number">10</field>
<field name="interval_type">minutes</field>
<field name="numbercall">-1</field>
<field name="doall" eval="True"/>
<field name="active" eval="False" />
</record>
</data>
</odoo>
\ No newline at end of file
from . import inherit_roke_work_order
from . import inherit_production_task
from . import inherit_workcenter
from . import work_log
from . import inherit_roke_routing
# import requests
#
# import re
#
#
# def process_url(web_base_url):
# # 替换 http:// 或 https://
# web_base_url = re.sub(r'^https?://', '', web_base_url)
# # 删除斜杠 /
# web_base_url = web_base_url.replace("/", "")
# return web_base_url
#
# # Uncaught (in promise) TypeError: self.keepRun is not a function
# # 测试
# web_base_url = "https://example.com/"
# processed_url = process_url(web_base_url)
#
#
# def upload_file(url, file_path, processed_url):
# try:
# files = {'file': open(file_path, 'rb')}
# print({'file': open(file_path, 'rb')})
# data = {'filePath': processed_url}
# response = requests.post(url, files=files, data=data)
# if response.status_code == 200:
# return response.json()
# else:
# return None
# except requests.exceptions.RequestException as e:
# return e
#
#
# file_path = r"C:\Users\zhangsan\Desktop\改BL320200-70S底盖(2).SLDPRT"
#
# data = upload_file(url, file_path, processed_url)
# if data:
# print("获取到的数据:", data)
# else:
# print("获取数据失败。")
# import json
# import requests
#
# url = "http://123.129.207.22:8088/cad/uploadFileUrl"
# dict_ = {
# 'ossId': "1772107631008669698",
# 'url': "http://121.37.69.162:9000/roke/localhost:8022/2024/03/25/274c6b3c80e34b059563874f5600ac20.DXF"
# }
#
# json_ = json.dumps(dict_, ensure_ascii=False)
# datas = requests.post(url, data=json_)
# content = json.loads(datas.content)
# print(content)
# dataaaa = content["data"]
# print(dataaaa)
# -*- coding: utf-8 -*-
"""
Description:
Versions:
Created by www.rokedata.com<HuChuanwei>
"""
import hashlib
import json
import time
class OpenApiHeader:
def __init__(self, app_id, timestamp, app_sign):
self.appID = app_id
self.timestamp = timestamp
self.appSign = app_sign
def to_json(self):
data = {
"app-id": self.appID,
"time-stamp": str(self.timestamp),
"app-sign": self.appSign
}
return json.dumps(data)
def to_dict(self):
return {
"app-id": self.appID,
"time-stamp": self.timestamp,
"app-sign": self.appSign
}
class OpenApiHeaderHelper:
def __init__(self, app_id, app_secret):
self.app_id = app_id
self.app_secret = app_secret
def gen_json(self):
openApiHeader = self._do_gen_header()
return openApiHeader.to_json()
def gen_map(self):
openApiHeader = self._do_gen_header()
return openApiHeader.to_dict()
def _do_gen_header(self):
timestamp = int(time.time() * 1000)
appSign = self._do_md5_hash(self.app_id + self.app_secret + str(timestamp))
return OpenApiHeader(self.app_id, timestamp, appSign)
@staticmethod
def _do_md5_hash(content):
hash_object = hashlib.md5(content.encode())
return hash_object.hexdigest()
\ No newline at end of file
import datetime
import pymysql
import logging
from odoo import api, models, fields
_logger = logging.getLogger(__name__)
class InheritRokeRoutingLineModel(models.Model):
_inherit = "roke.routing.line"
def write(self, vals):
res = super(InheritRokeRoutingLineModel, self).write(vals)
return res
# -*- coding: utf-8 -*-
"""
Description:
Versions:
Created by www.rokedata.com<HuChuanwei>
"""
import base64
import io
import json
import time
import datetime
import requests
import logging
from . import generator
from odoo import models, fields, api, _
_logger = logging.getLogger(__name__)
class InheritWorkCenter(models.Model):
_inherit = "roke.work.center"
app_name = fields.Char(string="切割软件名称")
app_ver = fields.Char(string="切割软件版本")
card_id = fields.Char(string="控制卡ID")
# 机床加工中的任务
filename = fields.Char(string="加工文件")
portionId = fields.Char(string="排版ID")
startTime = fields.Datetime(string="开始时间")
# 机床状态
deviceState = fields.Selection([
("OFFLINE", "离线"),
("WORKING", "加工中"),
("ALARMING", "报警中"),
("IDLE", "空闲"),
("UNKNOWN", "未知"),
("CLOSE", "关闭切割软件"),
("PAUSE", "暂停加工"),
("STOP", "停止加工")
], string="机床状态")
# 机床切割系统状态
axisX = fields.Float(string="X轴")
axisY = fields.Float(string="Y轴")
axisZ = fields.Integer(string="Z轴")
workTime = fields.Float(string="加工时长")
workTimeStr = fields.Char(string="加工时长")
workSpeed = fields.Integer(string="加工速度")
cutPercent = fields.Float(string="加工进度(%)")
laserPower = fields.Integer(string="激光器功率")
pwmFreq = fields.Integer(string="Pwm频率(Hz)")
gasType = fields.Char(string="气体类型")
gasPressure = fields.Integer(string="切割气压")
pwmRatio = fields.Integer(string="Pwm占空比(%)")
targetHeight = fields.Integer(string="跟随高度(设定值)")
diodeCurrent = fields.Integer(string="峰值功率(%)")
taskName = fields.Char(string="任务名称")
def _request_work_logs(self, card_id, headers, start_time, end_time, time_interval, page_number=0, page_size=50, total=None):
"""
请求加工记录接口
:return:
"""
if not start_time or not end_time:
end_datetime = fields.Datetime.now() + datetime.timedelta(hours=8)
start_datetime = end_datetime - datetime.timedelta(minutes=time_interval)
start_time = start_datetime.strftime("%Y-%m-%d %H:%M:%S")
end_time = end_datetime.strftime("%Y-%m-%d %H:%M:%S")
url = "https://mcs-gateway.fscut.com/api/statistics/work_logs/v2"
payload = json.dumps({
"cardId": card_id,
"startTime": start_time,
"endTime": end_time,
"pageNumber": page_number,
"pageSize": page_size,
"timeDesc": False
})
response = requests.request("POST", url, headers=headers, data=payload)
response_dict = json.loads(response.text)
if response_dict.get("status") != 0:
_logger.error("获取机床加工记录错误:")
_logger.error(response_dict)
return []
response_data = response_dict.get("data")
result = response_data.get("list")
if not total:
total = response_data.get("meta").get("total")
if (page_number + 1) * page_size < total:
time.sleep(1)
result += self._request_work_logs(
card_id,
headers,
start_time,
end_time,
time_interval,
page_number=page_number + 1,
page_size=page_size,
total=total
)
return result
def _get_request_headers(self):
"""
获取请求头
:return:
"""
app_id = self.env["ir.config_parameter"].get_param("fscut.app_id")
app_secret = self.env["ir.config_parameter"].get_param("fscut.app_secret")
helper = generator.OpenApiHeaderHelper(app_id, app_secret)
map_header = helper.gen_map()
return {
"Content-Type": "application/json",
"app-id": map_header.get("app-id"),
"time-stamp": str(map_header.get("time-stamp")),
"app-sign": map_header.get("app-sign")
}
def _get_work_log_vals(self, work_log, work_center_id, write=False):
"""
创建加加工记录
:return:
"""
vals = work_log.copy()
vals.pop("parts")
parts = work_log.get("parts", [])
part_vals = [] if not write else [(6, 0, [])]
for part in parts:
part_vals.append((0, 0, part))
vals.update({
"endState": str(work_log.get("endState")),
"part_ids": part_vals,
"work_center_id": work_center_id
})
return vals
def get_work_logs(self, start_time=None, end_time=None, time_interval=10):
"""
获取机床加工记录
:return:
"""
if not self:
records = self.search([("card_id", "!=", False)])
else:
records = self.filtered(lambda w: w.cardId)
WorkLog = self.sudo().env["roke.work.log"]
headers = self._get_request_headers()
for record in records:
work_logs = self._request_work_logs(record.card_id, headers, start_time, end_time, time_interval)
for work_log in work_logs:
workUuid = work_log.get("workUuid")
work_log_rec = WorkLog.search([("workUuid", "=", workUuid), ("work_center_id", "=", record.id)])
if work_log_rec:
work_log_rec.write(self._get_work_log_vals(work_log, record.id, write=True))
else:
WorkLog.create(self._get_work_log_vals(work_log, record.id))
time.sleep(1)
def _request_user_devices(self, headers):
"""
请求车床列表接口
:return:
"""
url = "https://mcs-gateway.fscut.com/api/user_devices"
payload = json.dumps({})
response = requests.request("POST", url, headers=headers, data=payload)
response_dict = json.loads(response.text)
result = response_dict.get("data")
return result
def _get_cardIdDevices(self, headers, cardIdDevices):
"""
单独执行时获取请求头和请求设备
:return:
"""
if not cardIdDevices:
cardIdDevices = {}
existing_devices = self.search([("card_id", "!=", False)])
for existing_device in existing_devices:
cardIdDevices[existing_device.id] = existing_device
if not headers:
headers = self._get_request_headers()
return headers, cardIdDevices
def get_devices_state(self, headers=None, cardIdDevices=None):
"""
获取设备状态
:return:
"""
headers, cardIdDevices = self._get_cardIdDevices(headers, cardIdDevices)
card_ids = list(cardIdDevices.keys())
url = "https://mcs-gateway.fscut.com/api/user_devices/current_state"
payload = json.dumps({"cardIds": card_ids})
response = requests.request("POST", url, headers=headers, data=payload)
response_dict = json.loads(response.text)
if response_dict.get("status") != 0:
_logger.error("获取设备状态异常")
_logger.error(response_dict)
return
result = response_dict.get("data")
for device_state in result:
cardId = device_state.get("cardId")
deviceState = device_state.get("deviceState")
cardIdDevices.get(cardId).write({"deviceState": deviceState})
time.sleep(1)
def get_cut_system_state(self, headers=None, cardIdDevices=None):
"""
获取机床切割系统的实时状态
:return:
"""
headers, cardIdDevices = self._get_cardIdDevices(headers, cardIdDevices)
for cardId, device in cardIdDevices.items():
url = "https://mcs-gateway.fscut.com/api/user_devices/cut_system_state"
payload = json.dumps({"cardId": cardId})
response = requests.request("POST", url, headers=headers, data=payload)
response_dict = json.loads(response.text)
if response_dict.get("status") != 0:
_logger.error("获取机床切割系统的实时状态异常")
_logger.error(response_dict)
time.sleep(1)
continue
result = response_dict.get("data")
device.write(result)
time.sleep(1)
def get_current_work(self, headers=None, cardIdDevices=None):
"""
获取机床加工中的任务
:return:
"""
headers, cardIdDevices = self._get_cardIdDevices(headers, cardIdDevices)
for cardId, device in cardIdDevices.items():
url = "https://mcs-gateway.fscut.com/api/user_devices/current_work"
payload = json.dumps({"cardId": cardId})
response = requests.request("POST", url, headers=headers, data=payload)
response_dict = json.loads(response.text)
if response_dict.get("status") != 0:
_logger.error("获取机床加工中的任务异常")
_logger.error(response_dict)
time.sleep(1)
continue
result = response_dict.get("data")
if result.get("startTime"): # 修改开始时间
result.update({
"startTime": datetime.datetime.strptime(result.get("startTime"), "%Y-%m-%d %H:%M:%S") - datetime.timedelta(hours=8)
})
device.write(result)
time.sleep(1)
def get_user_devices(self):
"""
获取车床列表
:return:
"""
headers = self._get_request_headers()
user_devices = self._request_user_devices(headers)
existing_devices = self.search([("card_id", "!=", False)])
cardIdDevices = {}
for existing_device in existing_devices:
cardIdDevices[existing_device.card_id] = existing_device
for user_device in user_devices:
cardId = user_device.get("cardId")
if cardId in cardIdDevices:
continue
new_device = self.create({
"code": cardId,
"name": user_device.get("nickname"),
"app_name": user_device.get("appName"),
"app_ver": user_device.get("appVer"),
"card_id": cardId
})
cardIdDevices[new_device.card_id] = new_device
self.flush()
_logger.info("获取机床列表完毕")
# 获取机床状态
self.get_devices_state(headers=headers, cardIdDevices=cardIdDevices)
self.flush()
_logger.info("获取机床状态完毕")
# 获取机床切割系统的实时状态
self.get_cut_system_state(headers=headers, cardIdDevices=cardIdDevices)
self.flush()
_logger.info("获取机床切割系统的实时状态完毕")
# 获取机床加工中的任务
self.get_current_work(headers=headers, cardIdDevices=cardIdDevices)
self.flush()
_logger.info("获取机床加工中的任务完毕")
def upload_task(self, task, attachment):
"""
上传任务
:return:
"""
headers = self._get_request_headers()
headers.pop("Content-Type")
url = "https://mcs-gateway.fscut.com/upload/api/device_tasks/upload/cut"
payload = {
"cardId": task.work_center_id.card_id,
"taskName": task.taskName,
"taskAmount": 1
}
binary_data = base64.b64decode(attachment.datas)
file_like_object = io.BytesIO(binary_data)
filename = attachment.name
files = [('file', (filename, file_like_object, 'application/octet-stream'))]
try:
response = requests.request("POST", url, headers=headers, data=payload, files=files)
response_dict = json.loads(response.text)
UploadMsg = response_dict.get("msg")
TaskUUID = response_dict.get("data") or ""
_logger.info(f"任务上传成功:{task.taskName}")
except Exception as e:
UploadMsg = e
TaskUUID = ""
_logger.error("上传任务失败")
_logger.error(e)
task.write({"UploadMsg": UploadMsg, "TaskUUID": TaskUUID})
# -*- coding: utf-8 -*-
"""
Description:
激光切割机加工记录
Versions:
Created by www.rokedata.com<HuChuanwei>
"""
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
import logging
_logger = logging.getLogger(__name__)
class RokeWorkLog(models.Model):
_name = "roke.work.log"
_description = "加工记录"
_order = "id desc"
_rec_name = "materialName"
work_center_id = fields.Many2one("roke.work.center", string="工作中心", index=True)
fileName = fields.Char(string="图纸文件路径")
portionId = fields.Char(string="排版唯一标识", index=True)
startTime = fields.Char(string="加工开始时间")
endTime = fields.Char(string="加工结束时间")
timeTaken = fields.Integer(string="实际切割用时")
tmEstimate = fields.Float(string="预计用时")
curveLength = fields.Float(string="切割长度")
moveLength = fields.Float(string="空移长度")
pierceCount = fields.Integer(string="穿孔数")
endState = fields.Selection([("0", "已完成"), ("-1", "正在加工"), ("1", "暂停"), ("2", "停止"), ("4", "未知")], string="加工状态")
material = fields.Char(string="材质", index=True)
materialName = fields.Char(string="工艺文件名", index=True)
portionName = fields.Char(string="排版名称", index=True)
thickness = fields.Integer(string="厚度(mm)")
plateSize = fields.Char(string="排版尺寸", index=True)
selected = fields.Boolean(string="是否为选中加工")
boundSize = fields.Char(string="图形边框尺寸")
syncTime = fields.Datetime(string="数据同步时间")
partAmount = fields.Integer(string="零件数量")
workUuid = fields.Char(string="加工记录标识", index=True)
taskUuid = fields.Char(string="任务标识")
part_ids = fields.One2many("roke.work.log.part", "log_id", string="零件信息")
@api.model
def create(self, vals):
res = super(RokeWorkLog, self).create(vals)
# file_list = res.fileName.split("\\")
# if not file_list:
# return res
# file_name = file_list[-1].split("_")
# if not file_name:
# return res
# task_code = file_name[0]
# task = self.env["roke.production.task"].sudo().search([("code", "=", task_code)])
# if not task:
# return res
# work_order = self.env["roke.work.order"].sudo().search([("process_id.name", "ilike", "切割")], limit=1)
# if not work_order:
# return res
# try:
# work_order.app_confirm(
# finish_qty=sum(res.part_ids.mapped("amount")),
# employee_id=self.env.user.employee_id.id,
# unqualified_qty=0,
# work_hours=round(res.timeTaken / 3600, 2),
# team_id=0,
# )
# except Exception as e:
# _logger.info(f"{e}")
return res
class RokeWorkLogPart(models.Model):
_name = "roke.work.log.part"
_description = "加工记录配件"
log_id = fields.Many2one("roke.work.log", string="加工记录", required=True, ondelete="cascade")
partId = fields.Char(string="零件唯一标识")
name = fields.Char(string="零件名称")
amount = fields.Integer(string="单种零件完成数")
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_roke_work_log_user,roke_work_log_user,model_roke_work_log,base.group_user,1,0,0,0
access_roke_work_log_part_user,roke_work_log_part_user,model_roke_work_log_part,base.group_user,1,0,0,0
access_roke_work_log_system,roke_work_log_system,model_roke_work_log,base.group_system,1,1,1,1
access_roke_work_log_part_system,roke_work_log_part_system,model_roke_work_log_part,base.group_system,1,1,1,1
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="inherit_view_roke_mes_purchase_receiving_form" model="ir.ui.view">
<field name="name">inherit.roke.mes.stock.picking.form</field>
<field name="model">roke.mes.stock.picking</field>
<field name="inherit_id" ref="roke_mes_purchase.view_roke_mes_purchase_receiving_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='partner_id']" position="replace">
<field name="partner_id" options="{'no_create': True}"
attrs="{'readonly':[('state', '!=', '草稿')]}"
domain="[('supplier', '=', True)]"/>
</xpath>
</field>
</record>
<record id="inherit_view_roke_mes_general_in_form" model="ir.ui.view">
<field name="name">inherit.roke.mes.stock.picking.form</field>
<field name="model">roke.mes.stock.picking</field>
<field name="inherit_id" ref="roke_mes_stock.view_roke_mes_general_in_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='partner_id']" position="replace">
<field name="partner_id" options="{'no_create': True}"
attrs="{'readonly':[('state', '!=', '草稿')]}"
domain="[('supplier', '=', True)]"/>
</xpath>
</field>
</record>
<record id="inherit_view_roke_mes_sale_deliver_form" model="ir.ui.view">
<field name="name">inherit.roke.mes.stock.picking</field>
<field name="model">roke.mes.stock.picking</field>
<field name="inherit_id" ref="roke_mes_sale.view_roke_mes_sale_deliver_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='partner_id']" position="replace">
<field name="partner_id" options="{'no_create': True}"
attrs="{'readonly':[('state', '!=', '草稿')]}"
domain="[('customer', '=', True)]"/>
</xpath>
</field>
</record>
<record id="inherit_view_roke_mes_general_out_form" model="ir.ui.view">
<field name="name">inherit.roke.mes.stock.picking</field>
<field name="model">roke.mes.stock.picking</field>
<field name="inherit_id" ref="roke_mes_stock.view_roke_mes_general_out_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='partner_id']" position="replace">
<field name="partner_id" options="{'no_create': True}"
attrs="{'readonly':[('state', '!=', '草稿')]}"
domain="[('customer', '=', True)]"/>
</xpath>
</field>
</record>
</odoo>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="jzjx_inherit_work_center_kanban_view" model="ir.ui.view">
<field name="name">jzjx.inherit.roke.work.center.kanban.view</field>
<field name="model">roke.work.center</field>
<field name="inherit_id" ref="roke_mes_production.roke_work_center_kanban_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='work_center_wo']" position="replace">
<div id="jzjx_work_center_state" class="row" style="display:flex;justify-content: center;align-items: center;font-size: 30px;">
<p style="color:#dee2e6;"><field name="deviceState"/></p>
</div>
</xpath>
<xpath expr="//div[@id='work_center_empty']" position="replace">
<div/>
</xpath>
</field>
</record>
<record id="jzjx_inherit_base_work_center_form_view" model="ir.ui.view">
<field name="name">jzjx.inherit.base.roke.work.center.form.view</field>
<field name="model">roke.work.center</field>
<field name="inherit_id" ref="roke_mes_base.view_roke_work_center_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='type_id']" position="after">
<field name="filename" readonly="1"/>
</xpath>
<xpath expr="//notebook" position="inside">
<page string="机床切割系统状态">
<group col="8">
<field name="axisX" readonly="1"/>
<field name="axisY" readonly="1"/>
<field name="axisZ" readonly="1"/>
<field name="workTimeStr" readonly="1"/>
<field name="workSpeed" readonly="1"/>
<field name="cutPercent" readonly="1"/>
<field name="laserPower" readonly="1"/>
<field name="pwmFreq" readonly="1"/>
<field name="gasType" readonly="1"/>
<field name="gasPressure" readonly="1"/>
<field name="pwmRatio" readonly="1"/>
<field name="targetHeight" readonly="1"/>
<field name="diodeCurrent" readonly="1"/>
</group>
</page>
</xpath>
</field>
</record>
<record id="jzjx_inherit_wc_work_center_form_view" model="ir.ui.view">
<field name="name">jzjx.inherit.wc.work.center.form.view</field>
<field name="model">roke.work.center</field>
<field name="inherit_id" ref="roke_mes_work_center.view_roke_production_wc_inherit_work_center_form_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='stock_location_id']" position="after">
<field name="portionId" readonly="1"/>
</xpath>
</field>
</record>
<!--TODO 模块没依赖roke_mes_workshop_inspect-->
<record id="jzjx_inherit_inspect_work_center_form_view" model="ir.ui.view">
<field name="name">jzjx.inherit.inspect.roke.work.center.form.view</field>
<field name="model">roke.work.center</field>
<field name="inherit_id" ref="roke_mes_workshop_inspect.view_roke_wi_inherit_work_center_form_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='before_inspect_scheme_id']" position="after">
<field name="startTime" readonly="1"/>
</xpath>
</field>
</record>
</odoo>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--切割机加工记录-->
<!--search-->
<record id="view_roke_work_log_search" model="ir.ui.view">
<field name="name">roke.work.log.search</field>
<field name="model">roke.work.log</field>
<field name="arch" type="xml">
<search string="切割机加工记录">
<field name="work_center_id"/>
<field name="portionId"/>
<field name="material"/>
<field name="materialName"/>
<field name="portionName"/>
<field name="plateSize"/>
<field name="workUuid"/>
<filter name="endState_0" string="已完成" domain="[('endState', '=', '0')]"/>
<filter name="endState_-1" string="正在加工" domain="[('endState', '=', '-1')]"/>
<filter name="endState_1" string="暂停" domain="[('endState', '=', '1')]"/>
<filter name="endState_2" string="停止" domain="[('endState', '=', '2')]"/>
<separator/>
<filter name="filter_startTime" date="startTime" default_period="this_month"/>
<filter name="filter_endTime" date="endTime" default_period="this_month"/>
<filter name="filter_syncTime" date="syncTime" default_period="this_month"/>
<group expand="0" string="Group By">
<filter string="材质" name="group_material" context="{'group_by': 'material'}"/>
<filter string="加工状态" name="group_endState" context="{'group_by': 'endState'}"/>
</group>
</search>
</field>
</record>
<!--tree-->
<record id="view_roke_work_log_tree" model="ir.ui.view">
<field name="name">roke.work.log.tree</field>
<field name="model">roke.work.log</field>
<field name="priority">1000</field><!--数越大优先级越小-->
<field name="arch" type="xml">
<tree string="切割机加工记录" create="false" edit="false" delete="false" duplicate="false">
<field name="work_center_id" optional="show"/>
<field name="fileName" optional="show"/>
<field name="portionId" optional="show"/>
<field name="startTime" optional="show"/>
<field name="endTime" optional="show"/>
<field name="timeTaken" optional="show"/>
<field name="endState" optional="show"/>
<field name="tmEstimate" optional="hide"/>
<field name="curveLength" optional="hide"/>
<field name="moveLength" optional="hide"/>
<field name="pierceCount" optional="hide"/>
<field name="material" optional="show"/>
<field name="materialName" optional="show"/>
<field name="portionName" optional="show"/>
<field name="thickness" optional="show"/>
<field name="plateSize" optional="hide"/>
<field name="selected" optional="hide"/>
<field name="boundSize" optional="hide"/>
<field name="syncTime" optional="hide"/>
<field name="partAmount" optional="show"/>
<field name="workUuid" optional="hide"/>
<field name="taskUuid" optional="hide"/>
</tree>
</field>
</record>
<!--form-->
<record id="view_roke_work_log_form" model="ir.ui.view">
<field name="name">roke.work.log.form</field>
<field name="model">roke.work.log</field>
<field name="arch" type="xml">
<form string="切割机加工记录" create="false" edit="false" delete="false" duplicate="false">
<header>
<field name="endState" widget="statusbar"/>
</header>
<group id="g1" col="4">
<group>
<field name="work_center_id" optional="show"/>
<field name="fileName" optional="show"/>
<field name="portionId" optional="show"/>
<field name="startTime" optional="show"/>
<field name="endTime" optional="show"/>
</group>
<group>
<field name="timeTaken" optional="show"/>
<field name="tmEstimate" optional="hide"/>
<field name="curveLength" optional="hide"/>
<field name="moveLength" optional="hide"/>
<field name="pierceCount" optional="hide"/>
</group>
<group>
<field name="material" optional="show"/>
<field name="materialName" optional="show"/>
<field name="portionName" optional="show"/>
<field name="thickness" optional="show"/>
</group>
<group>
<field name="selected" optional="hide"/>
<field name="boundSize" optional="hide"/>
<field name="syncTime" optional="hide"/>
<field name="workUuid" optional="hide"/>
</group>
</group>
<notebook>
<page string="零件信息">
<field name="part_ids">
<tree>
<field name="log_id" invisible="1"/>
<field name="partId"/>
<field name="name"/>
<field name="amount"/>
</tree>
<form>
<group>
<group>
<field name="log_id"/>
<field name="partId"/>
</group>
<group>
<field name="name"/>
<field name="amount"/>
</group>
</group>
</form>
</field>
</page>
</notebook>
</form>
</field>
</record>
<!--action-->
<record id="view_roke_work_log_action" model="ir.actions.act_window">
<field name="name">切割机加工记录</field>
<field name="res_model">roke.work.log</field>
<field name="view_mode">tree,form</field>
<field name="type">ir.actions.act_window</field>
<field name="domain">[]</field>
<field name="context">{'create': False, 'edit': False, 'delete': False}</field>
</record>
<menuitem id="roke_work_log_menu" name="切割机加工记录" parent="roke_mes_production.roke_production_report_menu"
action="view_roke_work_log_action" sequence="100"/>
</odoo>
from . import models
from . import controller
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': '生产-收入支出',
'depends': ['base', 'roke_mes_production'],
'author': 'www.rokedata.com',
'website': 'http://www.rokedata.com',
'description': """
""",
'data': [
'security/ir.model.access.csv',
'views/roke_product_income_expense.xml',
'views/template.xml',
],
'demo': [
# 'data/demo.xml',
],
'qweb':[
'static/src/xml/roke_product_income_expense_iframe.xml'
],
'application': True,
'installable': True,
'auto_install': False,
}
# -*- coding: utf-8 -*-
from . import main
import datetime
from odoo import http, tools
import os
from jinja2 import FileSystemLoader, Environment
import logging
_logger = logging.getLogger(__name__)
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
templateloader = FileSystemLoader(searchpath=BASE_DIR + "/static/src/js")
env = Environment(loader=templateloader)
class ProductIncomeExpenseIframe(http.Controller):
@http.route("/roke/pub/product_income_expense_iframe", type="http", auth='user', cors='*', csrf=False)
def product_income_expense_iframe(self, **kwargs):
_self = http.request
user_id = _self.env.user.id
user_name = _self.env.user.name
template = env.get_template('index.html')
data = {"code": 1, "message": "请求通过", "user_id": user_id, "user_name": user_name}
return template.render(data)
@http.route("/roke/product/product_income_expense/create", type="json", auth='none', cors='*', csrf=False)
def product_income_expense_create(self):
_self = http.request
data_list = _self.jsonrequest.get("data_list", [])
for v in data_list:
data = {
"business_date": v.get("business_date", False),
"abstract": v.get("abstract", False),
"income": v.get("income", False),
"expenditure": v.get("expenditure", False)
}
_self.env(user=v.get("user_id"))["roke.product.income.expense"].create(data)
return {"code": 0, "message": "创建成功!"}
@http.route("/roke/product/product_income_expense/get", type="json", auth='none', cors='*', csrf=False)
def product_income_expense_get_list(self):
_self = http.request
limit = _self.jsonrequest.get("limit", 20)
page = _self.jsonrequest.get("page", 1)
start_date = _self.jsonrequest.get("start_date", "")
end_date = _self.jsonrequest.get("end_date", "")
domain = []
if start_date and end_date:
domain.append(("business_date", ">=", start_date))
domain.append(("business_date", "<=", end_date))
data_list = _self.env["roke.product.income.expense"].sudo().search(domain, limit=limit,
offset=(page - 1) * limit,
order="business_date desc, create_date desc")
count = _self.env["roke.product.income.expense"].sudo().search_count(domain)
data = []
for v in data_list:
data.append({
"id": v.id,
"business_date": v.business_date and v.business_date.strftime('%Y-%m-%d'),
"abstract": v.abstract or "",
"income": v.income or 0,
"expenditure": v.expenditure or 0,
"balance": v.balance or 0,
"user_name": v.create_uid.name or "",
"create_date": (v.create_date + datetime.timedelta(hours=8)).strftime('%Y-%m-%d %H:%M'),
})
return {"code": 0, "message": "获取成功!", "data": data, "count": count}
@http.route("/roke/product/product_income_expense/delete", type="json", auth='none', cors='*', csrf=False)
def product_income_expense_delete(self):
_self = http.request
del_id = _self.jsonrequest.get("del_id", False)
if not del_id:
return {"code": 1, "message": "删除失败,没找到对应数据。"}
data = _self.env["roke.product.income.expense"].sudo().search([("id", "=", del_id)])
if not data:
return {"code": 1, "message": "删除失败,没找到对应数据。"}
data.unlink()
return {"code": 0, "message": "删除成功!"}
import calendar
import requests
import datetime as date_time
from datetime import datetime
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
class ProductIncomeExpense(models.Model):
_name = "roke.product.income.expense"
business_date = fields.Date(string="业务日期")
abstract = fields.Text(string="摘要")
income = fields.Float(string="收入")
expenditure = fields.Float(string="支出")
balance = fields.Float(string="结余", compute="_compute_balance")
@api.depends("income", "expenditure")
def _compute_balance(self):
data = self.search([("id", "in", self.ids)], order="business_date asc, create_date asc")
for v in data:
last_data = self.search([
"|",
"&",
("business_date", "=", v.business_date),
("create_date", "<", v.create_date),
("business_date", "<", v.business_date),
("id", "!=", v.id)
], limit=1, order="business_date desc, create_date desc")
if not last_data:
v.balance = 0 + v.income - v.expenditure
else:
v.balance = last_data.balance + v.income - v.expenditure
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_roke_product_income_expense,roke_product_income_expense,model_roke_product_income_expense,base.group_system,1,1,1,1
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>财务收支记录</title>
<!-- 引入element-ui CSS样式 -->
<link rel="stylesheet" href="/roke_product_income_expense/static/src/js/element-ui/index.css" />
<!-- 引入 vue js文件 -->
<script src="/roke_product_income_expense/static/src/js/js/vue.js"></script>
<!-- 引入 axios js文件 -->
<script src="/roke_product_income_expense/static/src/js/js/axios.min.js"></script>
<!-- moment.js 处理时间、日期 -->
<script src="/roke_product_income_expense/static/src/js/js/moment.js"></script>
<!-- 引入 element-ui js文件 -->
<script src="/roke_product_income_expense/static/src/js/element-ui/index.js"></script>
</head>
<body>
<div id="app" v-loading="loading" element-loading-text="加载中...">
<div style="margin-bottom: 20px;">
<el-table :data="createList" border :row-style="{height: '0'}"
style="width: 100%;border: 1px solid black;border-color: black" :cell-style="tableCellStyle"
:header-cell-style="tableHeaderCellStyle">
<el-table-column label="业务日期" align="center" width="166">
<template slot-scope="scope">
<el-date-picker v-model="scope.row.business_date" type="date" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" placeholder="选择日期">
</el-date-picker>
</template>
</el-table-column>
<el-table-column label="摘要" align="center">
<template slot-scope="scope">
<el-input v-model="scope.row.abstract" placeholder="请输入"></el-input>
</template>
</el-table-column>
<el-table-column label="收入" align="center" width="120">
<template slot-scope="scope">
<el-input v-model="scope.row.income" type="number" placeholder="请输入"></el-input>
</template>
</el-table-column>
<el-table-column label="支出" align="center" width="120">
<template slot-scope="scope">
<el-input v-model="scope.row.expenditure" type="number" placeholder="请输入"></el-input>
</template>
</el-table-column>
<!-- <el-table-column label="创建人" align="center" width="110">-->
<!-- <template slot-scope="scope">-->
<!-- <div>-->
<!-- [[ scope.row.user_name ]]-->
<!-- </div>-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column label="操作" align="center" width="95">
<template slot-scope="scope">
<el-button type="primary" @click="saveListData">保存</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div style="text-align: right; margin-bottom: 5px;">
<el-date-picker v-model="datePickerValue" type="daterange" range-separator="至" start-placeholder="开始日期"
end-placeholder="结束日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd"
@change="datePickerChange">
</el-date-picker>
</div>
<el-table :data="dataList" border height="500" :row-style="{height: '0'}"
style="width: 100%;border: 1px solid black;border-color: black" :cell-style="tableCellStyle"
:header-cell-style="tableHeaderCellStyle">
<el-table-column label="业务日期" align="center" width="166">
<template slot-scope="scope">
<div>
[[ scope.row.business_date ]]
</div>
</template>
</el-table-column>
<el-table-column label="摘要" align="center">
<template slot-scope="scope">
<div style="text-align: left;">
[[ scope.row.abstract ]]
</div>
</template>
</el-table-column>
<el-table-column label="收入" align="center" width="120">
<template slot-scope="scope">
<div style="text-align: right;">
[[ scope.row.income ]]
</div>
</template>
</el-table-column>
<el-table-column label="支出" align="center" width="120">
<template slot-scope="scope">
<div style="text-align: right;">
[[ scope.row.expenditure ]]
</div>
</template>
</el-table-column>
<el-table-column label="结余" align="center" width="120">
<template slot-scope="scope">
<div>
[[ scope.row.balance ]]
</div>
</template>
</el-table-column>
<el-table-column label="创建人" align="center" width="110">
<template slot-scope="scope">
<div>
[[ scope.row.user_name ]]
</div>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" width="160">
<template slot-scope="scope">
<div>
[[ scope.row.create_date ]]
</div>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="80">
<template slot-scope="scope">
<el-button type="danger" icon="el-icon-delete" circle @click="deleteItem(scope)"></el-button>
</template>
</el-table-column>
</el-table>
<div style="margin-top: 10px; text-align: center;">
<el-pagination :current-page="currentPageNo" :total="paginationTotal" @current-change="handleCurrentChangee"
:page-size="10" layout="prev, pager, next,total">
</el-pagination>
</div>
</div>
</body>
<script>
new Vue({
el: "#app",
delimiters: ["[[", "]]"], // 替换原本vue的{{ key }}取值方式(与odoo使用的jinja2冲突问题)
data() {
return {
TableHeight: 0,
currentPageNo: 1,
paginationTotal: 10,
loading: false,
dataList: [],
user_name: '',
user_id: null,
createList: [
{
business_date: '',
abstract: '',
income: '',
expenditure: '',
user_name: '',
user_id: null,
}
],
datePickerValue: ['', '']
};
},
created() {
this.user_name = this.getUrlSearch('user_name') //截取url后面的参数
this.user_id = this.getUrlSearch('user_id')
this.createList[0].user_name = this.user_name
this.createList[0].business_date = moment().format("YYYY-MM-DD")
this.createList[0].user_id = this.user_id
this.TableHeight = window.innerHeight;
this.getDataList()
},
methods: {
// 列表 时间过滤
datePickerChange(e) {
console.log(e);
if (!e) {
this.datePickerValue = ['', '']
}
this.getDataList()
},
// 分页请求数据
handleCurrentChangee(val) {
this.currentPageNo = val;
this.getDataList()
},
// 获取列表数据
getDataList() {
this.loading = true;
let parameter = {
limit: 10, //每页数量 非必填
page: this.currentPageNo, //当前页码
start_date: this.datePickerValue[0],
end_date: this.datePickerValue[1]
}
axios.request({
url: "/roke/product/product_income_expense/get",
method: "post",
headers: {
"Content-Type": "application/json",
},
data: parameter,
}).then((res) => {
if (res.data.result.code === 0) {
this.paginationTotal = res.data.result.count
this.dataList = res.data.result.data
} else {
this.$message({
type: "error",
message: res.data.result.message || "获取失败请稍后重试",
});
}
this.loading = false;
});
},
// 删除
deleteItem(item, index) {
if (item.row.id) {
this.loading = true;
axios.request({
url: "/roke/product/product_income_expense/delete",
method: "post",
headers: {
"Content-Type": "application/json",
},
data: {
del_id: item.row.id
}
}).then((res) => {
if (res.data.result.code === 0) {
this.$message({
type: "success",
message: res.data.result.message || "删除成功",
});
this.getDataList()
} else {
this.$message({
type: "error",
message: res.data.result.message || "删除失败",
});
}
this.loading = false;
});
} else {
this.dataList.splice(item.$index, 1)
}
},
// 保存
saveListData() {
if (this.createList[0].income != '' || this.createList[0].expenditure != '') {
this.loading = true;
axios.request({
url: "/roke/product/product_income_expense/create",
method: "post",
headers: {
"Content-Type": "application/json",
},
data: {
data_list: this.createList
}
}).then((res) => {
if (res.data.result.code === 0) {
this.$message({
type: "success",
message: res.data.result.message || "创建成功",
});
this.currentPageNo = 1
this.createList = [
{
business_date: moment().format("YYYY-MM-DD"),
abstract: '',
income: '',
expenditure: '',
user_name: this.user_name,
user_id: this.user_id
}
]
this.getDataList()
} else {
this.$message({
type: "error",
message: res.data.result.message || "创建失败",
});
}
this.loading = false;
});
} else {
this.$message({
type: "warning",
message: "请填写收入或支出后保存",
});
}
},
// table样式
tableCellStyle() {
return "border-color:black;"
},
// 修改 table header cell的背景色
tableHeaderCellStyle() {
return 'background: #eef1f6;border-color: black;color:black'
},
// 通过网址跳转过来的页面,截取后面的参数
getUrlSearch(name) {
// 未传参,返回空
if (!name) return '';
// 查询参数:先通过search取值,如果取不到就通过hash来取
var after = window.location.search;
after = after.substr(1) || window.location.hash.split('?')[1];
// 地址栏URL没有查询参数,返回空
if (!after) return null;
// 如果查询参数中没有"name",返回空
if (after.indexOf(name) === -1) return null;
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
// 当地址栏参数存在中文时,需要解码,不然会乱码
var r = decodeURI(after).match(reg);
// 如果url中"name"没有值,返回空
if (!r) return null;
return r[2];
},
},
});
</script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
padding: 15px 35px 30px 35px;
}
.el-table .el-table__cell {
padding: 3px 0;
}
.el-date-editor.el-input {
width: 140px;
}
</style>
</html>
\ No newline at end of file
!(function (e, t) {
"object" == typeof exports && "undefined" != typeof module
? (module.exports = t())
: "function" == typeof define && define.amd
? define(t)
: ((e = "undefined" != typeof globalThis ? globalThis : e || self).axios =
t());
})(this, function () {
"use strict";
function e(t) {
return (
(e =
"function" == typeof Symbol && "symbol" == typeof Symbol.iterator
? function (e) {
return typeof e;
}
: function (e) {
return e &&
"function" == typeof Symbol &&
e.constructor === Symbol &&
e !== Symbol.prototype
? "symbol"
: typeof e;
}),
e(t)
);
}
function t(e, t) {
if (!(e instanceof t))
throw new TypeError("Cannot call a class as a function");
}
function n(e, t) {
for (var n = 0; n < t.length; n++) {
var r = t[n];
(r.enumerable = r.enumerable || !1),
(r.configurable = !0),
"value" in r && (r.writable = !0),
Object.defineProperty(e, r.key, r);
}
}
function r(e, t, r) {
return (
t && n(e.prototype, t),
r && n(e, r),
Object.defineProperty(e, "prototype", { writable: !1 }),
e
);
}
function o(e, t) {
return (
(function (e) {
if (Array.isArray(e)) return e;
})(e) ||
(function (e, t) {
var n =
null == e
? null
: ("undefined" != typeof Symbol && e[Symbol.iterator]) ||
e["@@iterator"];
if (null == n) return;
var r,
o,
i = [],
a = !0,
s = !1;
try {
for (
n = n.call(e);
!(a = (r = n.next()).done) &&
(i.push(r.value), !t || i.length !== t);
a = !0
);
} catch (e) {
(s = !0), (o = e);
} finally {
try {
a || null == n.return || n.return();
} finally {
if (s) throw o;
}
}
return i;
})(e, t) ||
(function (e, t) {
if (!e) return;
if ("string" == typeof e) return i(e, t);
var n = Object.prototype.toString.call(e).slice(8, -1);
"Object" === n && e.constructor && (n = e.constructor.name);
if ("Map" === n || "Set" === n) return Array.from(e);
if (
"Arguments" === n ||
/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)
)
return i(e, t);
})(e, t) ||
(function () {
throw new TypeError(
"Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
);
})()
);
}
function i(e, t) {
(null == t || t > e.length) && (t = e.length);
for (var n = 0, r = new Array(t); n < t; n++) r[n] = e[n];
return r;
}
function a(e, t) {
return function () {
return e.apply(t, arguments);
};
}
var s,
u = Object.prototype.toString,
c = Object.getPrototypeOf,
f =
((s = Object.create(null)),
function (e) {
var t = u.call(e);
return s[t] || (s[t] = t.slice(8, -1).toLowerCase());
}),
l = function (e) {
return (
(e = e.toLowerCase()),
function (t) {
return f(t) === e;
}
);
},
d = function (t) {
return function (n) {
return e(n) === t;
};
},
p = Array.isArray,
h = d("undefined");
var m = l("ArrayBuffer");
var y = d("string"),
v = d("function"),
b = d("number"),
g = function (t) {
return null !== t && "object" === e(t);
},
w = function (e) {
if ("object" !== f(e)) return !1;
var t = c(e);
return !(
(null !== t &&
t !== Object.prototype &&
null !== Object.getPrototypeOf(t)) ||
Symbol.toStringTag in e ||
Symbol.iterator in e
);
},
E = l("Date"),
O = l("File"),
S = l("Blob"),
R = l("FileList"),
A = l("URLSearchParams");
function T(t, n) {
var r,
o,
i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {},
a = i.allOwnKeys,
s = void 0 !== a && a;
if (null != t)
if (("object" !== e(t) && (t = [t]), p(t)))
for (r = 0, o = t.length; r < o; r++) n.call(null, t[r], r, t);
else {
var u,
c = s ? Object.getOwnPropertyNames(t) : Object.keys(t),
f = c.length;
for (r = 0; r < f; r++) (u = c[r]), n.call(null, t[u], u, t);
}
}
function j(e, t) {
t = t.toLowerCase();
for (var n, r = Object.keys(e), o = r.length; o-- > 0; )
if (t === (n = r[o]).toLowerCase()) return n;
return null;
}
var N =
"undefined" != typeof globalThis
? globalThis
: "undefined" != typeof self
? self
: "undefined" != typeof window
? window
: global,
C = function (e) {
return !h(e) && e !== N;
};
var x,
P =
((x = "undefined" != typeof Uint8Array && c(Uint8Array)),
function (e) {
return x && e instanceof x;
}),
k = l("HTMLFormElement"),
U = (function (e) {
var t = Object.prototype.hasOwnProperty;
return function (e, n) {
return t.call(e, n);
};
})(),
_ = l("RegExp"),
F = function (e, t) {
var n = Object.getOwnPropertyDescriptors(e),
r = {};
T(n, function (n, o) {
!1 !== t(n, o, e) && (r[o] = n);
}),
Object.defineProperties(e, r);
},
B = "abcdefghijklmnopqrstuvwxyz",
L = "0123456789",
D = { DIGIT: L, ALPHA: B, ALPHA_DIGIT: B + B.toUpperCase() + L };
var I = l("AsyncFunction"),
q = {
isArray: p,
isArrayBuffer: m,
isBuffer: function (e) {
return (
null !== e &&
!h(e) &&
null !== e.constructor &&
!h(e.constructor) &&
v(e.constructor.isBuffer) &&
e.constructor.isBuffer(e)
);
},
isFormData: function (e) {
var t;
return (
e &&
(("function" == typeof FormData && e instanceof FormData) ||
(v(e.append) &&
("formdata" === (t = f(e)) ||
("object" === t &&
v(e.toString) &&
"[object FormData]" === e.toString()))))
);
},
isArrayBufferView: function (e) {
return "undefined" != typeof ArrayBuffer && ArrayBuffer.isView
? ArrayBuffer.isView(e)
: e && e.buffer && m(e.buffer);
},
isString: y,
isNumber: b,
isBoolean: function (e) {
return !0 === e || !1 === e;
},
isObject: g,
isPlainObject: w,
isUndefined: h,
isDate: E,
isFile: O,
isBlob: S,
isRegExp: _,
isFunction: v,
isStream: function (e) {
return g(e) && v(e.pipe);
},
isURLSearchParams: A,
isTypedArray: P,
isFileList: R,
forEach: T,
merge: function e() {
for (
var t = (C(this) && this) || {},
n = t.caseless,
r = {},
o = function (t, o) {
var i = (n && j(r, o)) || o;
w(r[i]) && w(t)
? (r[i] = e(r[i], t))
: w(t)
? (r[i] = e({}, t))
: p(t)
? (r[i] = t.slice())
: (r[i] = t);
},
i = 0,
a = arguments.length;
i < a;
i++
)
arguments[i] && T(arguments[i], o);
return r;
},
extend: function (e, t, n) {
var r =
arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : {},
o = r.allOwnKeys;
return (
T(
t,
function (t, r) {
n && v(t) ? (e[r] = a(t, n)) : (e[r] = t);
},
{ allOwnKeys: o }
),
e
);
},
trim: function (e) {
return e.trim
? e.trim()
: e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "");
},
stripBOM: function (e) {
return 65279 === e.charCodeAt(0) && (e = e.slice(1)), e;
},
inherits: function (e, t, n, r) {
(e.prototype = Object.create(t.prototype, r)),
(e.prototype.constructor = e),
Object.defineProperty(e, "super", { value: t.prototype }),
n && Object.assign(e.prototype, n);
},
toFlatObject: function (e, t, n, r) {
var o,
i,
a,
s = {};
if (((t = t || {}), null == e)) return t;
do {
for (i = (o = Object.getOwnPropertyNames(e)).length; i-- > 0; )
(a = o[i]),
(r && !r(a, e, t)) || s[a] || ((t[a] = e[a]), (s[a] = !0));
e = !1 !== n && c(e);
} while (e && (!n || n(e, t)) && e !== Object.prototype);
return t;
},
kindOf: f,
kindOfTest: l,
endsWith: function (e, t, n) {
(e = String(e)),
(void 0 === n || n > e.length) && (n = e.length),
(n -= t.length);
var r = e.indexOf(t, n);
return -1 !== r && r === n;
},
toArray: function (e) {
if (!e) return null;
if (p(e)) return e;
var t = e.length;
if (!b(t)) return null;
for (var n = new Array(t); t-- > 0; ) n[t] = e[t];
return n;
},
forEachEntry: function (e, t) {
for (
var n, r = (e && e[Symbol.iterator]).call(e);
(n = r.next()) && !n.done;
) {
var o = n.value;
t.call(e, o[0], o[1]);
}
},
matchAll: function (e, t) {
for (var n, r = []; null !== (n = e.exec(t)); ) r.push(n);
return r;
},
isHTMLForm: k,
hasOwnProperty: U,
hasOwnProp: U,
reduceDescriptors: F,
freezeMethods: function (e) {
F(e, function (t, n) {
if (v(e) && -1 !== ["arguments", "caller", "callee"].indexOf(n))
return !1;
var r = e[n];
v(r) &&
((t.enumerable = !1),
"writable" in t
? (t.writable = !1)
: t.set ||
(t.set = function () {
throw Error("Can not rewrite read-only method '" + n + "'");
}));
});
},
toObjectSet: function (e, t) {
var n = {},
r = function (e) {
e.forEach(function (e) {
n[e] = !0;
});
};
return p(e) ? r(e) : r(String(e).split(t)), n;
},
toCamelCase: function (e) {
return e
.toLowerCase()
.replace(/[-_\s]([a-z\d])(\w*)/g, function (e, t, n) {
return t.toUpperCase() + n;
});
},
noop: function () {},
toFiniteNumber: function (e, t) {
return (e = +e), Number.isFinite(e) ? e : t;
},
findKey: j,
global: N,
isContextDefined: C,
ALPHABET: D,
generateString: function () {
for (
var e =
arguments.length > 0 && void 0 !== arguments[0]
? arguments[0]
: 16,
t =
arguments.length > 1 && void 0 !== arguments[1]
? arguments[1]
: D.ALPHA_DIGIT,
n = "",
r = t.length;
e--;
)
n += t[(Math.random() * r) | 0];
return n;
},
isSpecCompliantForm: function (e) {
return !!(
e &&
v(e.append) &&
"FormData" === e[Symbol.toStringTag] &&
e[Symbol.iterator]
);
},
toJSONObject: function (e) {
var t = new Array(10);
return (function e(n, r) {
if (g(n)) {
if (t.indexOf(n) >= 0) return;
if (!("toJSON" in n)) {
t[r] = n;
var o = p(n) ? [] : {};
return (
T(n, function (t, n) {
var i = e(t, r + 1);
!h(i) && (o[n] = i);
}),
(t[r] = void 0),
o
);
}
}
return n;
})(e, 0);
},
isAsyncFn: I,
isThenable: function (e) {
return e && (g(e) || v(e)) && v(e.then) && v(e.catch);
},
};
function M(e, t, n, r, o) {
Error.call(this),
Error.captureStackTrace
? Error.captureStackTrace(this, this.constructor)
: (this.stack = new Error().stack),
(this.message = e),
(this.name = "AxiosError"),
t && (this.code = t),
n && (this.config = n),
r && (this.request = r),
o && (this.response = o);
}
q.inherits(M, Error, {
toJSON: function () {
return {
message: this.message,
name: this.name,
description: this.description,
number: this.number,
fileName: this.fileName,
lineNumber: this.lineNumber,
columnNumber: this.columnNumber,
stack: this.stack,
config: q.toJSONObject(this.config),
code: this.code,
status:
this.response && this.response.status ? this.response.status : null,
};
},
});
var z = M.prototype,
H = {};
[
"ERR_BAD_OPTION_VALUE",
"ERR_BAD_OPTION",
"ECONNABORTED",
"ETIMEDOUT",
"ERR_NETWORK",
"ERR_FR_TOO_MANY_REDIRECTS",
"ERR_DEPRECATED",
"ERR_BAD_RESPONSE",
"ERR_BAD_REQUEST",
"ERR_CANCELED",
"ERR_NOT_SUPPORT",
"ERR_INVALID_URL",
].forEach(function (e) {
H[e] = { value: e };
}),
Object.defineProperties(M, H),
Object.defineProperty(z, "isAxiosError", { value: !0 }),
(M.from = function (e, t, n, r, o, i) {
var a = Object.create(z);
return (
q.toFlatObject(
e,
a,
function (e) {
return e !== Error.prototype;
},
function (e) {
return "isAxiosError" !== e;
}
),
M.call(a, e.message, t, n, r, o),
(a.cause = e),
(a.name = e.name),
i && Object.assign(a, i),
a
);
});
function J(e) {
return q.isPlainObject(e) || q.isArray(e);
}
function W(e) {
return q.endsWith(e, "[]") ? e.slice(0, -2) : e;
}
function K(e, t, n) {
return e
? e
.concat(t)
.map(function (e, t) {
return (e = W(e)), !n && t ? "[" + e + "]" : e;
})
.join(n ? "." : "")
: t;
}
var V = q.toFlatObject(q, {}, null, function (e) {
return /^is[A-Z]/.test(e);
});
function G(t, n, r) {
if (!q.isObject(t)) throw new TypeError("target must be an object");
n = n || new FormData();
var o = (r = q.toFlatObject(
r,
{ metaTokens: !0, dots: !1, indexes: !1 },
!1,
function (e, t) {
return !q.isUndefined(t[e]);
}
)).metaTokens,
i = r.visitor || f,
a = r.dots,
s = r.indexes,
u =
(r.Blob || ("undefined" != typeof Blob && Blob)) &&
q.isSpecCompliantForm(n);
if (!q.isFunction(i)) throw new TypeError("visitor must be a function");
function c(e) {
if (null === e) return "";
if (q.isDate(e)) return e.toISOString();
if (!u && q.isBlob(e))
throw new M("Blob is not supported. Use a Buffer instead.");
return q.isArrayBuffer(e) || q.isTypedArray(e)
? u && "function" == typeof Blob
? new Blob([e])
: Buffer.from(e)
: e;
}
function f(t, r, i) {
var u = t;
if (t && !i && "object" === e(t))
if (q.endsWith(r, "{}"))
(r = o ? r : r.slice(0, -2)), (t = JSON.stringify(t));
else if (
(q.isArray(t) &&
(function (e) {
return q.isArray(e) && !e.some(J);
})(t)) ||
((q.isFileList(t) || q.endsWith(r, "[]")) && (u = q.toArray(t)))
)
return (
(r = W(r)),
u.forEach(function (e, t) {
!q.isUndefined(e) &&
null !== e &&
n.append(
!0 === s ? K([r], t, a) : null === s ? r : r + "[]",
c(e)
);
}),
!1
);
return !!J(t) || (n.append(K(i, r, a), c(t)), !1);
}
var l = [],
d = Object.assign(V, {
defaultVisitor: f,
convertValue: c,
isVisitable: J,
});
if (!q.isObject(t)) throw new TypeError("data must be an object");
return (
(function e(t, r) {
if (!q.isUndefined(t)) {
if (-1 !== l.indexOf(t))
throw Error("Circular reference detected in " + r.join("."));
l.push(t),
q.forEach(t, function (t, o) {
!0 ===
(!(q.isUndefined(t) || null === t) &&
i.call(n, t, q.isString(o) ? o.trim() : o, r, d)) &&
e(t, r ? r.concat(o) : [o]);
}),
l.pop();
}
})(t),
n
);
}
function $(e) {
var t = {
"!": "%21",
"'": "%27",
"(": "%28",
")": "%29",
"~": "%7E",
"%20": "+",
"%00": "\0",
};
return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g, function (e) {
return t[e];
});
}
function X(e, t) {
(this._pairs = []), e && G(e, this, t);
}
var Q = X.prototype;
function Z(e) {
return encodeURIComponent(e)
.replace(/%3A/gi, ":")
.replace(/%24/g, "$")
.replace(/%2C/gi, ",")
.replace(/%20/g, "+")
.replace(/%5B/gi, "[")
.replace(/%5D/gi, "]");
}
function Y(e, t, n) {
if (!t) return e;
var r,
o = (n && n.encode) || Z,
i = n && n.serialize;
if (
(r = i
? i(t, n)
: q.isURLSearchParams(t)
? t.toString()
: new X(t, n).toString(o))
) {
var a = e.indexOf("#");
-1 !== a && (e = e.slice(0, a)),
(e += (-1 === e.indexOf("?") ? "?" : "&") + r);
}
return e;
}
(Q.append = function (e, t) {
this._pairs.push([e, t]);
}),
(Q.toString = function (e) {
var t = e
? function (t) {
return e.call(this, t, $);
}
: $;
return this._pairs
.map(function (e) {
return t(e[0]) + "=" + t(e[1]);
}, "")
.join("&");
});
var ee,
te = (function () {
function e() {
t(this, e), (this.handlers = []);
}
return (
r(e, [
{
key: "use",
value: function (e, t, n) {
return (
this.handlers.push({
fulfilled: e,
rejected: t,
synchronous: !!n && n.synchronous,
runWhen: n ? n.runWhen : null,
}),
this.handlers.length - 1
);
},
},
{
key: "eject",
value: function (e) {
this.handlers[e] && (this.handlers[e] = null);
},
},
{
key: "clear",
value: function () {
this.handlers && (this.handlers = []);
},
},
{
key: "forEach",
value: function (e) {
q.forEach(this.handlers, function (t) {
null !== t && e(t);
});
},
},
]),
e
);
})(),
ne = {
silentJSONParsing: !0,
forcedJSONParsing: !0,
clarifyTimeoutError: !1,
},
re = {
isBrowser: !0,
classes: {
URLSearchParams:
"undefined" != typeof URLSearchParams ? URLSearchParams : X,
FormData: "undefined" != typeof FormData ? FormData : null,
Blob: "undefined" != typeof Blob ? Blob : null,
},
isStandardBrowserEnv:
("undefined" == typeof navigator ||
("ReactNative" !== (ee = navigator.product) &&
"NativeScript" !== ee &&
"NS" !== ee)) &&
"undefined" != typeof window &&
"undefined" != typeof document,
isStandardBrowserWebWorkerEnv:
"undefined" != typeof WorkerGlobalScope &&
self instanceof WorkerGlobalScope &&
"function" == typeof self.importScripts,
protocols: ["http", "https", "file", "blob", "url", "data"],
};
function oe(e) {
function t(e, n, r, o) {
var i = e[o++],
a = Number.isFinite(+i),
s = o >= e.length;
return (
(i = !i && q.isArray(r) ? r.length : i),
s
? (q.hasOwnProp(r, i) ? (r[i] = [r[i], n]) : (r[i] = n), !a)
: ((r[i] && q.isObject(r[i])) || (r[i] = []),
t(e, n, r[i], o) &&
q.isArray(r[i]) &&
(r[i] = (function (e) {
var t,
n,
r = {},
o = Object.keys(e),
i = o.length;
for (t = 0; t < i; t++) r[(n = o[t])] = e[n];
return r;
})(r[i])),
!a)
);
}
if (q.isFormData(e) && q.isFunction(e.entries)) {
var n = {};
return (
q.forEachEntry(e, function (e, r) {
t(
(function (e) {
return q.matchAll(/\w+|\[(\w*)]/g, e).map(function (e) {
return "[]" === e[0] ? "" : e[1] || e[0];
});
})(e),
r,
n,
0
);
}),
n
);
}
return null;
}
var ie = { "Content-Type": void 0 };
var ae = {
transitional: ne,
adapter: ["xhr", "http"],
transformRequest: [
function (e, t) {
var n,
r = t.getContentType() || "",
o = r.indexOf("application/json") > -1,
i = q.isObject(e);
if ((i && q.isHTMLForm(e) && (e = new FormData(e)), q.isFormData(e)))
return o && o ? JSON.stringify(oe(e)) : e;
if (
q.isArrayBuffer(e) ||
q.isBuffer(e) ||
q.isStream(e) ||
q.isFile(e) ||
q.isBlob(e)
)
return e;
if (q.isArrayBufferView(e)) return e.buffer;
if (q.isURLSearchParams(e))
return (
t.setContentType(
"application/x-www-form-urlencoded;charset=utf-8",
!1
),
e.toString()
);
if (i) {
if (r.indexOf("application/x-www-form-urlencoded") > -1)
return (function (e, t) {
return G(
e,
new re.classes.URLSearchParams(),
Object.assign(
{
visitor: function (e, t, n, r) {
return re.isNode && q.isBuffer(e)
? (this.append(t, e.toString("base64")), !1)
: r.defaultVisitor.apply(this, arguments);
},
},
t
)
);
})(e, this.formSerializer).toString();
if ((n = q.isFileList(e)) || r.indexOf("multipart/form-data") > -1) {
var a = this.env && this.env.FormData;
return G(
n ? { "files[]": e } : e,
a && new a(),
this.formSerializer
);
}
}
return i || o
? (t.setContentType("application/json", !1),
(function (e, t, n) {
if (q.isString(e))
try {
return (t || JSON.parse)(e), q.trim(e);
} catch (e) {
if ("SyntaxError" !== e.name) throw e;
}
return (n || JSON.stringify)(e);
})(e))
: e;
},
],
transformResponse: [
function (e) {
var t = this.transitional || ae.transitional,
n = t && t.forcedJSONParsing,
r = "json" === this.responseType;
if (e && q.isString(e) && ((n && !this.responseType) || r)) {
var o = !(t && t.silentJSONParsing) && r;
try {
return JSON.parse(e);
} catch (e) {
if (o) {
if ("SyntaxError" === e.name)
throw M.from(e, M.ERR_BAD_RESPONSE, this, null, this.response);
throw e;
}
}
}
return e;
},
],
timeout: 0,
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",
maxContentLength: -1,
maxBodyLength: -1,
env: { FormData: re.classes.FormData, Blob: re.classes.Blob },
validateStatus: function (e) {
return e >= 200 && e < 300;
},
headers: { common: { Accept: "application/json, text/plain, */*" } },
};
q.forEach(["delete", "get", "head"], function (e) {
ae.headers[e] = {};
}),
q.forEach(["post", "put", "patch"], function (e) {
ae.headers[e] = q.merge(ie);
});
var se = ae,
ue = q.toObjectSet([
"age",
"authorization",
"content-length",
"content-type",
"etag",
"expires",
"from",
"host",
"if-modified-since",
"if-unmodified-since",
"last-modified",
"location",
"max-forwards",
"proxy-authorization",
"referer",
"retry-after",
"user-agent",
]),
ce = Symbol("internals");
function fe(e) {
return e && String(e).trim().toLowerCase();
}
function le(e) {
return !1 === e || null == e ? e : q.isArray(e) ? e.map(le) : String(e);
}
function de(e, t, n, r, o) {
return q.isFunction(r)
? r.call(this, t, n)
: (o && (t = n),
q.isString(t)
? q.isString(r)
? -1 !== t.indexOf(r)
: q.isRegExp(r)
? r.test(t)
: void 0
: void 0);
}
var pe = (function (e, n) {
function i(e) {
t(this, i), e && this.set(e);
}
return (
r(
i,
[
{
key: "set",
value: function (e, t, n) {
var r = this;
function o(e, t, n) {
var o = fe(t);
if (!o)
throw new Error("header name must be a non-empty string");
var i = q.findKey(r, o);
(!i ||
void 0 === r[i] ||
!0 === n ||
(void 0 === n && !1 !== r[i])) &&
(r[i || t] = le(e));
}
var i,
a,
s,
u,
c,
f = function (e, t) {
return q.forEach(e, function (e, n) {
return o(e, n, t);
});
};
return (
q.isPlainObject(e) || e instanceof this.constructor
? f(e, t)
: q.isString(e) &&
(e = e.trim()) &&
!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim())
? f(
((c = {}),
(i = e) &&
i.split("\n").forEach(function (e) {
(u = e.indexOf(":")),
(a = e.substring(0, u).trim().toLowerCase()),
(s = e.substring(u + 1).trim()),
!a ||
(c[a] && ue[a]) ||
("set-cookie" === a
? c[a]
? c[a].push(s)
: (c[a] = [s])
: (c[a] = c[a] ? c[a] + ", " + s : s));
}),
c),
t
)
: null != e && o(t, e, n),
this
);
},
},
{
key: "get",
value: function (e, t) {
if ((e = fe(e))) {
var n = q.findKey(this, e);
if (n) {
var r = this[n];
if (!t) return r;
if (!0 === t)
return (function (e) {
for (
var t,
n = Object.create(null),
r = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;
(t = r.exec(e));
)
n[t[1]] = t[2];
return n;
})(r);
if (q.isFunction(t)) return t.call(this, r, n);
if (q.isRegExp(t)) return t.exec(r);
throw new TypeError("parser must be boolean|regexp|function");
}
}
},
},
{
key: "has",
value: function (e, t) {
if ((e = fe(e))) {
var n = q.findKey(this, e);
return !(
!n ||
void 0 === this[n] ||
(t && !de(0, this[n], n, t))
);
}
return !1;
},
},
{
key: "delete",
value: function (e, t) {
var n = this,
r = !1;
function o(e) {
if ((e = fe(e))) {
var o = q.findKey(n, e);
!o || (t && !de(0, n[o], o, t)) || (delete n[o], (r = !0));
}
}
return q.isArray(e) ? e.forEach(o) : o(e), r;
},
},
{
key: "clear",
value: function (e) {
for (var t = Object.keys(this), n = t.length, r = !1; n--; ) {
var o = t[n];
(e && !de(0, this[o], o, e, !0)) || (delete this[o], (r = !0));
}
return r;
},
},
{
key: "normalize",
value: function (e) {
var t = this,
n = {};
return (
q.forEach(this, function (r, o) {
var i = q.findKey(n, o);
if (i) return (t[i] = le(r)), void delete t[o];
var a = e
? (function (e) {
return e
.trim()
.toLowerCase()
.replace(/([a-z\d])(\w*)/g, function (e, t, n) {
return t.toUpperCase() + n;
});
})(o)
: String(o).trim();
a !== o && delete t[o], (t[a] = le(r)), (n[a] = !0);
}),
this
);
},
},
{
key: "concat",
value: function () {
for (
var e, t = arguments.length, n = new Array(t), r = 0;
r < t;
r++
)
n[r] = arguments[r];
return (e = this.constructor).concat.apply(e, [this].concat(n));
},
},
{
key: "toJSON",
value: function (e) {
var t = Object.create(null);
return (
q.forEach(this, function (n, r) {
null != n &&
!1 !== n &&
(t[r] = e && q.isArray(n) ? n.join(", ") : n);
}),
t
);
},
},
{
key: Symbol.iterator,
value: function () {
return Object.entries(this.toJSON())[Symbol.iterator]();
},
},
{
key: "toString",
value: function () {
return Object.entries(this.toJSON())
.map(function (e) {
var t = o(e, 2);
return t[0] + ": " + t[1];
})
.join("\n");
},
},
{
key: Symbol.toStringTag,
get: function () {
return "AxiosHeaders";
},
},
],
[
{
key: "from",
value: function (e) {
return e instanceof this ? e : new this(e);
},
},
{
key: "concat",
value: function (e) {
for (
var t = new this(e),
n = arguments.length,
r = new Array(n > 1 ? n - 1 : 0),
o = 1;
o < n;
o++
)
r[o - 1] = arguments[o];
return (
r.forEach(function (e) {
return t.set(e);
}),
t
);
},
},
{
key: "accessor",
value: function (e) {
var t = (this[ce] = this[ce] = { accessors: {} }).accessors,
n = this.prototype;
function r(e) {
var r = fe(e);
t[r] ||
(!(function (e, t) {
var n = q.toCamelCase(" " + t);
["get", "set", "has"].forEach(function (r) {
Object.defineProperty(e, r + n, {
value: function (e, n, o) {
return this[r].call(this, t, e, n, o);
},
configurable: !0,
});
});
})(n, e),
(t[r] = !0));
}
return q.isArray(e) ? e.forEach(r) : r(e), this;
},
},
]
),
i
);
})();
pe.accessor([
"Content-Type",
"Content-Length",
"Accept",
"Accept-Encoding",
"User-Agent",
"Authorization",
]),
q.freezeMethods(pe.prototype),
q.freezeMethods(pe);
var he = pe;
function me(e, t) {
var n = this || se,
r = t || n,
o = he.from(r.headers),
i = r.data;
return (
q.forEach(e, function (e) {
i = e.call(n, i, o.normalize(), t ? t.status : void 0);
}),
o.normalize(),
i
);
}
function ye(e) {
return !(!e || !e.__CANCEL__);
}
function ve(e, t, n) {
M.call(this, null == e ? "canceled" : e, M.ERR_CANCELED, t, n),
(this.name = "CanceledError");
}
q.inherits(ve, M, { __CANCEL__: !0 });
var be = re.isStandardBrowserEnv
? {
write: function (e, t, n, r, o, i) {
var a = [];
a.push(e + "=" + encodeURIComponent(t)),
q.isNumber(n) && a.push("expires=" + new Date(n).toGMTString()),
q.isString(r) && a.push("path=" + r),
q.isString(o) && a.push("domain=" + o),
!0 === i && a.push("secure"),
(document.cookie = a.join("; "));
},
read: function (e) {
var t = document.cookie.match(
new RegExp("(^|;\\s*)(" + e + ")=([^;]*)")
);
return t ? decodeURIComponent(t[3]) : null;
},
remove: function (e) {
this.write(e, "", Date.now() - 864e5);
},
}
: {
write: function () {},
read: function () {
return null;
},
remove: function () {},
};
function ge(e, t) {
return e && !/^([a-z][a-z\d+\-.]*:)?\/\//i.test(t)
? (function (e, t) {
return t ? e.replace(/\/+$/, "") + "/" + t.replace(/^\/+/, "") : e;
})(e, t)
: t;
}
var we = re.isStandardBrowserEnv
? (function () {
var e,
t = /(msie|trident)/i.test(navigator.userAgent),
n = document.createElement("a");
function r(e) {
var r = e;
return (
t && (n.setAttribute("href", r), (r = n.href)),
n.setAttribute("href", r),
{
href: n.href,
protocol: n.protocol ? n.protocol.replace(/:$/, "") : "",
host: n.host,
search: n.search ? n.search.replace(/^\?/, "") : "",
hash: n.hash ? n.hash.replace(/^#/, "") : "",
hostname: n.hostname,
port: n.port,
pathname:
"/" === n.pathname.charAt(0) ? n.pathname : "/" + n.pathname,
}
);
}
return (
(e = r(window.location.href)),
function (t) {
var n = q.isString(t) ? r(t) : t;
return n.protocol === e.protocol && n.host === e.host;
}
);
})()
: function () {
return !0;
};
function Ee(e, t) {
var n = 0,
r = (function (e, t) {
e = e || 10;
var n,
r = new Array(e),
o = new Array(e),
i = 0,
a = 0;
return (
(t = void 0 !== t ? t : 1e3),
function (s) {
var u = Date.now(),
c = o[a];
n || (n = u), (r[i] = s), (o[i] = u);
for (var f = a, l = 0; f !== i; ) (l += r[f++]), (f %= e);
if (((i = (i + 1) % e) === a && (a = (a + 1) % e), !(u - n < t))) {
var d = c && u - c;
return d ? Math.round((1e3 * l) / d) : void 0;
}
}
);
})(50, 250);
return function (o) {
var i = o.loaded,
a = o.lengthComputable ? o.total : void 0,
s = i - n,
u = r(s);
n = i;
var c = {
loaded: i,
total: a,
progress: a ? i / a : void 0,
bytes: s,
rate: u || void 0,
estimated: u && a && i <= a ? (a - i) / u : void 0,
event: o,
};
(c[t ? "download" : "upload"] = !0), e(c);
};
}
var Oe = {
http: null,
xhr:
"undefined" != typeof XMLHttpRequest &&
function (e) {
return new Promise(function (t, n) {
var r,
o = e.data,
i = he.from(e.headers).normalize(),
a = e.responseType;
function s() {
e.cancelToken && e.cancelToken.unsubscribe(r),
e.signal && e.signal.removeEventListener("abort", r);
}
q.isFormData(o) &&
(re.isStandardBrowserEnv || re.isStandardBrowserWebWorkerEnv
? i.setContentType(!1)
: i.setContentType("multipart/form-data;", !1));
var u = new XMLHttpRequest();
if (e.auth) {
var c = e.auth.username || "",
f = e.auth.password
? unescape(encodeURIComponent(e.auth.password))
: "";
i.set("Authorization", "Basic " + btoa(c + ":" + f));
}
var l = ge(e.baseURL, e.url);
function d() {
if (u) {
var r = he.from(
"getAllResponseHeaders" in u && u.getAllResponseHeaders()
);
!(function (e, t, n) {
var r = n.config.validateStatus;
n.status && r && !r(n.status)
? t(
new M(
"Request failed with status code " + n.status,
[M.ERR_BAD_REQUEST, M.ERR_BAD_RESPONSE][
Math.floor(n.status / 100) - 4
],
n.config,
n.request,
n
)
)
: e(n);
})(
function (e) {
t(e), s();
},
function (e) {
n(e), s();
},
{
data:
a && "text" !== a && "json" !== a
? u.response
: u.responseText,
status: u.status,
statusText: u.statusText,
headers: r,
config: e,
request: u,
}
),
(u = null);
}
}
if (
(u.open(
e.method.toUpperCase(),
Y(l, e.params, e.paramsSerializer),
!0
),
(u.timeout = e.timeout),
"onloadend" in u
? (u.onloadend = d)
: (u.onreadystatechange = function () {
u &&
4 === u.readyState &&
(0 !== u.status ||
(u.responseURL &&
0 === u.responseURL.indexOf("file:"))) &&
setTimeout(d);
}),
(u.onabort = function () {
u &&
(n(new M("Request aborted", M.ECONNABORTED, e, u)), (u = null));
}),
(u.onerror = function () {
n(new M("Network Error", M.ERR_NETWORK, e, u)), (u = null);
}),
(u.ontimeout = function () {
var t = e.timeout
? "timeout of " + e.timeout + "ms exceeded"
: "timeout exceeded",
r = e.transitional || ne;
e.timeoutErrorMessage && (t = e.timeoutErrorMessage),
n(
new M(
t,
r.clarifyTimeoutError ? M.ETIMEDOUT : M.ECONNABORTED,
e,
u
)
),
(u = null);
}),
re.isStandardBrowserEnv)
) {
var p =
(e.withCredentials || we(l)) &&
e.xsrfCookieName &&
be.read(e.xsrfCookieName);
p && i.set(e.xsrfHeaderName, p);
}
void 0 === o && i.setContentType(null),
"setRequestHeader" in u &&
q.forEach(i.toJSON(), function (e, t) {
u.setRequestHeader(t, e);
}),
q.isUndefined(e.withCredentials) ||
(u.withCredentials = !!e.withCredentials),
a && "json" !== a && (u.responseType = e.responseType),
"function" == typeof e.onDownloadProgress &&
u.addEventListener("progress", Ee(e.onDownloadProgress, !0)),
"function" == typeof e.onUploadProgress &&
u.upload &&
u.upload.addEventListener("progress", Ee(e.onUploadProgress)),
(e.cancelToken || e.signal) &&
((r = function (t) {
u &&
(n(!t || t.type ? new ve(null, e, u) : t),
u.abort(),
(u = null));
}),
e.cancelToken && e.cancelToken.subscribe(r),
e.signal &&
(e.signal.aborted
? r()
: e.signal.addEventListener("abort", r)));
var h,
m = ((h = /^([-+\w]{1,25})(:?\/\/|:)/.exec(l)) && h[1]) || "";
m && -1 === re.protocols.indexOf(m)
? n(new M("Unsupported protocol " + m + ":", M.ERR_BAD_REQUEST, e))
: u.send(o || null);
});
},
};
q.forEach(Oe, function (e, t) {
if (e) {
try {
Object.defineProperty(e, "name", { value: t });
} catch (e) {}
Object.defineProperty(e, "adapterName", { value: t });
}
});
var Se = function (e) {
for (
var t, n, r = (e = q.isArray(e) ? e : [e]).length, o = 0;
o < r && ((t = e[o]), !(n = q.isString(t) ? Oe[t.toLowerCase()] : t));
o++
);
if (!n) {
if (!1 === n)
throw new M(
"Adapter ".concat(t, " is not supported by the environment"),
"ERR_NOT_SUPPORT"
);
throw new Error(
q.hasOwnProp(Oe, t)
? "Adapter '".concat(t, "' is not available in the build")
: "Unknown adapter '".concat(t, "'")
);
}
if (!q.isFunction(n)) throw new TypeError("adapter is not a function");
return n;
};
function Re(e) {
if (
(e.cancelToken && e.cancelToken.throwIfRequested(),
e.signal && e.signal.aborted)
)
throw new ve(null, e);
}
function Ae(e) {
return (
Re(e),
(e.headers = he.from(e.headers)),
(e.data = me.call(e, e.transformRequest)),
-1 !== ["post", "put", "patch"].indexOf(e.method) &&
e.headers.setContentType("application/x-www-form-urlencoded", !1),
Se(e.adapter || se.adapter)(e).then(
function (t) {
return (
Re(e),
(t.data = me.call(e, e.transformResponse, t)),
(t.headers = he.from(t.headers)),
t
);
},
function (t) {
return (
ye(t) ||
(Re(e),
t &&
t.response &&
((t.response.data = me.call(
e,
e.transformResponse,
t.response
)),
(t.response.headers = he.from(t.response.headers)))),
Promise.reject(t)
);
}
)
);
}
var Te = function (e) {
return e instanceof he ? e.toJSON() : e;
};
function je(e, t) {
t = t || {};
var n = {};
function r(e, t, n) {
return q.isPlainObject(e) && q.isPlainObject(t)
? q.merge.call({ caseless: n }, e, t)
: q.isPlainObject(t)
? q.merge({}, t)
: q.isArray(t)
? t.slice()
: t;
}
function o(e, t, n) {
return q.isUndefined(t)
? q.isUndefined(e)
? void 0
: r(void 0, e, n)
: r(e, t, n);
}
function i(e, t) {
if (!q.isUndefined(t)) return r(void 0, t);
}
function a(e, t) {
return q.isUndefined(t)
? q.isUndefined(e)
? void 0
: r(void 0, e)
: r(void 0, t);
}
function s(n, o, i) {
return i in t ? r(n, o) : i in e ? r(void 0, n) : void 0;
}
var u = {
url: i,
method: i,
data: i,
baseURL: a,
transformRequest: a,
transformResponse: a,
paramsSerializer: a,
timeout: a,
timeoutMessage: a,
withCredentials: a,
adapter: a,
responseType: a,
xsrfCookieName: a,
xsrfHeaderName: a,
onUploadProgress: a,
onDownloadProgress: a,
decompress: a,
maxContentLength: a,
maxBodyLength: a,
beforeRedirect: a,
transport: a,
httpAgent: a,
httpsAgent: a,
cancelToken: a,
socketPath: a,
responseEncoding: a,
validateStatus: s,
headers: function (e, t) {
return o(Te(e), Te(t), !0);
},
};
return (
q.forEach(Object.keys(Object.assign({}, e, t)), function (r) {
var i = u[r] || o,
a = i(e[r], t[r], r);
(q.isUndefined(a) && i !== s) || (n[r] = a);
}),
n
);
}
var Ne = "1.4.0",
Ce = {};
["object", "boolean", "number", "function", "string", "symbol"].forEach(
function (t, n) {
Ce[t] = function (r) {
return e(r) === t || "a" + (n < 1 ? "n " : " ") + t;
};
}
);
var xe = {};
Ce.transitional = function (e, t, n) {
function r(e, t) {
return (
"[Axios v1.4.0] Transitional option '" +
e +
"'" +
t +
(n ? ". " + n : "")
);
}
return function (n, o, i) {
if (!1 === e)
throw new M(
r(o, " has been removed" + (t ? " in " + t : "")),
M.ERR_DEPRECATED
);
return (
t &&
!xe[o] &&
((xe[o] = !0),
console.warn(
r(
o,
" has been deprecated since v" +
t +
" and will be removed in the near future"
)
)),
!e || e(n, o, i)
);
};
};
var Pe = {
assertOptions: function (t, n, r) {
if ("object" !== e(t))
throw new M("options must be an object", M.ERR_BAD_OPTION_VALUE);
for (var o = Object.keys(t), i = o.length; i-- > 0; ) {
var a = o[i],
s = n[a];
if (s) {
var u = t[a],
c = void 0 === u || s(u, a, t);
if (!0 !== c)
throw new M(
"option " + a + " must be " + c,
M.ERR_BAD_OPTION_VALUE
);
} else if (!0 !== r)
throw new M("Unknown option " + a, M.ERR_BAD_OPTION);
}
},
validators: Ce,
},
ke = Pe.validators,
Ue = (function () {
function e(n) {
t(this, e),
(this.defaults = n),
(this.interceptors = { request: new te(), response: new te() });
}
return (
r(e, [
{
key: "request",
value: function (e, t) {
"string" == typeof e ? ((t = t || {}).url = e) : (t = e || {});
var n,
r = (t = je(this.defaults, t)),
o = r.transitional,
i = r.paramsSerializer,
a = r.headers;
void 0 !== o &&
Pe.assertOptions(
o,
{
silentJSONParsing: ke.transitional(ke.boolean),
forcedJSONParsing: ke.transitional(ke.boolean),
clarifyTimeoutError: ke.transitional(ke.boolean),
},
!1
),
null != i &&
(q.isFunction(i)
? (t.paramsSerializer = { serialize: i })
: Pe.assertOptions(
i,
{ encode: ke.function, serialize: ke.function },
!0
)),
(t.method = (
t.method ||
this.defaults.method ||
"get"
).toLowerCase()),
(n = a && q.merge(a.common, a[t.method])) &&
q.forEach(
["delete", "get", "head", "post", "put", "patch", "common"],
function (e) {
delete a[e];
}
),
(t.headers = he.concat(n, a));
var s = [],
u = !0;
this.interceptors.request.forEach(function (e) {
("function" == typeof e.runWhen && !1 === e.runWhen(t)) ||
((u = u && e.synchronous),
s.unshift(e.fulfilled, e.rejected));
});
var c,
f = [];
this.interceptors.response.forEach(function (e) {
f.push(e.fulfilled, e.rejected);
});
var l,
d = 0;
if (!u) {
var p = [Ae.bind(this), void 0];
for (
p.unshift.apply(p, s),
p.push.apply(p, f),
l = p.length,
c = Promise.resolve(t);
d < l;
)
c = c.then(p[d++], p[d++]);
return c;
}
l = s.length;
var h = t;
for (d = 0; d < l; ) {
var m = s[d++],
y = s[d++];
try {
h = m(h);
} catch (e) {
y.call(this, e);
break;
}
}
try {
c = Ae.call(this, h);
} catch (e) {
return Promise.reject(e);
}
for (d = 0, l = f.length; d < l; ) c = c.then(f[d++], f[d++]);
return c;
},
},
{
key: "getUri",
value: function (e) {
return Y(
ge((e = je(this.defaults, e)).baseURL, e.url),
e.params,
e.paramsSerializer
);
},
},
]),
e
);
})();
q.forEach(["delete", "get", "head", "options"], function (e) {
Ue.prototype[e] = function (t, n) {
return this.request(
je(n || {}, { method: e, url: t, data: (n || {}).data })
);
};
}),
q.forEach(["post", "put", "patch"], function (e) {
function t(t) {
return function (n, r, o) {
return this.request(
je(o || {}, {
method: e,
headers: t ? { "Content-Type": "multipart/form-data" } : {},
url: n,
data: r,
})
);
};
}
(Ue.prototype[e] = t()), (Ue.prototype[e + "Form"] = t(!0));
});
var _e = Ue,
Fe = (function () {
function e(n) {
if ((t(this, e), "function" != typeof n))
throw new TypeError("executor must be a function.");
var r;
this.promise = new Promise(function (e) {
r = e;
});
var o = this;
this.promise.then(function (e) {
if (o._listeners) {
for (var t = o._listeners.length; t-- > 0; ) o._listeners[t](e);
o._listeners = null;
}
}),
(this.promise.then = function (e) {
var t,
n = new Promise(function (e) {
o.subscribe(e), (t = e);
}).then(e);
return (
(n.cancel = function () {
o.unsubscribe(t);
}),
n
);
}),
n(function (e, t, n) {
o.reason || ((o.reason = new ve(e, t, n)), r(o.reason));
});
}
return (
r(
e,
[
{
key: "throwIfRequested",
value: function () {
if (this.reason) throw this.reason;
},
},
{
key: "subscribe",
value: function (e) {
this.reason
? e(this.reason)
: this._listeners
? this._listeners.push(e)
: (this._listeners = [e]);
},
},
{
key: "unsubscribe",
value: function (e) {
if (this._listeners) {
var t = this._listeners.indexOf(e);
-1 !== t && this._listeners.splice(t, 1);
}
},
},
],
[
{
key: "source",
value: function () {
var t;
return {
token: new e(function (e) {
t = e;
}),
cancel: t,
};
},
},
]
),
e
);
})();
var Be = {
Continue: 100,
SwitchingProtocols: 101,
Processing: 102,
EarlyHints: 103,
Ok: 200,
Created: 201,
Accepted: 202,
NonAuthoritativeInformation: 203,
NoContent: 204,
ResetContent: 205,
PartialContent: 206,
MultiStatus: 207,
AlreadyReported: 208,
ImUsed: 226,
MultipleChoices: 300,
MovedPermanently: 301,
Found: 302,
SeeOther: 303,
NotModified: 304,
UseProxy: 305,
Unused: 306,
TemporaryRedirect: 307,
PermanentRedirect: 308,
BadRequest: 400,
Unauthorized: 401,
PaymentRequired: 402,
Forbidden: 403,
NotFound: 404,
MethodNotAllowed: 405,
NotAcceptable: 406,
ProxyAuthenticationRequired: 407,
RequestTimeout: 408,
Conflict: 409,
Gone: 410,
LengthRequired: 411,
PreconditionFailed: 412,
PayloadTooLarge: 413,
UriTooLong: 414,
UnsupportedMediaType: 415,
RangeNotSatisfiable: 416,
ExpectationFailed: 417,
ImATeapot: 418,
MisdirectedRequest: 421,
UnprocessableEntity: 422,
Locked: 423,
FailedDependency: 424,
TooEarly: 425,
UpgradeRequired: 426,
PreconditionRequired: 428,
TooManyRequests: 429,
RequestHeaderFieldsTooLarge: 431,
UnavailableForLegalReasons: 451,
InternalServerError: 500,
NotImplemented: 501,
BadGateway: 502,
ServiceUnavailable: 503,
GatewayTimeout: 504,
HttpVersionNotSupported: 505,
VariantAlsoNegotiates: 506,
InsufficientStorage: 507,
LoopDetected: 508,
NotExtended: 510,
NetworkAuthenticationRequired: 511,
};
Object.entries(Be).forEach(function (e) {
var t = o(e, 2),
n = t[0],
r = t[1];
Be[r] = n;
});
var Le = Be;
var De = (function e(t) {
var n = new _e(t),
r = a(_e.prototype.request, n);
return (
q.extend(r, _e.prototype, n, { allOwnKeys: !0 }),
q.extend(r, n, null, { allOwnKeys: !0 }),
(r.create = function (n) {
return e(je(t, n));
}),
r
);
})(se);
return (
(De.Axios = _e),
(De.CanceledError = ve),
(De.CancelToken = Fe),
(De.isCancel = ye),
(De.VERSION = Ne),
(De.toFormData = G),
(De.AxiosError = M),
(De.Cancel = De.CanceledError),
(De.all = function (e) {
return Promise.all(e);
}),
(De.spread = function (e) {
return function (t) {
return e.apply(null, t);
};
}),
(De.isAxiosError = function (e) {
return q.isObject(e) && !0 === e.isAxiosError;
}),
(De.mergeConfig = je),
(De.AxiosHeaders = he),
(De.formToJSON = function (e) {
return oe(q.isHTMLForm(e) ? new FormData(e) : e);
}),
(De.HttpStatusCode = Le),
(De.default = De),
De
);
});
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
odoo.define('roke_product_income_expense.product_income_expense_iframe', function (require) {
"use strict";
var core = require('web.core');
var session = require('web.session');
var AbstractAction = require('web.AbstractAction');
var ProductIncomeExpenseIFrame = AbstractAction.extend({
template: 'ProductIncomeExpenseIFrame',
init: function (parent, action, params) {
this.add_sum = 0
this.key = ""
this.old_data = {}
this.action_controller = `${action.params.controller}?user_id=${session.uid}&user_name=${session.name}`
return this._super.apply(this, arguments);
},
});
core.action_registry.add('product_income_expense_iframe', ProductIncomeExpenseIFrame);
return ProductIncomeExpenseIFrame;
});
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="ProductIncomeExpenseIFrame">
<iframe id="ProductIncomeExpenseIFrame" t-attf-src="#{widget.action_controller}" style="width: 100%;height: 100%;border: none;"></iframe>
</t>
</templates>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="roke_product_income_expense_iframe_action" model="ir.actions.client">
<field name="name">财务收支记录</field>
<field name="tag">product_income_expense_iframe</field>
<field name="target">current</field>
<field name="params" eval="{'controller': '/roke/pub/product_income_expense_iframe'}"/>
</record>
<menuitem
id="roke_product_income_expense_iframe_menu"
name="收入支出表"
action="roke_product_income_expense_iframe_action"
parent="roke_mes_production.roke_production_business_menu"
sequence="60"
groups="base.group_system"
/>
</odoo>
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--id 为自定义,唯一标识符 ,inherit_id 是继承自哪里,为固定写法-->
<template id="product_income_expense_id" inherit_id="web.assets_backend">
<!--我们用xpath 找到我们要放置的地方-->
<xpath expr="." position="inside">
<script type="text/javascript" src="/roke_product_income_expense/static/src/js/roke_product_income_expense_iframe.js"/>
</xpath>
</template>
</odoo>
\ No newline at end of file
# -*- coding: utf-8 -*-
from . import models
from . import controllers
from . import wizard
# -*- coding: utf-8 -*-
{
'name': '融科-玖姿机械',
'name': '融科-大东联石油',
'version': '14.0',
'category': 'mes',
'depends': ['roke_mes_purchase', 'roke_mes_sale', 'roke_mes_documents', 'roke_mes_stock', 'roke_workstation_api',
......@@ -11,15 +11,11 @@
玖姿机械
""",
'data': [
'datas/config_parameter_data.xml',
'datas/cron_data.xml',
'security/ir.model.access.csv',
'views/inherit_roke_mes_stock_picking_views.xml',
'views/inherit_roke_production_task.xml',
'views/button_js.xml',
'views/iniherit_work_order_view.xml',
'views/roke_work_log_views.xml',
'views/iniherit_work_center_view.xml',
'views/inherit_roke_product.xml'
],
'qweb': [
"static/src/xml/roke_craft_design.xml",
......
......@@ -168,8 +168,7 @@ class RokeWorkstationWorkOrderModel(http.Controller):
for line in lines:
if line["type"] == "delete":
line_id = line["line_id"]
routing_obj.line_ids.filtered(
lambda l: l.id == line_id).unlink()
routing_obj.line_ids.filtered(lambda l: l.id == line_id).unlink()
elif line["type"] == "add":
sequence = line["sequence"]
process_id = line["process_id"]
......
from . import inherit_roke_work_order
from . import inherit_production_task
from . import inherit_roke_routing_line
from . import inherit_roke_product
......@@ -13,12 +13,6 @@ class InheritProductionTask(models.Model):
_inherit = "roke.production.task"
file_ids = fields.Many2many("ir.attachment", "roke_production_task_ir_attachment", "pro_id", "att_id")
taskName = fields.Char(string="任务名称")
UploadMsg = fields.Char(string="上传状态")
TaskUUID = fields.Char(string="任务UUID")
spare_parts_qty = fields.Float(string="切割零部件数", default=0)
press_riveting_qty = fields.Float(string="压铆零部件数", default=0)
bending_qty = fields.Float(string="折弯零部件数", default=0)
work_order_hours = fields.Float(string="总报工时", compute="_compute_work_order_hours")
......@@ -27,23 +21,6 @@ class InheritProductionTask(models.Model):
for record in self:
record.work_order_hours = sum(record.work_order_ids.mapped("work_hours"))
def upload_task(self):
"""
上传任务 TODO 任务数量取计划数还是计划数-完成数?上传一次后还能再上传不?多个加工文件时,上传第一个还是最后一个?
:return:
"""
self.ensure_one()
if not self.work_center_id:
raise ValidationError("未指派工作中心,禁止上传")
if not self.work_center_id.card_id:
raise ValidationError("当前工作中心无控制卡信息,无法上传")
if not self.file_ids:
raise ValidationError("当前任务无加工文件,无法上传")
if not self.taskName:
raise ValidationError("必须填写任务名称")
attachment = self.file_ids[:1]
self.work_center_id.upload_task(self, attachment)
def write(self, vals):
res = super(InheritProductionTask, self).write(vals)
if vals.get('file_ids'):
......@@ -56,10 +33,6 @@ class InheritProductionTask(models.Model):
self.document_ids = [(4, a.id)]
return res
@api.onchange("routing_id", "product_id", "plan_qty", "type", "spare_parts_qty", "press_riveting_qty", "bending_qty")
def _onchange_routing_id(self):
return super(InheritProductionTask, self)._onchange_routing_id()
def change_routing_id_work_order(self, routing):
product = self.product_id
plan_qty = self.plan_qty
......@@ -75,8 +48,7 @@ class InheritProductionTask(models.Model):
work_order_data['planned_start_time'] = date
work_order_data['plan_date'] = date
work_order_data['priority'] = self.priority
work_orders.append(
(0, 0, work_order_data))
work_orders.append((0, 0, work_order_data))
else:
num = work_order_num // date_num
if num < 1:
......@@ -95,55 +67,9 @@ class InheritProductionTask(models.Model):
work_order_data['planned_start_time'] = date
work_order_data['plan_date'] = date
work_order_data['priority'] = self.priority
work_orders.append(
(0, 0, work_order_data))
work_orders.append((0, 0, work_order_data))
return work_orders
def _create_work_order_get_values(self, task, routing_line):
"""
任务生成工单获取工单数据
:return:
"""
res = super(InheritProductionTask, self)._create_work_order_get_values(task, routing_line)
rounding_type = self.env['ir.config_parameter'].sudo().get_param('e_bom.material.demand.rounding',
default="精确计算")
if "切割" in routing_line.process_id.name:
plan_qty = task.spare_parts_qty
elif "压铆" in routing_line.process_id.name:
plan_qty = task.press_riveting_qty
elif "折弯" in routing_line.process_id.name:
plan_qty = task.bending_qty
else:
plan_qty = task.plan_qty * routing_line.multiple
if rounding_type == "向上取整":
plan_qty = math.ceil(plan_qty)
elif rounding_type == "向下取整":
plan_qty = int(plan_qty)
res.update({"plan_qty": plan_qty})
return res
def _get_new_work_order_data(self, routing_line, product, plan_qty, task_type):
"""
onchang获取工单数据
:return:
"""
res = super(InheritProductionTask, self)._get_new_work_order_data(routing_line, product, plan_qty, task_type)
rounding_type = self.env['ir.config_parameter'].sudo().get_param('e_bom.material.demand.rounding', default="精确计算")
if "切割" in routing_line.process_id.name:
plan_qty = self.spare_parts_qty
elif "压铆" in routing_line.process_id.name:
plan_qty = self.press_riveting_qty
elif "折弯" in routing_line.process_id.name:
plan_qty = self.bending_qty
else:
plan_qty = self.plan_qty * routing_line.multiple
if rounding_type == "向上取整":
plan_qty = math.ceil(plan_qty)
elif rounding_type == "向下取整":
plan_qty = int(plan_qty)
res.update({"plan_qty": plan_qty})
return res
def craft_design(self):
if self.record_ids and not self.routing_id.routing_task_id:
raise ValidationError("该任务已报工,无法生成新的工艺设计。")
......
from datetime import timedelta
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
class InheritProductionTask(models.Model):
_inherit = "roke.product"
standard_hours = fields.Float(string='标准工时', help='产品的标准工时(小时)')
from odoo import models, fields, api, _
class InheritRokeRoutingLine(models.Model):
_inherit = "roke.routing.line"
rated_working_hours = fields.Float(string='标准工时', help='工序的标准工时(小时)')
class InheritRokeProcess(models.Model):
_inherit = "roke.process"
rated_working_hours = fields.Float(string='标准工时', help='工序的标准工时(小时)')
......@@ -30,52 +30,3 @@ class InheritWorkOrder(models.Model):
v.next_wo_id = v.repair_wr_id.work_order_id.id
else:
v.next_wo_id = next_wo[0].id
def _get_production_multiple(self, previous):
"""
获取当前生产倍数
:param previous:
:return:
"""
judge = "切割" in self.process_id.name or "压铆" in self.process_id.name or "折弯" in self.process_id.name
if not self.routing_line_id and not judge:
# 无工艺明细直接返回
return 1
if "切割" in self.process_id.name and self.task_id:
multiple = self.task_id.spare_parts_qty / self.task_id.plan_qty
elif "压铆" in self.process_id.name and self.task_id:
multiple = self.task_id.press_riveting_qty / self.task_id.plan_qty
elif "折弯" in self.process_id.name and self.task_id:
multiple = self.task_id.bending_qty / self.task_id.plan_qty
else:
multiple = self.routing_line_id.multiple
if len(previous) > 1:
# 取到最小数对应的前道工单
rel_previous = self._multi_previous_get_min_finished(previous)
rel_previous_judge = "切割" in rel_previous.process_id.name or "压铆" in rel_previous.process_id.name \
or "折弯" in rel_previous.process_id.name
if not rel_previous.routing_line_id.multiple and not rel_previous_judge: # 无倍数直接返回
return 1
if "切割" in rel_previous.process_id.name:
rel_previous_multiple = rel_previous.task_id.spare_parts_qty / rel_previous.task_id.plan_qty
elif "压铆" in rel_previous.process_id.name:
rel_previous_multiple = rel_previous.task_id.press_riveting_qty / rel_previous.task_id.plan_qty
elif "折弯" in rel_previous.process_id.name:
rel_previous_multiple = rel_previous.task_id.bending_qty / rel_previous.task_id.plan_qty
else:
rel_previous_multiple = rel_previous.routing_line_id.multiple
return multiple / rel_previous_multiple
if not previous.routing_line_id.multiple and not judge: # 无倍数直接返回
return 1
elif not previous and judge:
return 1
if "切割" in previous.process_id.name and self.task_id and previous.task_id:
previous_multiple = previous.task_id.spare_parts_qty / self.task_id.plan_qty
elif "压铆" in previous.process_id.name and self.task_id and previous.task_id:
previous_multiple = previous.task_id.press_riveting_qty / self.task_id.plan_qty
elif "折弯" in previous.process_id.name and self.task_id and previous.task_id:
previous_multiple = previous.task_id.bending_qty / self.task_id.plan_qty
else:
previous_multiple = previous.routing_line_id.multiple
return (multiple / previous_multiple) if previous_multiple else 0
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
,,,,,,,
\ No newline at end of file
......@@ -7,14 +7,14 @@
<!-- 禁止界面缩放 -->
<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文件-->
<link rel="stylesheet" href="/jzjx_project/static/src/html/element-ui/index.css" />
<link rel="stylesheet" href="/jzjx_project/static/src/html/assets/iconfont/iconfont.css" />
<script src="/jzjx_project/static/src/html/js/vue.js"></script>
<script src="/jzjx_project/static/src/html/js/axios.min.js"></script>
<script src="/jzjx_project/static/src/html/js/Sortable.min.js"></script>
<script src="/jzjx_project/static/src/html/js/vuedraggable.umd.min.js"></script>
<script src="/jzjx_project/static/src/html/element-ui/index.js"></script>
<script src="/jzjx_project/static/src/html/assets/iconfont/iconfont.js"></script>
<link rel="stylesheet" href="/sdddl_project/static/src/html/element-ui/index.css" />
<link rel="stylesheet" href="/sdddl_project/static/src/html/assets/iconfont/iconfont.css" />
<script src="/sdddl_project/static/src/html/js/vue.js"></script>
<script src="/sdddl_project/static/src/html/js/axios.min.js"></script>
<script src="/sdddl_project/static/src/html/js/Sortable.min.js"></script>
<script src="/sdddl_project/static/src/html/js/vuedraggable.umd.min.js"></script>
<script src="/sdddl_project/static/src/html/element-ui/index.js"></script>
<script src="/sdddl_project/static/src/html/assets/iconfont/iconfont.js"></script>
</head>
<body id="bodyId" style="display: none;">
......
odoo.define('jzjx_project.roke_craft_design', function (require) {
odoo.define('sdddl_project.roke_craft_design', function (require) {
"use strict";
var core = require('web.core');
......@@ -7,7 +7,7 @@ odoo.define('jzjx_project.roke_craft_design', function (require) {
const Dialog = require("web.Dialog");
var RokeCraftDesign = AbstractAction.extend({
template: 'jzjx_project.roke_craft_design',
template: 'sdddl_project.roke_craft_design',
init: function (parent, action, params) {
this.action_controller = `${action.params.controller}&user_id=${session.uid}`;
......@@ -74,6 +74,6 @@ odoo.define('jzjx_project.roke_craft_design', function (require) {
}
});
core.action_registry.add('jzjx_project.roke_craft_design', RokeCraftDesign);
core.action_registry.add('sdddl_project.roke_craft_design', RokeCraftDesign);
return RokeCraftDesign;
});
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<templates id="roke_routing_settings_template" xml:space="preserve">
<t t-name="jzjx_project.roke_craft_design">
<t t-name="sdddl_project.roke_craft_design">
<iframe id="roke_craft_design.xml_iframe" t-attf-src="#{widget.action_controller}" frameBorder="no" width="100%" height="100%" />
</t>
</templates>
\ No newline at end of file
......@@ -3,8 +3,8 @@
<template id="roke_jz_jx_templates" inherit_id="web.assets_backend" name="roke_jz_jx">
<xpath expr="script[last()]" position="after">
<!-- <script type="text/javascript" src="/roke_pub_wx_notice/static/src/js/sync_wx_btn.js"/>-->
<script type="text/javascript" src="/jzjx_project/static/src/js/button.js"/>
<script type="text/javascript" src="/jzjx_project/static/src/js/roke_craft_design.js"/>
<script type="text/javascript" src="/sdddl_project/static/src/js/button.js"/>
<script type="text/javascript" src="/sdddl_project/static/src/js/roke_craft_design.js"/>
</xpath>
</template>
</odoo>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="view_roke_product_form_inherit_standard_hours" model="ir.ui.view">
<field name="name">roke.product.form.inherit.standard.hours</field>
<field name="model">roke.product</field>
<field name="inherit_id" ref="roke_workstation_api.capacity_inherit_view_roke_product_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='capacity']" position="after">
<field name="standard_hours"/>
</xpath>
</field>
</record>
</data>
</odoo>
\ No newline at end of file
......@@ -8,21 +8,10 @@
<xpath expr="//page/group[@name='attachment']" position="after">
<field name="file_ids" widget="many2many_pic_preview" string="上传作业指导"/>
</xpath>
<xpath expr="//field[@name='sum_unqualified_qty']" position="after">
<field name="taskName"/>
</xpath>
<xpath expr="//field[@name='pass_rate']" position="after">
<field name="UploadMsg" readonly="1"/>
<field name="work_order_hours" readonly="1"/>
</xpath>
<xpath expr="//field[@name='type']" position="after">
<field name="spare_parts_qty"/>
<field name="press_riveting_qty"/>
<field name="bending_qty"/>
</xpath>
<xpath expr="//header" position="inside">
<button name="upload_task" type="object" string="上传任务" class="btn btn-primary"
attrs="{'invisible': [('UploadMsg', '=', 'OK')]}"/>
<field name="record_ids" invisible="1"/>
<button name="craft_design" type="object" string="工艺设计" class="btn btn-primary"/>
</xpath>
......
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