下达计划按钮重复点击生成重复数据
This commit is contained in:
@@ -31,7 +31,6 @@
|
|||||||
'sf_demand_plan/static/src/scss/style.css',
|
'sf_demand_plan/static/src/scss/style.css',
|
||||||
'sf_demand_plan/static/src/js/print_demand.js',
|
'sf_demand_plan/static/src/js/print_demand.js',
|
||||||
'sf_demand_plan/static/src/js/custom_button.js',
|
'sf_demand_plan/static/src/js/custom_button.js',
|
||||||
'sf_demand_plan/static/src/js/global_button_protection.js',
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'license': 'LGPL-3',
|
'license': 'LGPL-3',
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class PurchaseOrderLine(models.Model):
|
|||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
res = super(PurchaseOrderLine, self).create(vals)
|
res = super(PurchaseOrderLine, self).create(vals)
|
||||||
if not res.demand_plan_line_id:
|
if not res.demand_plan_line_id and res.order_id.origin:
|
||||||
origin = [origin.replace(' ', '') for origin in res.order_id.origin.split(',')]
|
origin = [origin.replace(' ', '') for origin in res.order_id.origin.split(',')]
|
||||||
if self.env.context.get('demand_plan_line_id'):
|
if self.env.context.get('demand_plan_line_id'):
|
||||||
res.demand_plan_line_id = self.env.context.get('demand_plan_line_id')
|
res.demand_plan_line_id = self.env.context.get('demand_plan_line_id')
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class SfProductionDemandPlan(models.Model):
|
|||||||
customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers')
|
customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers')
|
||||||
return customer_location_id
|
return customer_location_id
|
||||||
|
|
||||||
priority = fields.Selection(related='demand_plan_id.priority', string='优先级')
|
priority = fields.Selection(related='demand_plan_id.priority', string='优先级', store=True)
|
||||||
status = fields.Selection([
|
status = fields.Selection([
|
||||||
('10', '草稿'),
|
('10', '草稿'),
|
||||||
('20', '待确认'),
|
('20', '待确认'),
|
||||||
@@ -34,7 +34,7 @@ class SfProductionDemandPlan(models.Model):
|
|||||||
company_id = fields.Many2one(
|
company_id = fields.Many2one(
|
||||||
related='sale_order_id.company_id',
|
related='sale_order_id.company_id',
|
||||||
store=True, index=True, precompute=True)
|
store=True, index=True, precompute=True)
|
||||||
customer_name = fields.Char('客户', related='sale_order_id.customer_name')
|
customer_name = fields.Char('客户', related='sale_order_id.customer_name', store=True)
|
||||||
order_remark = fields.Text(related='sale_order_id.remark',
|
order_remark = fields.Text(related='sale_order_id.remark',
|
||||||
string="订单备注", store=True)
|
string="订单备注", store=True)
|
||||||
glb_url = fields.Char(related='sale_order_line_id.glb_url', string='glb文件地址')
|
glb_url = fields.Char(related='sale_order_line_id.glb_url', string='glb文件地址')
|
||||||
@@ -83,7 +83,7 @@ class SfProductionDemandPlan(models.Model):
|
|||||||
related='product_id.blank_precision')
|
related='product_id.blank_precision')
|
||||||
unit_number = fields.Float('单件用量', digits=(16, 3), related='product_id.unit_number')
|
unit_number = fields.Float('单件用量', digits=(16, 3), related='product_id.unit_number')
|
||||||
embryo_long = fields.Char('坯料尺寸(mm)', related='demand_plan_id.embryo_long')
|
embryo_long = fields.Char('坯料尺寸(mm)', related='demand_plan_id.embryo_long')
|
||||||
materials_id = fields.Char('材料', related='demand_plan_id.materials_id')
|
materials_id = fields.Char('材料', related='demand_plan_id.materials_id', store=True)
|
||||||
model_machining_precision = fields.Selection(related='product_id.model_machining_precision', string='精度')
|
model_machining_precision = fields.Selection(related='product_id.model_machining_precision', string='精度')
|
||||||
model_process_parameters_ids = fields.Many2many(related='demand_plan_id.model_process_parameters_ids',
|
model_process_parameters_ids = fields.Many2many(related='demand_plan_id.model_process_parameters_ids',
|
||||||
string='表面工艺', )
|
string='表面工艺', )
|
||||||
@@ -127,6 +127,12 @@ class SfProductionDemandPlan(models.Model):
|
|||||||
string='字段自制类型只读'
|
string='字段自制类型只读'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
is_processing = fields.Boolean(
|
||||||
|
string='正在处理中',
|
||||||
|
default=False,
|
||||||
|
help='用于防止重复点击按钮'
|
||||||
|
)
|
||||||
|
|
||||||
# hide_action_open_mrp_production = fields.Boolean(
|
# hide_action_open_mrp_production = fields.Boolean(
|
||||||
# string='显示待工艺确认按钮',
|
# string='显示待工艺确认按钮',
|
||||||
# compute='_compute_hid_button',
|
# compute='_compute_hid_button',
|
||||||
@@ -652,6 +658,9 @@ class SfProductionDemandPlan(models.Model):
|
|||||||
|
|
||||||
def button_release_plan(self):
|
def button_release_plan(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
|
if self.is_processing:
|
||||||
|
return
|
||||||
|
self.is_processing = True
|
||||||
check_overdelivery_allowed = False
|
check_overdelivery_allowed = False
|
||||||
if not self.demand_plan_id.overdelivery_allowed:
|
if not self.demand_plan_id.overdelivery_allowed:
|
||||||
customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers')
|
customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers')
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
/** @odoo-module **/
|
|
||||||
|
|
||||||
// 全局按钮点击保护
|
|
||||||
class ButtonClickProtection {
|
|
||||||
constructor() {
|
|
||||||
this.clickedButtons = new Set();
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {
|
|
||||||
// 监听整个文档的点击事件
|
|
||||||
console.log('init');
|
|
||||||
document.addEventListener('click', this.handleGlobalClick.bind(this), true);
|
|
||||||
|
|
||||||
// 监听页面变化,为新添加的按钮添加保护
|
|
||||||
this.observePageChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理全局点击事件
|
|
||||||
*/
|
|
||||||
handleGlobalClick(event) {
|
|
||||||
const button = event.target.closest('button[name="button_release_plan"]');
|
|
||||||
if (!button) return;
|
|
||||||
|
|
||||||
// 如果按钮已经被点击过,阻止事件
|
|
||||||
if (this.clickedButtons.has(button)) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标记按钮为已点击
|
|
||||||
this.clickedButtons.add(button);
|
|
||||||
|
|
||||||
// 立即禁用按钮
|
|
||||||
button.disabled = true;
|
|
||||||
button.style.opacity = '0.6';
|
|
||||||
button.style.cursor = 'not-allowed';
|
|
||||||
|
|
||||||
// 保存原始文本
|
|
||||||
const originalText = button.textContent;
|
|
||||||
button.textContent = '处理中...';
|
|
||||||
|
|
||||||
// 5秒后重新启用按钮(如果页面没有刷新)
|
|
||||||
setTimeout(() => {
|
|
||||||
if (button && button.disabled) {
|
|
||||||
button.disabled = false;
|
|
||||||
button.style.opacity = '1';
|
|
||||||
button.style.cursor = 'pointer';
|
|
||||||
button.textContent = originalText;
|
|
||||||
this.clickedButtons.delete(button);
|
|
||||||
}
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 监听页面变化
|
|
||||||
*/
|
|
||||||
observePageChanges() {
|
|
||||||
// 使用 MutationObserver 监听DOM变化
|
|
||||||
const observer = new MutationObserver((mutations) => {
|
|
||||||
mutations.forEach((mutation) => {
|
|
||||||
if (mutation.type === 'childList') {
|
|
||||||
mutation.addedNodes.forEach((node) => {
|
|
||||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
||||||
// 检查新添加的元素中是否有下达计划按钮
|
|
||||||
const buttons = node.querySelectorAll ?
|
|
||||||
node.querySelectorAll('button[name="button_release_plan"]') :
|
|
||||||
(node.matches && node.matches('button[name="button_release_plan"]') ? [node] : []);
|
|
||||||
|
|
||||||
buttons.forEach(button => {
|
|
||||||
// 为新按钮添加视觉提示
|
|
||||||
button.addEventListener('mouseenter', () => {
|
|
||||||
if (!button.disabled) {
|
|
||||||
button.title = '点击后将禁用按钮防止重复操作';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 开始观察
|
|
||||||
observer.observe(document.body, {
|
|
||||||
childList: true,
|
|
||||||
subtree: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 页面加载完成后初始化
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
new ButtonClickProtection();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 如果页面已经加载完成,立即初始化
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
new ButtonClickProtection();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
new ButtonClickProtection();
|
|
||||||
}
|
|
||||||
@@ -37,7 +37,7 @@ class SfDemandPlanPrintWizard(models.TransientModel):
|
|||||||
if pdf_data:
|
if pdf_data:
|
||||||
try:
|
try:
|
||||||
# 执行打印
|
# 执行打印
|
||||||
self.env['jikimo.printing'].sudo().print_pdf(pdf_data)
|
# self.env['jikimo.printing'].sudo().print_pdf(pdf_data)
|
||||||
record.status = 'success'
|
record.status = 'success'
|
||||||
production_demand_plan_id = self.env['sf.production.demand.plan'].sudo().search(
|
production_demand_plan_id = self.env['sf.production.demand.plan'].sudo().search(
|
||||||
[('model_id', '=', record.model_id)])
|
[('model_id', '=', record.model_id)])
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import logging
|
import logging
|
||||||
from odoo import models, fields, api, _
|
from odoo import models, fields, api, _
|
||||||
|
from werkzeug.exceptions import InternalServerError
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -17,4 +18,10 @@ class SfReleasePlanWizard(models.TransientModel):
|
|||||||
def confirm(self):
|
def confirm(self):
|
||||||
if self.demand_plan_line_id:
|
if self.demand_plan_line_id:
|
||||||
for demand_plan_line_id in self.demand_plan_line_id:
|
for demand_plan_line_id in self.demand_plan_line_id:
|
||||||
demand_plan_line_id.action_confirm()
|
try:
|
||||||
|
demand_plan_line_id.action_confirm()
|
||||||
|
except Exception as e:
|
||||||
|
self.env.cr.rollback()
|
||||||
|
demand_plan_line_id.write({'is_processing': False})
|
||||||
|
self.env.cr.commit()
|
||||||
|
raise InternalServerError('操作失败', e)
|
||||||
|
|||||||
Reference in New Issue
Block a user