diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py
index be81e110..c7ae6ecc 100644
--- a/sf_manufacturing/models/stock.py
+++ b/sf_manufacturing/models/stock.py
@@ -205,39 +205,17 @@ class StockRule(models.Model):
productions_values)
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
- self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
- productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
- (
- p.move_dest_ids.procure_method != 'make_to_order' and not
- p.move_raw_ids and not p.workorder_ids)).action_confirm()
+
'''
创建工单
'''
# productions._create_workorder()
#
- grouped_product_ids = {k: list(g) for k, g in groupby(productions, key=lambda x: x.product_id.id)}
- # 初始化一个字典来存储每个product_id对应的生产订单名称列表
- product_id_to_production_names = {}
- # 对于每个product_id,获取其所有生产订单的名称
- for product_id, productions in grouped_product_ids.items():
- # 为同一个product_id创建一个生产订单名称列表
- product_id_to_production_names[product_id] = [production.name for production in productions]
- for production_item in productions:
- if production_item.product_id.id in product_id_to_production_names:
- # # 同一个产品多个制造订单对应一个编程单和模型库
- # # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
- if not production_item.programming_no:
- production_programming = self.env['mrp.production'].search(
- [('product_id.id', '=', production_item.product_id.id),
- ('origin', '=', production_item.origin)],
- limit=1, order='id asc')
- if not production_programming.programming_no:
- production_item.fetchCNC(
- ', '.join(product_id_to_production_names[production_item.product_id.id]))
- else:
- production_item.write({'programming_no': production_programming.programming_no,
- 'programming_state': '编程中'})
-
+ self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
+ productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
+ (
+ p.move_dest_ids.procure_method != 'make_to_order' and not
+ p.move_raw_ids and not p.workorder_ids)).action_confirm()
for production in productions:
'''
创建制造订单时生成序列号
@@ -283,6 +261,28 @@ class StockRule(models.Model):
'product_id': production.product_id.id,
'state': 'draft',
})
+ grouped_product_ids = {k: list(g) for k, g in groupby(productions, key=lambda x: x.product_id.id)}
+ # 初始化一个字典来存储每个product_id对应的生产订单名称列表
+ product_id_to_production_names = {}
+ # 对于每个product_id,获取其所有生产订单的名称
+ for product_id, productions in grouped_product_ids.items():
+ # 为同一个product_id创建一个生产订单名称列表
+ product_id_to_production_names[product_id] = [production.name for production in productions]
+ for production_item in productions:
+ if production_item.product_id.id in product_id_to_production_names:
+ # # 同一个产品多个制造订单对应一个编程单和模型库
+ # # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
+ if not production_item.programming_no:
+ production_programming = self.env['mrp.production'].search(
+ [('product_id.id', '=', production_item.product_id.id),
+ ('origin', '=', production_item.origin)],
+ limit=1, order='id asc')
+ if not production_programming.programming_no:
+ production_item.fetchCNC(
+ ', '.join(product_id_to_production_names[production_item.product_id.id]))
+ else:
+ production_item.write({'programming_no': production_programming.programming_no,
+ 'programming_state': '编程中'})
return True
diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml
index a2736834..790c0551 100644
--- a/sf_manufacturing/views/mrp_workorder_view.xml
+++ b/sf_manufacturing/views/mrp_workorder_view.xml
@@ -483,7 +483,10 @@
-
+
@@ -729,7 +732,7 @@
-
+、
工件配送
sf.workpiece.delivery
diff --git a/sf_mrs_connect/controllers/controllers.py b/sf_mrs_connect/controllers/controllers.py
index ee2ef3e5..b6d4c659 100644
--- a/sf_mrs_connect/controllers/controllers.py
+++ b/sf_mrs_connect/controllers/controllers.py
@@ -40,7 +40,7 @@ class Sf_Mrs_Connect(http.Controller):
download_state = request.env['sf.cnc.processing'].with_user(
request.env.ref("base.user_admin")).download_file_tmp(
ret['folder_name'], r)
- if download_state == 0:
+ if download_state is False:
res['status'] = -2
res['message'] = '编程单号为%s的CNC程序文件从FTP拉取失败' % (ret['programming_no'])
return json.JSONEncoder().encode(res)
diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py
index 6508132d..f47f8c8d 100644
--- a/sf_sale/models/sale_order.py
+++ b/sf_sale/models/sale_order.py
@@ -171,6 +171,11 @@ class ProductTemplate(models.Model):
class RePurchaseOrder(models.Model):
_inherit = 'purchase.order'
+ mrp_production_count = fields.Integer(
+ "Count of MO Source",
+ compute='_compute_mrp_production_count',
+ groups='mrp.group_mrp_user,sf_base.group_purchase,sf_base.group_purchase_director')
+
remark = fields.Text('备注')
user_id = fields.Many2one(
'res.users', string='买家', index=True, tracking=True,
diff --git a/sf_sale/security/group_security.xml b/sf_sale/security/group_security.xml
index 5f23b5bb..97b6d05d 100644
--- a/sf_sale/security/group_security.xml
+++ b/sf_sale/security/group_security.xml
@@ -54,7 +54,7 @@
销售经理查看自己的订单
- ['|',('user_id','=',user.id),('create_uid', '=',user.id)]
+ ['|','|',('user_id','=',user.id),('user_id', '=', False),('create_uid', '=',user.id)]
@@ -74,7 +74,7 @@
采购岗查看自己的订单
- ['|',('user_id','=',user.id),('create_uid', '=',user.id)]
+ ['|','|',('user_id','=',user.id),('user_id', '=', False),('create_uid', '=',user.id)]
diff --git a/sf_sale/views/purchase_order_view.xml b/sf_sale/views/purchase_order_view.xml
index 85f5b1c8..eda8e59d 100644
--- a/sf_sale/views/purchase_order_view.xml
+++ b/sf_sale/views/purchase_order_view.xml
@@ -79,6 +79,13 @@
sf_base.group_purchase,sf_base.group_purchase_director
+
+
+ mrp.group_mrp_user,sf_base.group_purchase,sf_base.group_purchase_director
+
+
+
{'readonly': [('state', 'in', ['purchase'])]}
diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py
index 61156536..182141cf 100644
--- a/sf_tool_management/models/base.py
+++ b/sf_tool_management/models/base.py
@@ -944,13 +944,11 @@ class FunctionalToolDismantle(models.Model):
functional_tool_assembly = self.functional_tool_id.functional_tool_name_id
if self.scrap_boolean:
# 刀柄报废 入库到Scrap
- lot.create_stock_quant(location, location_dest_scrap_ids[-1], functional_tool_assembly.id, code,
- functional_tool_assembly, functional_tool_assembly.tool_groups_id)
+ lot.create_stock_quant(location, location_dest_scrap_ids[-1], False, code, False, False)
lot.tool_material_status = '报废'
else:
# 刀柄不报废 入库到刀具房
- lot.create_stock_quant(location, location_dest, functional_tool_assembly.id, code,
- functional_tool_assembly, functional_tool_assembly.tool_groups_id)
+ lot.create_stock_quant(location, location_dest, False, code, False, False)
lot.tool_material_status = '可用'
# ==============功能刀具[报废]拆解================
diff --git a/sf_tool_management/models/maintenance_equipment.py b/sf_tool_management/models/maintenance_equipment.py
index d308f1f1..48bc531f 100644
--- a/sf_tool_management/models/maintenance_equipment.py
+++ b/sf_tool_management/models/maintenance_equipment.py
@@ -3,6 +3,7 @@ import requests
import logging
from odoo import models, api, fields
from odoo.exceptions import ValidationError
+from datetime import datetime, timedelta
from odoo.addons.sf_base.commons.common import Common
@@ -101,7 +102,7 @@ class SfMaintenanceEquipment(models.Model):
tool_install_time = {'Nomal': '正常', 'Warning': '报警'}
equipment_tool_id.write({
'functional_tool_name_id': functional_tool_id.id,
- 'tool_install_time': time
+ 'tool_install_time': time - timedelta(hours=8)
})
if functional_tool_id.current_location != '机内刀库':
# 对功能刀具进行移动到生产线
diff --git a/sf_tool_management/models/tool_material_search.py b/sf_tool_management/models/tool_material_search.py
index af8833fb..ededd64f 100644
--- a/sf_tool_management/models/tool_material_search.py
+++ b/sf_tool_management/models/tool_material_search.py
@@ -25,7 +25,8 @@ class ToolMaterial(models.Model):
have_been_used_num = fields.Integer('在用数量', compute='_compute_number', store=True)
scrap_num = fields.Integer('报废数量', compute='_compute_number', store=True)
- barcode_ids = fields.One2many('stock.lot', 'tool_material_search_id', string='序列号', readonly=True)
+ barcode_ids = fields.One2many('stock.lot', 'tool_material_search_id', string='序列号', readonly=True,
+ domain=[('tool_material_status', '!=', '未入库')])
@api.depends('product_id.stock_quant_ids.quantity')
def _compute_number(self):
@@ -46,8 +47,6 @@ class ToolMaterial(models.Model):
record.scrap_num = scrap_num
record.number = usable_num + have_been_used_num + scrap_num
-
-
@api.model
def _read_group_cutting_tool_material_id(self, categories, domain, order):
cutting_tool_material_id = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
diff --git a/sf_tool_management/views/tool_material_search.xml b/sf_tool_management/views/tool_material_search.xml
index 8a740676..ef6209f3 100644
--- a/sf_tool_management/views/tool_material_search.xml
+++ b/sf_tool_management/views/tool_material_search.xml
@@ -63,6 +63,7 @@
+
diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py
index c429a5eb..ee212b2a 100644
--- a/sf_warehouse/models/model.py
+++ b/sf_warehouse/models/model.py
@@ -557,8 +557,10 @@ class SfStockMoveLine(models.Model):
_name = 'stock.move.line'
_inherit = ['stock.move.line', 'printing.utils']
+ stock_lot_name = fields.Char('序列号名称', related='lot_id.name')
current_location_id = fields.Many2one(
- 'sf.shelf.location', string='当前货位', compute='_compute_current_location_id', store=True)
+ 'sf.shelf.location', string='当前货位', compute='_compute_current_location_id', store=True, readonly=False,
+ domain="[('product_id', '=', product_id),'|',('product_sn_id.name', '=', stock_lot_name),('product_sn_ids.lot_id.name','=',stock_lot_name)]")
# location_dest_id = fields.Many2one('stock.location', string='目标库位')
location_dest_id_product_type = fields.Many2many(related='location_dest_id.product_type')
location_dest_id_value = fields.Integer(compute='_compute_location_dest_id_value', store=True)
@@ -856,7 +858,9 @@ class SfStockMoveLine(models.Model):
def compute_destination_location_id(self):
for record in self:
obj = self.env['sf.shelf.location'].search([('name', '=',
- self.destination_location_id.name)])
+ record.destination_location_id.name)])
+ if obj and obj.product_id and obj.product_id != record.product_id:
+ raise ValidationError('目标货位【%s】已被【%s】产品占用!' % (obj.code, obj.product_id))
if record.lot_id:
if record.product_id.tracking == 'serial':
shelf_location_obj = self.env['sf.shelf.location'].search(
@@ -869,7 +873,7 @@ class SfStockMoveLine(models.Model):
if obj:
obj.product_sn_id = record.lot_id.id
elif record.product_id.tracking == 'lot':
- self.put_shelf_location(record)
+ record.put_shelf_location(record)
if not obj.product_id:
obj.product_id = record.product_id.id
else:
@@ -980,15 +984,26 @@ class SfStockPicking(models.Model):
# 调用入库方法进行入库刀货位
line.compute_destination_location_id()
else:
- # 对除刀柄之外的刀具物料进行 目标货位必填校验
+ # 对除刀柄之外的刀具物料入库到刀具房进行 目标货位必填校验
if self.location_dest_id.name == '刀具房' and line.product_id.cutting_tool_material_id.name not in (
'刀柄', False):
raise ValidationError('请选择【%s】产品的目标货位!' % line.product_id.name)
+ if line.current_location_id:
+ # 对货位的批次产品进行出货
+ line.put_shelf_location(line)
+
if line.current_location_id:
+ # 按序列号管理的产品
if line.current_location_id.product_sn_id:
line.current_location_id.product_sn_id = False
# line.current_location_id.location_status = '空闲'
line.current_location_id.product_num = 0
+ line.current_location_id.product_id = False
+ else:
+ # 对除刀柄之外的刀具物料从刀具房出库进行 当前货位必填校验
+ if self.location_id.name == '刀具房' and line.product_id.cutting_tool_material_id.name not in (
+ '刀柄', False):
+ raise ValidationError('请选择【%s】产品的当前货位!' % line.product_id.name)
# 对入库作业的刀柄和托盘进行Rfid绑定校验
for move in self.move_ids:
@@ -1115,6 +1130,7 @@ class CustomStockMove(models.Model):
采购入库扫码绑定Rfid码
"""
for record in self:
+ logging.info('Rfid:%s' % barcode)
if record:
lot = self.env['stock.lot'].sudo().search([('rfid', '=', barcode)])
if lot:
@@ -1126,7 +1142,9 @@ class CustomStockMove(models.Model):
'该Rfid【%s】已经被序列号为【%s】的【%s】物料所占用!' % (barcode, lot.name, material))
if '刀柄' in (record.product_id.cutting_tool_material_id.name or '') or '托盘' in (
record.product_id.fixture_material_id.name or ''):
+ logging.info('开始录入Rfid:%s' % record.move_line_nosuggest_ids)
for move_line_nosuggest_id in record.move_line_nosuggest_ids:
+ logging.info('录入的记录%s , Rfid:%s' % (move_line_nosuggest_id, move_line_nosuggest_id.rfid))
if move_line_nosuggest_id.rfid:
if move_line_nosuggest_id.rfid == barcode:
if record.product_id.cutting_tool_material_id.name:
@@ -1135,7 +1153,9 @@ class CustomStockMove(models.Model):
raise ValidationError('该托盘的Rfid已经录入,请勿重复录入!!!')
else:
line_id = int(re.sub(r"\D", "", str(move_line_nosuggest_id.id)))
- self.env['stock.move.line'].sudo().search([('id', '=', line_id)]).write({'rfid': barcode})
+ res = self.env['stock.move.line'].sudo().search([('id', '=', line_id)]).write(
+ {'rfid': barcode})
+ logging.info('Rfid是否录入:%s' % res)
move_line_nosuggest_id.rfid = barcode
break
else:
diff --git a/sf_warehouse/views/change_stock_move_views.xml b/sf_warehouse/views/change_stock_move_views.xml
index a77b916c..29d09926 100644
--- a/sf_warehouse/views/change_stock_move_views.xml
+++ b/sf_warehouse/views/change_stock_move_views.xml
@@ -7,16 +7,18 @@
-
+
+
-
-
-
-
-
+
+
+
+
+
@@ -55,6 +57,7 @@
+
diff --git a/web_gantt/static/src/js/gantt_row.js b/web_gantt/static/src/js/gantt_row.js
index 420e3ad5..fb7ffab7 100644
--- a/web_gantt/static/src/js/gantt_row.js
+++ b/web_gantt/static/src/js/gantt_row.js
@@ -592,8 +592,23 @@ var GanttRow = Widget.extend({
});
pill.decorations = pillDecorations;
- if (self.colorField) {
- pill._color = self._getColor(pill[self.colorField]);
+ // let isDelay = false
+ // if(pill.state != 'processing' && pill.state != 'finished') { // 判断待加工
+ // isDelay = pill.order_deadline.isBefore(new Date())
+ // }
+ pill.exState = ''
+ if (self.colorField){
+ // console.log(self.colorField, self, pill, '颜色')
+ // pill._color = self._getColor(pill[self.colorField]);
+ // 设置pill背景颜色2 修改时间2024年6月25日17:09:43
+ let isDelay = false
+ if(pill.state != 'processing' && pill.state != 'finished') { // 判断待加工
+ isDelay = pill.order_deadline.isBefore(new Date())
+ }
+ if(isDelay) {
+ pill.disableDragdrop = true
+ }
+ pill._color = self._getColor2(isDelay ? 'delay' : pill.state);
}
if (self.progressField) {
@@ -613,6 +628,13 @@ var GanttRow = Widget.extend({
}
return 0;
},
+ _getColor2 (state) {
+ return {
+ 'finished': 'ccc',
+ 'delay': 9,
+ 'processing': 13 // 绿色
+ }[state]
+ },
/**
* Get context to evaluate decoration
*
@@ -867,10 +889,11 @@ var GanttRow = Widget.extend({
if ($pill.hasClass('ui-draggable-dragging')) {
return;
}
-
var self = this;
var pill = _.findWhere(this.pills, { id: $pill.data('id') });
-
+ if(pill.state == 'finished'){ // 已完成状态不能拖拽
+ return;
+ }
// DRAGGABLE
if (this.options.canEdit && !pill.disableStartResize && !pill.disableStopResize && !this.isGroup) {
diff --git a/web_gantt/static/src/scss/web_gantt.scss b/web_gantt/static/src/scss/web_gantt.scss
index 7dbca3e3..bc48bee5 100644
--- a/web_gantt/static/src/scss/web_gantt.scss
+++ b/web_gantt/static/src/scss/web_gantt.scss
@@ -754,3 +754,7 @@
left: -0.5 * $o-connector-creator-bullet-diameter;
}
}
+
+.o_gantt_view .o_gantt_row_nogroup .o_gantt_pill.o_gantt_color_ccc {
+ background-color: #ccc;
+}
\ No newline at end of file