Compare commits
6 Commits
master_sf_
...
feature/71
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
307e860fe0 | ||
|
|
bd27f288f7 | ||
|
|
5bb6fcd4f7 | ||
|
|
b33c992b25 | ||
|
|
788183e239 | ||
|
|
f38f60a6a8 |
2
jikimo_demand_plan_queue/__init__.py
Normal file
2
jikimo_demand_plan_queue/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import models
|
||||
18
jikimo_demand_plan_queue/__manifest__.py
Normal file
18
jikimo_demand_plan_queue/__manifest__.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': '机企猫 需求计划排程队列',
|
||||
'version': '1.0',
|
||||
'summary': """ 使用队列进行排程 """,
|
||||
'author': 'fox',
|
||||
'website': '',
|
||||
'category': '',
|
||||
'depends': ['queue_job_batch', 'sf_demand_plan'],
|
||||
'data': [
|
||||
|
||||
],
|
||||
|
||||
'application': True,
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
2
jikimo_demand_plan_queue/models/__init__.py
Normal file
2
jikimo_demand_plan_queue/models/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import production_demand_plan
|
||||
20
jikimo_demand_plan_queue/models/production_demand_plan.py
Normal file
20
jikimo_demand_plan_queue/models/production_demand_plan.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class ProductionDemandPlan(models.Model):
|
||||
_inherit = 'sf.production.demand.plan'
|
||||
|
||||
|
||||
def _do_production_schedule(self, pro_plan_list):
|
||||
"""使用队列进行排程"""
|
||||
batch_size = 10
|
||||
current_time = fields.Datetime.now().strftime('%Y%m%d%H%M%S')
|
||||
index = 1
|
||||
for i in range(0, len(pro_plan_list), batch_size):
|
||||
batch = self.env['queue.job.batch'].get_new_batch('plan-%s-%s' % (current_time, index))
|
||||
pro_plans = pro_plan_list[i:i+batch_size]
|
||||
pro_plans.with_context(
|
||||
job_batch=batch
|
||||
).with_delay().do_production_schedule()
|
||||
index += 1
|
||||
batch.enqueue()
|
||||
@@ -190,7 +190,7 @@ def _create(self, data_list):
|
||||
# 如果该用户组被限制创建或更新操作
|
||||
if rec['is_create_or_update']:
|
||||
raise UserError(
|
||||
_("您没有执行此操作的权限。请联系管理员"))
|
||||
_("您没有执行此操作(%s)的权限。请联系管理员" % group_xml_id))
|
||||
else:
|
||||
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
|
||||
# 例如,记录日志、发送通知或者简单地跳过这部分逻辑
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
""",
|
||||
'category': 'sf',
|
||||
'website': 'https://www.sf.jikimo.com',
|
||||
'depends': ['sf_plan', 'jikimo_printing'],
|
||||
'depends': ['sf_plan'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'views/demand_plan.xml',
|
||||
|
||||
@@ -72,7 +72,6 @@ class SfProductionDemandPlan(models.Model):
|
||||
model_long = fields.Char('尺寸(mm)', compute='_compute_model_long')
|
||||
blank_type = fields.Selection([('圆料', '圆料'), ('方料', '方料')], string='坯料分类',
|
||||
related='product_id.blank_type')
|
||||
blank_precision = fields.Selection([('精坯', '精坯'), ('粗坯', '粗坯')], string='坯料类型', related='product_id.blank_precision')
|
||||
embryo_long = fields.Char('坯料尺寸(mm)', compute='_compute_embryo_long')
|
||||
materials_id = fields.Char('材料', compute='_compute_materials_id', store=True)
|
||||
model_machining_precision = fields.Selection(selection=_get_machining_precision, string='精度',
|
||||
@@ -197,14 +196,11 @@ class SfProductionDemandPlan(models.Model):
|
||||
else:
|
||||
line.model_long = None
|
||||
|
||||
@api.depends('product_id.model_long', 'product_id.model_width', 'product_id.model_height', 'product_id.blank_type')
|
||||
@api.depends('product_id.model_long', 'product_id.model_width', 'product_id.model_height')
|
||||
def _compute_embryo_long(self):
|
||||
for line in self:
|
||||
if line.product_id:
|
||||
if line.product_id.blank_type == '圆料':
|
||||
line.embryo_long = f"Ø{round(line.product_id.model_width, 3)}*{round(line.product_id.model_long, 3)}"
|
||||
else:
|
||||
line.embryo_long = f"{round(line.product_id.model_long, 3)}*{round(line.product_id.model_width, 3)}*{round(line.product_id.model_height, 3)}"
|
||||
line.embryo_long = f"{round(line.product_id.model_long, 3)}*{round(line.product_id.model_width, 3)}*{round(line.product_id.model_height, 3)}"
|
||||
else:
|
||||
line.embryo_long = None
|
||||
|
||||
@@ -327,8 +323,12 @@ class SfProductionDemandPlan(models.Model):
|
||||
date_planned_start = datetime.combine(date_part, time_part)
|
||||
pro_plan_list.production_line_id = sf_production_line.id
|
||||
pro_plan_list.date_planned_start = date_planned_start
|
||||
for pro_plan in pro_plan_list:
|
||||
pro_plan.do_production_schedule()
|
||||
self._do_production_schedule(pro_plan_list)
|
||||
|
||||
def _do_production_schedule(self, pro_plan_list):
|
||||
for pro_plan in pro_plan_list:
|
||||
pro_plan.do_production_schedule()
|
||||
|
||||
|
||||
def button_action_print(self):
|
||||
return {
|
||||
@@ -403,30 +403,29 @@ class SfProductionDemandPlan(models.Model):
|
||||
outsourcing_purchase_request.extend(pr_ids.ids)
|
||||
if record.supply_method == 'outsourcing' and not record.sale_order_line_id.is_incoming_material:
|
||||
bom_line_ids = record.product_id.bom_ids.bom_line_ids
|
||||
if bom_line_ids:
|
||||
# BOM_数量
|
||||
total_product_qty = sum(line.product_qty for line in bom_line_ids)
|
||||
bom_product_ids = bom_line_ids.mapped('product_id')
|
||||
product_purchase_orders = self.env['purchase.order'].sudo().search([
|
||||
('state', 'in', ('purchase', 'done')),
|
||||
('order_line.product_id', 'in', bom_product_ids.ids)
|
||||
])
|
||||
# 购订单_数量
|
||||
total_outsourcing_purchase_quantity = sum(
|
||||
sum(
|
||||
order.order_line.filtered(
|
||||
lambda line: line.product_id in bom_product_ids
|
||||
).mapped('product_qty')
|
||||
)
|
||||
for order in product_purchase_orders
|
||||
# BOM_数量
|
||||
total_product_qty = sum(line.product_qty for line in bom_line_ids)
|
||||
bom_product_ids = bom_line_ids.mapped('product_id')
|
||||
product_purchase_orders = self.env['purchase.order'].sudo().search([
|
||||
('state', 'in', ('purchase', 'done')),
|
||||
('order_line.product_id', 'in', bom_product_ids.ids)
|
||||
])
|
||||
# 购订单_数量
|
||||
total_outsourcing_purchase_quantity = sum(
|
||||
sum(
|
||||
order.order_line.filtered(
|
||||
lambda line: line.product_id in bom_product_ids
|
||||
).mapped('product_qty')
|
||||
)
|
||||
quantity = total_outsourcing_purchase_quantity / total_product_qty
|
||||
if float_compare(quantity, record.product_uom_qty,
|
||||
precision_rounding=record.product_id.uom_id.rounding) == -1:
|
||||
purchase_request = self.env['purchase.request'].sudo().search(
|
||||
[('line_ids.product_id', 'in', bom_product_ids.ids),
|
||||
('line_ids.purchase_state', 'not in', ('purchase', 'done')), ('state', '!=', 'done')])
|
||||
outsourcing_purchase_request.extend(purchase_request.ids)
|
||||
for order in product_purchase_orders
|
||||
)
|
||||
quantity = total_outsourcing_purchase_quantity / total_product_qty
|
||||
if float_compare(quantity, record.product_uom_qty,
|
||||
precision_rounding=record.product_id.uom_id.rounding) == -1:
|
||||
purchase_request = self.env['purchase.request'].sudo().search(
|
||||
[('line_ids.product_id', 'in', bom_product_ids.ids),
|
||||
('line_ids.purchase_state', 'not in', ('purchase', 'done')), ('state', '!=', 'done')])
|
||||
outsourcing_purchase_request.extend(purchase_request.ids)
|
||||
record.outsourcing_purchase_request = json.dumps(outsourcing_purchase_request)
|
||||
if outsourcing_purchase_request:
|
||||
record.hide_action_purchase_orders = True
|
||||
|
||||
@@ -81,9 +81,4 @@
|
||||
input,label {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
th[data-name=processing_time] + th::before{
|
||||
content: '待执行单据';
|
||||
line-height: 38px;
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,14 @@
|
||||
<field name="model">sf.production.demand.plan</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="需求计划" default_order="sequence desc,id desc" editable="bottom"
|
||||
class="demand_plan_tree freeze-columns-before-part_number">
|
||||
class="demand_plan_tree">
|
||||
<header>
|
||||
<button string="打印" name="button_action_print" type="object"
|
||||
class="btn-primary"/>
|
||||
</header>
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="id" optional="hide"/>
|
||||
<field name="priority"/>
|
||||
<field name="status"/>
|
||||
<field name="customer_name"/>
|
||||
<field name="order_remark"/>
|
||||
@@ -27,8 +28,7 @@
|
||||
<field name="qty_delivered"/>
|
||||
<field name="qty_to_deliver"/>
|
||||
<field name="model_long"/>
|
||||
<field name="blank_type" optional="hide"/>
|
||||
<field name="blank_precision"/>
|
||||
<field name="blank_type"/>
|
||||
<field name="embryo_long"/>
|
||||
<field name="materials_id"/>
|
||||
<field name="model_machining_precision"/>
|
||||
@@ -43,10 +43,7 @@
|
||||
<field name="date_order"/>
|
||||
<field name="contract_code"/>
|
||||
<field name="plan_remark"/>
|
||||
<field name="priority" decoration-danger="priority == '1'"
|
||||
decoration-warning="priority == '2'"
|
||||
decoration-info="priority == '3'"
|
||||
decoration-success="priority == '4'"/>
|
||||
<field name="processing_time"/>
|
||||
<field name="material_check" optional="hide"/>
|
||||
<field name="hide_action_open_mrp_production" invisible="1"/>
|
||||
<field name="hide_action_purchase_orders" invisible="1"/>
|
||||
@@ -65,7 +62,6 @@
|
||||
<field name="planned_start_date"/>
|
||||
<field name="actual_start_date"/>
|
||||
<field name="actual_end_date"/>
|
||||
<field name="processing_time"/>
|
||||
<field name="create_date" optional="hide" string="创建时间"/>
|
||||
<field name="create_uid" optional="hide" string="创建人"/>
|
||||
<field name="write_date" string="更新时间"/>
|
||||
@@ -95,8 +91,7 @@
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="group_by_priority" string="优先级" domain="[]" context="{'group_by': 'priority'}"/>
|
||||
<filter name="group_by_status" string="状态" domain="[]" context="{'group_by': 'status'}"/>
|
||||
<filter name="group_by_customer_name" string="客户" domain="[]"
|
||||
context="{'group_by': 'customer_name'}"/>
|
||||
<filter name="group_by_customer_name" string="客户" domain="[]" context="{'group_by': 'customer_name'}"/>
|
||||
<filter name="group_by_is_incoming_material" string="客供料" domain="[]"
|
||||
context="{'group_by': 'is_incoming_material'}"/>
|
||||
<filter name="group_by_supply_method" string="供货方式" domain="[]"
|
||||
@@ -127,9 +122,4 @@
|
||||
action="sf_production_demand_plan_action"
|
||||
parent="sf_plan.sf_production_plan_menu"
|
||||
/>
|
||||
|
||||
<!-- 调拨动作中屏蔽验证-->
|
||||
<record id="stock.action_validate_picking" model="ir.actions.server">
|
||||
<field name="binding_model_id" eval="False"/>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -3,7 +3,6 @@ import logging
|
||||
|
||||
import re
|
||||
from odoo import models, fields, api
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class ResProductCategory(models.Model):
|
||||
@@ -48,14 +47,11 @@ class ResMrpBomMo(models.Model):
|
||||
item.subcontractor_name = ''
|
||||
|
||||
def bom_create_line_has(self, embryo):
|
||||
product = self.product_tmpl_id
|
||||
if product.unit_number in (0, None, False):
|
||||
raise ValidationError(f'产品{product.name}单件用量的值不能为{product.unit_number}')
|
||||
vals = {
|
||||
'bom_id': self.id,
|
||||
'product_id': embryo.id,
|
||||
'product_tmpl_id': embryo.product_tmpl_id.id,
|
||||
'product_qty': product.unit_number,
|
||||
'product_qty': 1,
|
||||
'product_uom_id': 1
|
||||
}
|
||||
return self.env['mrp.bom.line'].sudo().create(vals)
|
||||
@@ -126,7 +122,7 @@ class ResMrpBomMo(models.Model):
|
||||
# 查bom的原材料
|
||||
def get_raw_bom(self, product):
|
||||
raw_bom = self.env['product.product'].search(
|
||||
[('categ_id.type', '=', '原材料'), ('materials_type_id', '=', product.materials_type_id.id)], limit=1)
|
||||
[('categ_id.type', '=', '原材料'), ('materials_type_id', '=', product.materials_type_id.id)],limit=1)
|
||||
return raw_bom
|
||||
|
||||
|
||||
|
||||
@@ -95,8 +95,6 @@
|
||||
<page string="加工参数">
|
||||
<group>
|
||||
<group string="模型">
|
||||
<field name="blank_type" readonly="1"/>
|
||||
<field name="blank_precision" readonly="1"/>
|
||||
<label for="model_long" string="坯料尺寸[mm]"/>
|
||||
<div class="o_address_format">
|
||||
<label for="model_long" string="长"/>
|
||||
@@ -106,7 +104,7 @@
|
||||
<label for="model_height" string="高"/>
|
||||
<field name="model_height" class="o_address_zip"/>
|
||||
</div>
|
||||
<field name="unit_number" readonly="1"/>
|
||||
<field name="blank_type" readonly="1"/>
|
||||
<field name="model_volume" string="体积[mm³]"/>
|
||||
<field name="product_model_type_id" string="模型类型"/>
|
||||
<field name="model_processing_panel" placeholder="例如R,U" string="加工面板"
|
||||
|
||||
@@ -489,7 +489,7 @@ class Sf_Dashboard_Connect(http.Controller):
|
||||
|
||||
# 工单返工数量
|
||||
|
||||
plan_data_rework = work_order_obj.search(work_order_domain + [
|
||||
plan_data_rework = work_order_obj.search(plan_domain + [
|
||||
('state', 'in', ['rework'])
|
||||
])
|
||||
|
||||
@@ -857,6 +857,7 @@ class Sf_Dashboard_Connect(http.Controller):
|
||||
:param kw:
|
||||
:return:
|
||||
"""
|
||||
request.env['stock.warehouse'].browse(request.env.company.id).pbm_loc_id
|
||||
# res = {'status': 1, 'message': '成功', 'not_done_data': [], 'done_data': []}
|
||||
res = {'status': 1, 'message': '成功', 'data': {}}
|
||||
plan_obj = request.env['sf.production.plan'].sudo()
|
||||
|
||||
@@ -27,11 +27,9 @@ class ResProductMo(models.Model):
|
||||
categ_type = fields.Selection(string='产品的类别', related='categ_id.type', store=True)
|
||||
model_name = fields.Char('模型名称')
|
||||
blank_type = fields.Selection([('圆料', '圆料'), ('方料', '方料')], string='坯料分类')
|
||||
blank_precision = fields.Selection([('精坯', '精坯'), ('粗坯', '粗坯')], string='坯料类型')
|
||||
model_long = fields.Float('模型长(mm)', digits=(16, 3))
|
||||
model_width = fields.Float('模型宽(mm)', digits=(16, 3))
|
||||
model_height = fields.Float('模型高(mm)', digits=(16, 3))
|
||||
unit_number = fields.Float('单件用量', digits=(16, 3), default=1)
|
||||
model_volume = fields.Float('模型体积(m³)')
|
||||
model_area = fields.Float('模型表面积(m²)')
|
||||
model_machining_precision = fields.Selection(selection=_get_machining_precision, string='加工精度')
|
||||
@@ -903,11 +901,9 @@ class ResProductMo(models.Model):
|
||||
vals = {
|
||||
'name': product_name,
|
||||
'blank_type': item.get('blank_type'),
|
||||
'blank_precision': item.get('blank_precision'),
|
||||
'model_long': item.get('blank_length') if blank_bool else self.format_float(item['model_long'] + embryo_redundancy_id.long),
|
||||
'model_width': item.get('blank_width') if blank_bool else self.format_float(item['model_width'] + embryo_redundancy_id.width),
|
||||
'model_height': item.get('blank_height') if blank_bool else self.format_float(item['model_height'] + embryo_redundancy_id.height),
|
||||
'unit_number': item.get('unit_number'),
|
||||
'model_volume': self.format_float(((item['model_long'] + embryo_redundancy_id.long) *
|
||||
(item['model_width'] + embryo_redundancy_id.width) *
|
||||
(item['model_height'] + embryo_redundancy_id.height))) if not blank_bool else (
|
||||
@@ -961,7 +957,7 @@ class ResProductMo(models.Model):
|
||||
self.attachment_update(item['quality_standard_name'], copy_product_id.product_tmpl_id.id,
|
||||
'quality_standard', item['quality_standard_mimetype'])
|
||||
return copy_product_id
|
||||
|
||||
|
||||
def format_float(self, value):
|
||||
# 将浮点数转换为字符串
|
||||
value_str = str(value)
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
|
||||
|
||||
<div class="page" style="min-height: 800px; position: relative; padding-bottom: 250px;">
|
||||
|
||||
|
||||
<table class="table table-sm o_main_table mt-4" style="border: 1px solid black;">
|
||||
<tr>
|
||||
<td style="width: 15%; border: 1px solid black;"><strong>产品名称:</strong></td>
|
||||
@@ -113,7 +113,7 @@
|
||||
<td style="border: 1px solid black;"><span t-field="o.check_qty"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h4 class="text-center mt-4">检验结果</h4>
|
||||
<div class="" style="position: relative;">
|
||||
<table class="table table-sm mt-2" style="border: 1px solid black;">
|
||||
@@ -182,7 +182,7 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="col-6">
|
||||
<p><strong>操作员: </strong> <span t-field="o.measure_operator"/></p>
|
||||
@@ -200,7 +200,7 @@
|
||||
<p></p>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
|
||||
<!-- 页脚固定在底部 -->
|
||||
<!-- <div style="position: absolute; bottom: 0; left: 0; right: 0;"> -->
|
||||
<t t-call="sf_quality.report_quality_footer"/>
|
||||
|
||||
Reference in New Issue
Block a user