diff --git a/sf_demand_plan/__manifest__.py b/sf_demand_plan/__manifest__.py index 0496cad2..08c981cb 100644 --- a/sf_demand_plan/__manifest__.py +++ b/sf_demand_plan/__manifest__.py @@ -31,7 +31,6 @@ 'sf_demand_plan/static/src/scss/style.css', 'sf_demand_plan/static/src/js/print_demand.js', 'sf_demand_plan/static/src/js/custom_button.js', - 'sf_demand_plan/static/src/js/global_button_protection.js', ] }, 'license': 'LGPL-3', diff --git a/sf_demand_plan/models/purchase_order.py b/sf_demand_plan/models/purchase_order.py index b9802866..ea6d6372 100644 --- a/sf_demand_plan/models/purchase_order.py +++ b/sf_demand_plan/models/purchase_order.py @@ -36,7 +36,7 @@ class PurchaseOrderLine(models.Model): @api.model def create(self, 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(',')] if self.env.context.get('demand_plan_line_id'): res.demand_plan_line_id = self.env.context.get('demand_plan_line_id') diff --git a/sf_demand_plan/models/sf_production_demand_plan.py b/sf_demand_plan/models/sf_production_demand_plan.py index 234546b0..f0a35792 100644 --- a/sf_demand_plan/models/sf_production_demand_plan.py +++ b/sf_demand_plan/models/sf_production_demand_plan.py @@ -17,7 +17,7 @@ class SfProductionDemandPlan(models.Model): customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers') 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([ ('10', '草稿'), ('20', '待确认'), @@ -34,7 +34,7 @@ class SfProductionDemandPlan(models.Model): company_id = fields.Many2one( related='sale_order_id.company_id', 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', string="订单备注", store=True) 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') unit_number = fields.Float('单件用量', digits=(16, 3), related='product_id.unit_number') 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_process_parameters_ids = fields.Many2many(related='demand_plan_id.model_process_parameters_ids', string='表面工艺', ) @@ -127,6 +127,12 @@ class SfProductionDemandPlan(models.Model): string='字段自制类型只读' ) + is_processing = fields.Boolean( + string='正在处理中', + default=False, + help='用于防止重复点击按钮' + ) + # hide_action_open_mrp_production = fields.Boolean( # string='显示待工艺确认按钮', # compute='_compute_hid_button', @@ -652,6 +658,9 @@ class SfProductionDemandPlan(models.Model): def button_release_plan(self): self.ensure_one() + if self.is_processing: + return + self.is_processing = True check_overdelivery_allowed = False if not self.demand_plan_id.overdelivery_allowed: customer_location_id = self.env['ir.model.data']._xmlid_to_res_id('stock.stock_location_customers') diff --git a/sf_demand_plan/static/src/js/global_button_protection.js b/sf_demand_plan/static/src/js/global_button_protection.js deleted file mode 100644 index 530028f4..00000000 --- a/sf_demand_plan/static/src/js/global_button_protection.js +++ /dev/null @@ -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(); -} \ No newline at end of file diff --git a/sf_demand_plan/wizard/sf_demand_plan_print_wizard.py b/sf_demand_plan/wizard/sf_demand_plan_print_wizard.py index 8d3a27b4..3fa7c55f 100644 --- a/sf_demand_plan/wizard/sf_demand_plan_print_wizard.py +++ b/sf_demand_plan/wizard/sf_demand_plan_print_wizard.py @@ -37,7 +37,7 @@ class SfDemandPlanPrintWizard(models.TransientModel): if pdf_data: try: # 执行打印 - self.env['jikimo.printing'].sudo().print_pdf(pdf_data) + # self.env['jikimo.printing'].sudo().print_pdf(pdf_data) record.status = 'success' production_demand_plan_id = self.env['sf.production.demand.plan'].sudo().search( [('model_id', '=', record.model_id)]) diff --git a/sf_demand_plan/wizard/sf_release_plan_wizard.py b/sf_demand_plan/wizard/sf_release_plan_wizard.py index 42f85819..431eeb92 100644 --- a/sf_demand_plan/wizard/sf_release_plan_wizard.py +++ b/sf_demand_plan/wizard/sf_release_plan_wizard.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import logging from odoo import models, fields, api, _ +from werkzeug.exceptions import InternalServerError _logger = logging.getLogger(__name__) @@ -17,4 +18,10 @@ class SfReleasePlanWizard(models.TransientModel): def confirm(self): if 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)