Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/优化制造功能

This commit is contained in:
mgw
2024-09-14 14:32:55 +08:00
13 changed files with 73 additions and 50 deletions

View File

@@ -1,3 +1,4 @@
import traceback
from datetime import datetime
import logging
import requests
@@ -53,11 +54,14 @@ class StatusChange(models.Model):
if not ret.get('error'):
logging.info('接口已经执行=============')
else:
logging.error('工厂加工同步订单状态失败 {}'.format(ret))
raise UserError('工厂加工同步订单状态失败')
traceback_error = traceback.format_exc()
logging.error("bfm订单状态同步失败:%s request info %s" % traceback_error)
logging.error('/api/get/state/get_order 请求失败{}'.format(ret))
raise UserError('工厂加工同步订单状态到bfm失败')
except UserError as e:
logging.error('工厂加工同步订单状态失败 {}'.format(e))
raise UserError('工厂加工同步订单状态失败')
traceback_error = traceback.format_exc()
logging.error("工厂加工同步订单状态失败:%s " % traceback_error)
raise UserError(e)
return res
def action_cancel(self):

View File

@@ -45,7 +45,6 @@
'sf_manufacturing/static/src/scss/kanban_change.scss',
'sf_manufacturing/static/src/xml/button_show_on_tree.xml',
'sf_manufacturing/static/src/js/workpiece_delivery_wizard_confirm.js',
'sf_manufacturing/static/src/js/custom_barcode_handlers.js',
]
},

View File

@@ -1,10 +1,10 @@
import logging
import requests
from odoo import models, fields, api, _
from odoo.exceptions import UserError
import logging
_logger = logging.getLogger(__name__)
@@ -54,7 +54,7 @@ class AgvScheduling(models.Model):
def web_search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, count_limit=None):
domain = domain or []
new_domain = []
for index, item in enumerate(domain):
for item in domain:
if isinstance(item, list):
if item[0] == 'delivery_workpieces':
new_domain.append('&')
@@ -63,7 +63,7 @@ class AgvScheduling(models.Model):
continue
new_domain.append(item)
return super(AgvScheduling, self).web_search_read(new_domain, fields, limit=limit, offset=offset)
return super(AgvScheduling, self).web_search_read(new_domain, fields, offset, limit, order, count_limit)
@api.depends('task_completion_time', 'task_delivery_time')
def _compute_task_duration(self):

View File

@@ -318,8 +318,10 @@ class MrpProduction(models.Model):
# cnc程序获取
def fetchCNC(self, production_names):
cnc = self.env['mrp.production'].search([('id', '=', self.id)])
quick_order = self.env['quick.easy.order'].search(
[('name', '=', cnc.product_id.default_code.rsplit('-', 1)[0])])
quick_order = False
if cnc.product_id.default_code:
quick_order = self.env['quick.easy.order'].search(
[('name', '=', cnc.product_id.default_code.rsplit('-', 1)[0])])
programme_way = False
if cnc.manual_quotation is True:
programme_way = 'manual operation'

View File

@@ -222,7 +222,7 @@ class ResMrpWorkOrder(models.Model):
material_width = fields.Float(string='')
material_height = fields.Float(string='')
# 零件图号
part_number = fields.Char(string='零件图号')
part_number = fields.Char(related='production_id.part_number', string='零件图号')
# 工序状态
process_state = fields.Selection([
('待装夹', '待装夹'),

View File

@@ -267,6 +267,10 @@ class StockRule(models.Model):
workorder_duration += workorder.duration_expected
sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)])
# 根据销售订单号查询快速订单
quick_easy_order = self.env['quick.easy.order'].sudo().search([('sale_order_id', '=', sale_order.id)])
production.write({'part_number': quick_easy_order.part_drawing_number,
'part_drawing': quick_easy_order.machining_drawings})
if sale_order:
# sale_order.write({'schedule_status': 'to schedule'})
self.env['sf.production.plan'].sudo().with_company(company_id).create({
@@ -288,6 +292,7 @@ class StockRule(models.Model):
# 为同一个product_id创建一个生产订单名称列表
product_id_to_production_names[product_id] = [production.name for production in all_production]
for production_item in productions:
production_programming = self.env['mrp.production'].search(
[('product_id.id', '=', production_item.product_id.id),
('origin', '=', production_item.origin)],

View File

@@ -14,7 +14,7 @@
<group col="1">
<field name="production_ids" readonly="1" widget="many2many_tags" string="制造订单号"/>
<field name="delivery_type" readonly="1"/>
<field name="feeder_station_start_id" options="{'no_create': True}" required="1"/>
<field name="feeder_station_start_id" string="当前接驳站" options="{'no_create': True}" required="1"/>
<field name="workcenter_id" options="{'no_create': True}"/>
</group>
<footer>

View File

@@ -6,6 +6,7 @@ from datetime import datetime
from odoo import fields, models
# from odoo.exceptions import ValidationError
from odoo.exceptions import UserError
from datetime import datetime, timedelta
_logger = logging.getLogger(__name__)
@@ -17,7 +18,7 @@ class Action_Plan_All_Wizard(models.TransientModel):
# 选择生产线
production_line_id = fields.Many2one('sf.production.line', string=u'生产线', required=True)
date_planned_start = fields.Datetime(string='计划开始时间', index=True, copy=False,
default=fields.Datetime.now)
default=datetime.now() + timedelta(minutes=10))
# 接收传递过来的计划ID
plan_ids = fields.Many2many('sf.production.plan', string=u'计划ID')

View File

@@ -1505,29 +1505,26 @@ class FunctionalToolDismantle(models.Model):
'handle_code_id': self.handle_lot_id.id,
'handle_product_id': self.handle_product_id.id,
'loading_task_source': '3',
'use_tool_time': fields.Datetime.now() + timedelta(hours=4),
'reason_for_applying': '刀具寿命到期'
})
action = self.env.ref('sf_tool_management.sf_functional_tool_assembly_form')
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': '组装单创建完成',
'message': '请组装同名称的功能刀具',
'type': 'info',
'links': [{
'label': '组装单',
'url': f'#action={action.id}&id={assembly_id.id}&model=sf.functional.tool.assembly',
}],
},
'type': 'ir.actions.act_window',
'res_model': 'sf.functional.tool.assembly',
'view_type': 'form',
'view_mode': 'form',
'res_id': assembly_id.id,
# 'target': 'new'
}
# {
# 'type': 'ir.actions.act_window',
# 'res_model': 'sf.functional.tool.assembly',
# 'view_type': 'form',
# 'view_mode': 'form',
# 'res_id': assembly_id.id,
# 'type': 'ir.actions.client',
# 'tag': 'display_notification',
# 'params': {
# 'title': '组装单创建完成',
# 'message': '请组装同名称的功能刀具',
# 'type': 'info'
# }
# }
# 'params': {

View File

@@ -30,9 +30,23 @@ class jikimo_bom(models.Model):
return result
def check_types_in_list(self):
# 统计每个元素的类型
type_counts = Counter(item.cutting_tool_material_id.name for item in self.product_ids)
return all(count > 0 for count in type_counts.values()) and len(type_counts) == self.options.split('+')
"""
检查产品列表中的元素是否包含了所有指定的类型,并且每种类型至少出现一次。
:return: 如果条件满足返回True否则返回False
"""
if not self.product_ids:
return False
try:
# 统计每个类型的出现次数
type_counts = Counter(item.cutting_tool_material_id.name for item in self.product_ids)
# 检查是否每种类型的出现次数都大于0并且类型的数量与选项字符串中的数量相等
return all(count > 0 for count in type_counts.values()) and len(type_counts) == len(self.options.split('+'))
except AttributeError:
# 如果出现属性错误,说明产品列表中的元素可能缺少必要的属性
return False
# type_counts = Counter(item.cutting_tool_material_id.name for item in self.product_ids)
# return all(count > 0 for count in type_counts.values()) and len(type_counts) == self.options.split('+')
def write(self, vals):
# 在更新模型时记录旧的 Many2many ID 列表
@@ -47,9 +61,15 @@ class jikimo_bom(models.Model):
return True
else:
raise UserError('每种物料最少要有一个')
return True
return super(jikimo_bom, self).write(vals)
def bom_product_domains(self, assembly_options):
"""
根据装配选项生成产品域列表
:param assembly_options: 装配选项字符串,各选项以'+'分隔
:return: 动态生成的产品搜索条件
"""
self.options = assembly_options
cutting_tool_materials = self.env['sf.cutting.tool.material'].search(
[('name', 'in', assembly_options.split('+'))])
@@ -82,23 +102,22 @@ class jikimo_bom(models.Model):
domains = domains + domain
if index != 0:
domains = ['|'] + domains
# wqwqwe = self.env['product.product'].search(ddd)
# product = self.env['product.product'].search(domain)
# if product:
# products = products + product
domains = domains + [('stock_move_count', '>', 0)]
return domains
def generate_bill_materials(self, assembly_options):
"""
生成物料清单
根据装配选项生成物料清单首先获取产品领域然后搜索相关产品并设置产品ID。
:param assembly_options: 组装方式
:type assembly_options: 装配选项字符串,各选项以'+'分隔
"""
domains = self.bom_product_domains(assembly_options)
products = self.env['product.product'].search(domains)
if products:
self.product_ids = [Command.set(products.ids)]
# if option.name == '刀盘':
# hilt = self.env['product.product'].search(
# [('cutting_tool_blade_diameter', '=', self.tool_inventory_id.diameter),
# ('cutting_tool_material_id', '=', option.id)])
# self.product_ids = [Command.set(hilt.ids)]k
class jikimo_bom_line(models.Model):

View File

@@ -14,10 +14,7 @@ class ToolInventory(models.Model):
self._bom_mainfest()
return self.bom_mainfest()
request.session['jikimo_bom_product'] = {'bom_id': int(self.jikimo_bom_ids)}
# context = dict(self.env.context)
# context.update({'jikimo_bom_product': self.jikimo_bom_ids.options})
# if self.functional_cutting_tool_model_id.cutting_tool_type_ids:
# context.update({'jikimo_bom_product_cutting_tool_type': self.functional_cutting_tool_model_id.cutting_tool_type_ids.ids})
return {
'type': 'ir.actions.act_window',
'name': '刀具组装清单',
@@ -26,7 +23,6 @@ class ToolInventory(models.Model):
'view_id': self.env.ref('sf_tool_management.view_jikimo_bom_form').id,
'res_id': int(self.jikimo_bom_ids),
'target': 'current', # Use 'new' to open in a new window/tab
# {'jikimo_bom_product': self.jikimo_bom_ids.options}
}
# 创建bom单

View File

@@ -891,7 +891,8 @@
<group attrs="{'invisible': [('dismantle_cause', 'not in', ['寿命到期报废','崩刀报废'])]}">
<!-- <group col="3">-->
<group>
<field name="scrap_boolean" string="是否报废" readonly="0"/>
<field name="scrap_boolean" string="是否报废"
attrs="{'readonly': [('state' , '=', '已拆解')]}"/>
</group>
<!-- <group></group>-->
<!-- <group>-->

View File

@@ -15,7 +15,6 @@ class JikimoBomWizard(models.TransientModel):
('刀柄+刀杆+刀片', '刀柄+刀杆+刀片'),
('刀柄+刀盘+刀片', '刀柄+刀盘+刀片')
], string='组装方式', required=True)
# assembly_options_ids = fields.Many2many('sf.cutting.tool.material', string="组装方式")
is_ok = fields.Boolean('确认上述信息正确无误。')
def submit(self):