300 lines
14 KiB
Python
300 lines
14 KiB
Python
# -*- coding: utf-8 -*-
|
||
import base64
|
||
import json, requests
|
||
from odoo import models, fields, api, _
|
||
from datetime import datetime, timedelta
|
||
from odoo.exceptions import UserError, ValidationError
|
||
|
||
|
||
# sf排程
|
||
class sf_production_plan(models.Model):
|
||
_name = 'sf.production.plan'
|
||
# _inherit = 'mrp.production'
|
||
_description = 'sf_production_plan'
|
||
|
||
state = fields.Selection([
|
||
('draft', '待排程'),
|
||
('done', '已排程'),
|
||
('processing', '已加工'),
|
||
('finished', '已完成')
|
||
], string='工单状态', tracking=True)
|
||
name = fields.Char(string='工单编号')
|
||
# selected = fields.Boolean(default=False)
|
||
# order_number = fields.Char(string='订单号')
|
||
order_deadline = fields.Datetime(string='订单交期')
|
||
production_id = fields.Many2one('mrp.production', '关联制造订单')
|
||
product_qty = fields.Float(string='数量', digits='Product Unit of Measure', required=True, default=0.0)
|
||
production_line_id = fields.Many2one('sf.production.line', string='生产线')
|
||
date_planned_start = fields.Datetime(string='计划开始时间', required=True, index=True, copy=False,
|
||
default=fields.Datetime.now)
|
||
date_planned_finished = fields.Datetime(string='计划结束时间')
|
||
# 排程设置selection(倒排,顺排,默认倒排)
|
||
schedule_setting = fields.Selection([
|
||
('reverse', '倒排'), ('positive', '顺排')], string='排程设置', default='reverse')
|
||
product_id = fields.Many2one('product.product', '关联产品')
|
||
origin = fields.Char(string='订单号')
|
||
# 加工时长
|
||
process_time = fields.Float(string='加工时长', digits=(16, 2))
|
||
# 实际加工时长、实际开始时间、实际结束时间
|
||
actual_process_time = fields.Float(string='实际加工时长', digits=(16, 2))
|
||
actual_start_time = fields.Datetime(string='实际开始时间')
|
||
actual_end_time = fields.Datetime(string='实际结束时间')
|
||
shift = fields.Char(string='班次')
|
||
|
||
|
||
# 序号、坯料编号、坯料名称、材质、数量、长度、宽度、厚度、直径、计划开始时间、计划结束时间、状态(已产出与待产出)、操作、创建人、创建时间、客户名称、订单号、行号、长度、宽度、厚度、直径、交货数量、交货日期
|
||
# sequence = fields.Integer(string='序号', required=True, copy=False, readonly=True, index=True,
|
||
# default=lambda self: self.env['ir.sequence'].sudo().next_by_code('sf.pl.plan'))
|
||
sequence = fields.Integer(string='序号', copy=False, readonly=True, index=True)
|
||
current_operation_name = fields.Char(string='当前工序名称', size=64, default='生产计划')
|
||
|
||
|
||
|
||
|
||
|
||
|
||
# state = fields.Selection([
|
||
# ('未排程', '未排程'), ('已排程', '已排程')], string='State', copy=False, index=True, readonly=True,
|
||
# store=True, tracking=True)
|
||
|
||
# orderpoint_id = fields.Many2one('stock.warehouse.orderpoint', compute='_compute_orderpoint_id')
|
||
# location_src_id = fields.Many2one('stock.location', 'Components Location', compute='_compute_orderpoint_id', active=False)
|
||
# location_dest_id = fields.Many2one('stock.location', 'Finished Products Location', compute='_compute_orderpoint_id')
|
||
# picking_type_id = fields.Many2one('stock.picking.type', 'Operation Type', compute='_compute_orderpoint_id')
|
||
# move_dest_ids = fields.One2many('stock.move', 'created_production_id', compute='_compute_orderpoint_id')
|
||
|
||
@api.model
|
||
def _compute_orderpoint_id(self):
|
||
pass
|
||
|
||
def test_sale_order(self):
|
||
company_id = self.env.ref('base.main_company').sudo()
|
||
date = datetime.today()
|
||
aaa = self.env['sale.order'].with_user(self.env.ref("base.user_admin")).sale_order_create(
|
||
company_id, 'delivery_name', 'delivery_telephone', 'delivery_address',
|
||
date)
|
||
print('aaa', aaa)
|
||
|
||
# 当不设置计划结束时间时,增加计算计划结束时间的方法,根据采购周期加缓冲期两个值来算就可以了
|
||
def action_view_production_schedule(self):
|
||
self.ensure_one()
|
||
if self.date_planned_start and self.date_planned_finished:
|
||
return None
|
||
elif self.date_planned_start and not self.date_planned_finished:
|
||
# 如果没有给出计划结束时间,则计划结束时间为计划开始时间+采购周期+缓冲期
|
||
# 采购周期
|
||
purchase_cycle = 3
|
||
# 缓冲期
|
||
buffer_period = 1
|
||
# 计划结束时间 = 计划开始时间 + 采购周期 + 缓冲期
|
||
self.date_planned_finished = self.date_planned_start + timedelta(days=purchase_cycle) + timedelta(
|
||
days=buffer_period)
|
||
self.state = '已排程'
|
||
return self.date_planned_finished
|
||
else:
|
||
return None
|
||
|
||
def cancel_plan(self):
|
||
self.ensure_one()
|
||
self.date_planned_finished = None
|
||
self.state = 'draft'
|
||
|
||
# @api.model
|
||
# def create(self, vals):
|
||
# if 'sequence' not in vals:
|
||
# vals['sequence'] = self.env['sf.production.plan'].search_count([]) + 1
|
||
# return super().create(vals)
|
||
|
||
def unlink(self):
|
||
sequence_to_reorder = self.mapped('sequence')
|
||
res = super().unlink()
|
||
records_to_reorder = self.search([('sequence', '>', min(sequence_to_reorder))])
|
||
for record in records_to_reorder:
|
||
record.sequence -= 1
|
||
return res
|
||
|
||
# 生成编码
|
||
def _get_pl_no(self):
|
||
sf_pl_no = self.env['sf.production.plan'].sudo().search(
|
||
[('pl_no', '!=', '')],
|
||
limit=1,
|
||
order="id desc")
|
||
today_date = datetime.today().strftime('%y%m%d')
|
||
if not sf_pl_no:
|
||
# 如果没有找到先前的坯料编码,则今天的第一个坯料编码为PL230520-001
|
||
num = 'PL' + today_date + '-001'
|
||
else:
|
||
# 获取最后一个坯料编码
|
||
last_pl_no = sf_pl_no.pl_no
|
||
last_date = last_pl_no[2:8]
|
||
last_seq = int(last_pl_no[-3:])
|
||
|
||
if last_date == today_date:
|
||
# 如果最后一个坯料编码的日期与今天相同,则序号加1
|
||
new_seq = last_seq + 1
|
||
num = 'PL' + today_date + f'-{new_seq:03}'
|
||
else:
|
||
# 如果最后一个坯料编码的日期与今天不同,则今天的第一个坯料编码为PL230520-001
|
||
num = 'PL' + today_date + '-001'
|
||
|
||
return num
|
||
|
||
# pl_no = fields.Char(string='坯料编号', required=True, default=_get_pl_no, readonly=True)
|
||
# pl_name = fields.Char(string='坯料名称', size=64, required=True)
|
||
# material = fields.Many2one('sf.production.materials', string='材质', required=True)
|
||
# quantity = fields.Float(string='数量', required=True)
|
||
# length = fields.Float(string='长度', required=True)
|
||
# width = fields.Float(string='宽度', required=True)
|
||
# thickness = fields.Float(string='厚度', required=True)
|
||
# diameter = fields.Float(string='直径', required=True)
|
||
# plan_start_time = fields.Datetime(string='计划开始时间')
|
||
# plan_end_time = fields.Datetime(string='计划结束时间')
|
||
# state = fields.Selection([
|
||
# ('draft', '待排程'),
|
||
# ('produce', '已排程'),
|
||
# ('done', '已产出'),
|
||
# ], string='状态', copy=False, index=True, default='draft')
|
||
# customer_name = fields.Char(string='客户名称', size=64)
|
||
# order_no = fields.Char(string='订单号', size=64)
|
||
# line_no = fields.Char(string='行号', size=64)
|
||
# delivery_length = fields.Float(string='交货长度')
|
||
# delivery_width = fields.Float(string='交货宽度')
|
||
# delivery_thickness = fields.Float(string='交货厚度')
|
||
# delivery_diameter = fields.Float(string='交货直径')
|
||
# delivery_quantity = fields.Float(string='交货数量')
|
||
# delivery_date = fields.Datetime(string='交货日期', related='plan_end_time', readonly=False, store=True)
|
||
|
||
# 当不设置计划结束时间时,增加计算计划结束时间的方法,根据采购周期加缓冲期两个值来算就可以了
|
||
def do_production_schedule(self):
|
||
if not self.production_line_id:
|
||
raise ValidationError("未选择生产线")
|
||
else:
|
||
aa = self.env['mrp.production'].sudo().search([('name', '=', self.name)])
|
||
workorder_time = 0
|
||
print(aa.workorder_ids)
|
||
print(type(aa.workorder_ids))
|
||
if aa.workorder_ids:
|
||
for item in aa.workorder_ids:
|
||
current_workorder = self.env['mrp.workorder'].sudo().search([('id', '=', item.id)])
|
||
workorder_time += current_workorder.duration_expected
|
||
print(workorder_time)
|
||
self.date_planned_finished = self.date_planned_start + timedelta(minutes=workorder_time)
|
||
self.state = 'done'
|
||
else:
|
||
self.date_planned_finished = self.date_planned_start + timedelta(days=3)
|
||
self.state = 'done'
|
||
return {
|
||
'name': '排程甘特图',
|
||
'type': 'ir.actions.act_window',
|
||
'res_model': 'sf.production.plan', # 要跳转的模型名称
|
||
'view_mode': 'gantt,tree,form', # 要显示的视图类型,可以是'form', 'tree', 'kanban', 'graph', 'calendar', 'pivot'等
|
||
'target': 'current', # 跳转的目标窗口,可以是'current'或'new'
|
||
}
|
||
# if self.production_line_id:
|
||
# if self.plan_start_time and self.plan_end_time:
|
||
# return None
|
||
# elif self.plan_start_time and not self.plan_end_time:
|
||
# # 如果没有给出计划结束时间,则计划结束时间为计划开始时间+采购周期+缓冲期
|
||
# # 采购周期
|
||
# purchase_cycle = 3
|
||
# # 缓冲期
|
||
# buffer_period = 1
|
||
# # 计划结束时间 = 计划开始时间 + 采购周期 + 缓冲期
|
||
# self.plan_end_time = self.plan_start_time + timedelta(days=purchase_cycle) + timedelta(
|
||
# days=buffer_period)
|
||
# self.state = 'produce'
|
||
# return self.plan_end_time
|
||
# else:
|
||
# return None
|
||
# # 后面要补充计划开始时间的计算方法
|
||
# # # 坯料预制时间
|
||
# # # pl_time = 0.5
|
||
# # # 采购周期
|
||
# # purchase_cycle = 3
|
||
# # # 缓冲期
|
||
# # buffer_period = 1
|
||
# # # 计划结束时间 = 计划开始时间 + 坯料预制时间 + 采购周期 + 缓冲期
|
||
# # # plan_end_time = plan_start_time + pl_time + purchase_cycle + buffer_period
|
||
# # # 计划结束时间 = 计划开始时间(是一个datatime) + 采购周期(Float) + 缓冲期(Float)
|
||
# # self.plan_end_time = self.plan_start_time + timedelta(days=purchase_cycle) + timedelta(days=buffer_period)
|
||
# # return self.plan_end_time
|
||
# else:
|
||
# raise ValidationError('生产线为空!')
|
||
|
||
def cancel_production_schedule(self):
|
||
self.date_planned_finished = False
|
||
self.state = 'draft'
|
||
return self.date_planned_finished
|
||
|
||
def liucheng_cs(self):
|
||
res = {'order_number': '123', 'delivery_end_date': str(datetime.now()),
|
||
'delivery_name': '机企猫', 'delivery_telephone': '18943919239',
|
||
'delivery_address': '新时空大厦',
|
||
'bfm_process_order_list': []}
|
||
aa = self.env['ir.attachment'].search([('id', '=', 631)])
|
||
temp = self.env['product.template'].search([('id', '=', 47)])
|
||
item = aa.datas.decode('utf-8')
|
||
val = {
|
||
'model_long': 3,
|
||
'model_width': 1,
|
||
'model_height': 1,
|
||
'model_volume': 3,
|
||
'model_machining_precision': '0.10',
|
||
'model_name': aa.name,
|
||
'model_data': base64.b64encode(aa.datas).decode('utf-8'),
|
||
'model_file': base64.b64encode(temp.model_file).decode('utf-8'),
|
||
'texture_code': '001',
|
||
'texture_type_code': '001001',
|
||
# 'surface_process_code': self.env['jikimo.surface.process']._json_surface_process_code(item),
|
||
'process_parameters_code': 'R',
|
||
'price': 20,
|
||
'number': 2,
|
||
'total_amount': 100,
|
||
'remark': '这只是测试',
|
||
'barcode': 123456789,
|
||
}
|
||
res['bfm_process_order_list'].append(val)
|
||
url = '/api/bfm_process_order/list'
|
||
res['bfm_process_order_list'] = json.dumps(res['bfm_process_order_list'])
|
||
try:
|
||
ret = requests.post(('http://localhost:1069' + url), json={}, data=res)
|
||
# aa = json.loads(ret.text)
|
||
print(ret)
|
||
except Exception as e:
|
||
raise UserError(e)
|
||
|
||
|
||
# # sf生产排程
|
||
# class sf_produce_plan(models.Model):
|
||
# _name = 'sf.produce.plan'
|
||
# _description = 'sf生产排程'
|
||
|
||
# # 重写create方法,使得创建坯料预制排程时,如果给出了计划结束时间,则计划开始时间为计划结束时间减去坯料预制时间
|
||
# @api.model
|
||
# def create(self, vals):
|
||
# # 评估结束时间
|
||
# vals['plan_end_time'] = self._get_plan_end_time(vals['plan_start_time'], vals['quantity'])
|
||
# return super(sf_pl_plan, self).create(vals)
|
||
|
||
# # 当不设置计划结束时间时,增加计算计划结束时间的方法
|
||
# @api.onchange('plan_start_time', 'quantity')
|
||
# def _onchange_plan_start_time(self):
|
||
# if self.plan_start_time and self.quantity:
|
||
# self.plan_end_time = self._get_plan_end_time(self.plan_start_time, self.quantity)
|
||
#
|
||
# # 计算计划结束时间
|
||
# def _get_plan_end_time(self, plan_start_time, quantity):
|
||
# # 坯料预制时间
|
||
# pl_time = 0.5
|
||
# # 计划结束时间 = 计划开始时间 + 坯料预制时间
|
||
# plan_end_time = plan_start_time + pl_time
|
||
# return plan_end_time
|
||
#
|
||
|
||
# 机台作业计划
|
||
class machine_work_schedule(models.Model):
|
||
_name = 'sf.machine.schedule'
|
||
_description = '机台作业计划'
|
||
|
||
name = fields.Char(string='机台名')
|