[IMP] sale_order_batch: add cancel and set to open

This commit is contained in:
Niels Göttsch 2025-09-30 17:15:36 +02:00 committed by Niels Göttsch
parent 426d617446
commit 8af3f6be79
9 changed files with 166 additions and 12 deletions

View file

@ -1 +1,2 @@
from . import models from . import models
from . import wizard

View file

@ -7,13 +7,14 @@
"version": "16.0.2.3.0", "version": "16.0.2.3.0",
"depends": ["sale", "product"], "depends": ["sale", "product"],
"data": [ "data": [
"data/ir_sequence_data.xml", "security/ir.model.access.csv",
"security/ir_rules.xml",
"views/sale_order_batch_views.xml", "views/sale_order_batch_views.xml",
"views/sale_order_batch_product_views.xml", "views/sale_order_batch_product_views.xml",
"views/sale_order_views.xml", "views/sale_order_views.xml",
"views/sale_menus.xml", "views/sale_menus.xml",
"security/ir.model.access.csv", "wizard/sale_order_batch_cancel_wizard.xml",
"security/ir_rules.xml", "data/ir_sequence_data.xml",
], ],
"license": "LGPL-3", "license": "LGPL-3",
} }

View file

@ -11,6 +11,10 @@ class SaleOrder(models.Model):
check_company=True, check_company=True,
domain="[('state','!=','closed')]", domain="[('state','!=','closed')]",
) )
batch_state = fields.Selection(
related="batch_id.state",
string="Batch State",
)
def _get_current_batch(self): def _get_current_batch(self):
""" """

View file

@ -1,4 +1,5 @@
from odoo import _, api, fields, models from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.addons.sale.models.sale_order import INVOICE_STATUS from odoo.addons.sale.models.sale_order import INVOICE_STATUS
@ -185,13 +186,37 @@ class SaleOrderBatch(models.Model):
return True return True
def action_cancel(self): def action_cancel(self):
for batch in self: cancel_warning = self._show_cancel_wizard()
orders = batch.sale_order_ids if cancel_warning:
# use _action_cancel to skip the wizzard self.ensure_one()
# ToDo: Implement wizard logic return {
orders._action_cancel() "name": _("Cancel %s", self.name),
batch.update({"state": "cancel"}) "view_mode": "form",
return True "type": "ir.actions.act_window",
"res_model": "sale.order.batch.cancel.wizard",
"target": "new",
"context": {"active_ids": self.ids},
}
else:
self._action_cancel()
def _action_cancel(self):
orders = self.mapped("sale_order_ids")
# use _action_cancel to skip the wizzard
orders._action_cancel()
self.write({"state": "cancel"})
def _show_cancel_wizard(self):
"""Decide whether the sale.order.batch.cancel wizard should be shown to cancel specified orders.
:return: True if there is any non-draft order in the given orders
:rtype: bool
"""
if self.env.context.get("disable_cancel_warning"):
return False
batch_orders = self.mapped("sale_order_ids")
return any(order._show_cancel_wizard() for order in batch_orders)
def action_open(self): def action_open(self):
for batch in self: for batch in self:
@ -210,3 +235,29 @@ class SaleOrderBatch(models.Model):
"sale.order.batch" "sale.order.batch"
) or _("New") ) or _("New")
return super().create(vals_list) return super().create(vals_list)
class SaleOrderBatchCancelWizard(models.TransientModel):
_name = "sale.order.batch.cancel.wizard"
_description = "Sale Order Batch Cancel Wizard"
def action_cancel(self):
batches = self.env["sale.order.batch"].browse(self._context["active_ids"])
for batch in batches:
orders = batch.sale_order_ids
# Warn if any sale order is not in draft
not_draft_orders = orders.filtered(lambda o: o.state != "draft")
if not_draft_orders:
raise UserError(
_(
"You can only cancel batches where all sale orders are in draft state."
)
)
# use _action_cancel to skip the wizzard
# ToDo: Implement wizard logic
orders._action_cancel()
batch.update({"state": "cancel"})
return True
def action_discard(self):
return {"type": "ir.actions.act_window_close"}

View file

@ -3,3 +3,4 @@ access_sale_order_batch_invoicing_payments,sale.order.batch,model_sale_order_bat
access_sale_order_batch,sale.order.batch,model_sale_order_batch,sales_team.group_sale_salesman,1,1,1,0 access_sale_order_batch,sale.order.batch,model_sale_order_batch,sales_team.group_sale_salesman,1,1,1,0
access_sale_order_batch_manager,sale.order.batch.manager,model_sale_order_batch,sales_team.group_sale_manager,1,1,1,1 access_sale_order_batch_manager,sale.order.batch.manager,model_sale_order_batch,sales_team.group_sale_manager,1,1,1,1
access_sale_order_batch_product,sale.order.batch.product,model_sale_order_batch_product,sales_team.group_sale_salesman,1,1,1,1 access_sale_order_batch_product,sale.order.batch.product,model_sale_order_batch_product,sales_team.group_sale_salesman,1,1,1,1
sale_order_batch.access_sale_order_batch_cancel_wizard,access_sale_order_batch_cancel_wizard,sale_order_batch.model_sale_order_batch_cancel_wizard,base.group_user,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 access_sale_order_batch sale.order.batch model_sale_order_batch sales_team.group_sale_salesman 1 1 1 0
4 access_sale_order_batch_manager sale.order.batch.manager model_sale_order_batch sales_team.group_sale_manager 1 1 1 1
5 access_sale_order_batch_product sale.order.batch.product model_sale_order_batch_product sales_team.group_sale_salesman 1 1 1 1
6 sale_order_batch.access_sale_order_batch_cancel_wizard access_sale_order_batch_cancel_wizard sale_order_batch.model_sale_order_batch_cancel_wizard base.group_user 1 1 1 1

View file

@ -10,6 +10,13 @@
<field name="company_id" groups="base.group_multi_company" optional="show" readonly="1"/> <field name="company_id" groups="base.group_multi_company" optional="show" readonly="1"/>
<field name="company_id" groups="!base.group_multi_company" invisible="1"/> <field name="company_id" groups="!base.group_multi_company" invisible="1"/>
<field name="sale_order_ids" widget="many2many_tags"/> <field name="sale_order_ids" widget="many2many_tags"/>
<field
name="state"
decoration-success="state == 'sale' or state == 'done'"
decoration-info="state == 'draft' or state == 'sent'"
widget="badge"
optional="hide"
/>
<field <field
name="invoice_status" name="invoice_status"
decoration-success="invoice_status == 'invoiced'" decoration-success="invoice_status == 'invoiced'"
@ -18,7 +25,27 @@
widget="badge" widget="badge"
optional="show" optional="show"
/> />
<field name="state"/> </tree>
</field>
</record>
<record id="view_order_batch_quotation_tree" model="ir.ui.view">
<field name="name">sale.order.batch.quotation.tree</field>
<field name="model">sale.order.batch</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="date_order"/>
<field name="company_id" groups="base.group_multi_company" optional="show" readonly="1"/>
<field name="company_id" groups="!base.group_multi_company" invisible="1"/>
<field name="sale_order_ids" widget="many2many_tags"/>
<field
name="state"
decoration-success="state == 'sale' or state == 'done'"
decoration-info="state == 'draft' or state == 'sent'"
widget="badge"
optional="show"
/>
</tree> </tree>
</field> </field>
</record> </record>
@ -140,6 +167,7 @@
</group> </group>
<notebook> <notebook>
<page string="Sale Orders" name="orders"> <page string="Sale Orders" name="orders">
<field name="state" invisible="1"/>
<field name="sale_order_ids"> <field name="sale_order_ids">
<tree delete="0" editable="0" create="0"> <tree delete="0" editable="0" create="0">
<field name="name"/> <field name="name"/>
@ -148,13 +176,20 @@
<field name="amount_untaxed"/> <field name="amount_untaxed"/>
<field name="amount_total"/> <field name="amount_total"/>
<field name="company_id" invisible="1"/> <field name="company_id" invisible="1"/>
<field
name="state"
decoration-success="state == 'sale' or state == 'done'"
decoration-info="state == 'draft' or state == 'sent'"
widget="badge"
optional="show"
/>
<field <field
name="invoice_status" name="invoice_status"
decoration-success="invoice_status == 'invoiced'" decoration-success="invoice_status == 'invoiced'"
decoration-info="invoice_status == 'to invoice'" decoration-info="invoice_status == 'to invoice'"
decoration-warning="invoice_status == 'upselling'" decoration-warning="invoice_status == 'upselling'"
widget="badge" widget="badge"
optional="show" optional="hide"
/> />
</tree> </tree>
</field> </field>
@ -214,6 +249,7 @@
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
<field name="res_model">sale.order.batch</field> <field name="res_model">sale.order.batch</field>
<field name="view_mode">tree,form,activity</field> <field name="view_mode">tree,form,activity</field>
<field name="view_id" ref="view_order_batch_quotation_tree"/>
<field name="context">{'search_default_filter_batch_open': 1}</field> <field name="context">{'search_default_filter_batch_open': 1}</field>
</record> </record>
@ -222,6 +258,7 @@
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
<field name="res_model">sale.order.batch</field> <field name="res_model">sale.order.batch</field>
<field name="view_mode">tree,form,activity</field> <field name="view_mode">tree,form,activity</field>
<field name="view_id" ref="view_order_batch_tree"/>
<field name="context">{'search_default_filter_batch_finished': 1}</field> <field name="context">{'search_default_filter_batch_finished': 1}</field>
</record> </record>

View file

@ -0,0 +1 @@
from . import sale_order_batch_cancel_wizard

View file

@ -0,0 +1,34 @@
from odoo import api, fields, models
class SaleOrderBatchCancelWizard(models.TransientModel):
_name = "sale.order.batch.cancel.wizard"
_description = "Cancel Sale Order Batch Confirmation"
batch_ids = fields.Many2many(
comodel_name="sale.order.batch",
string="Batches to Cancel",
default=lambda self: self.env["sale.order.batch"].browse(
self.env.context.get("active_ids", [])
),
)
order_ids = fields.Many2many(
comodel_name="sale.order",
string="Orders to Cancel",
compute="_compute_order_ids",
)
@api.depends("batch_ids")
def _compute_order_ids(self):
for record in self:
batches = record.batch_ids
record.order_ids = batches.mapped("sale_order_ids")
def action_cancel(self):
batches = self.batch_ids
batches._action_cancel()
return {"type": "ir.actions.act_window_close"}
def action_discard(self):
return {"type": "ir.actions.act_window_close"}

View file

@ -0,0 +1,24 @@
<odoo>
<record id="view_sale_order_batch_cancel_wizard_form" model="ir.ui.view">
<field name="name">sale.order.batch.cancel.wizard.form</field>
<field name="model">sale.order.batch.cancel.wizard</field>
<field name="arch" type="xml">
<form>
<group col="1">
<div col="2" class="alert alert-warning" role="alert">
<span>Are you sure you want to cancel this order?</span>
</div>
<group col="2">
<field name="batch_ids" invisible="1"/>
<field name="order_ids" widget="many2many_tags"/>
</group>
</group>
<footer>
<button string="Cancel" name="action_cancel" type="object" class="btn-primary mx-1"/>
<button string="Discard" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
</odoo>