[imp] add batch invoicing, improve max_qty constraint

This commit is contained in:
Niels Göttsch 2024-07-23 23:03:22 +02:00
parent 7e0e9e5862
commit 83ff3d9f67
8 changed files with 90 additions and 14 deletions

View file

@ -3,7 +3,7 @@
"summary": "Add minimum and maximum order quantities to sale orders and use default packaging",
"author": "BAKEUP",
"website": "https://www.bakeup.org",
"category": "Stock",
"category": "Sale",
"version": "16.0.0.0.1",
"depends": ["sale", "sale_order_batch"],
"data": [

View file

@ -10,6 +10,11 @@ class SaleOrderLine(models.Model):
@api.constrains("product_uom_qty", "product_uom_max_qty")
def _check_product_uom_qty(self):
for record in self:
if record.product_uom_max_qty != 0 and record.product_uom_qty > record.product_uom_max_qty:
raise UserError(_("The quantity must be less than or equal to the maximum quantity."))
for order_line in self:
if order_line.product_uom_max_qty != 0 and order_line.product_uom_qty > order_line.product_uom_max_qty:
raise UserError(
_(
f"{order_line.order_id.name},{order_line.product_id.name}:"
"The quantity must be less than or equal to the maximum quantity."
)
)

View file

@ -10,9 +10,14 @@
</xpath>
<xpath
expr="//field[@name='sale_order_line_ids']/tree/field[@name='product_uom_qty']"
position="after"
position="before"
>
<field name="product_uom_ordered_qty" optional="hide"/>
</xpath>
<xpath
expr="//field[@name='sale_order_line_ids']/tree/field[@name='product_uom_qty']"
position="after"
>
<field name="product_uom_max_qty"/>
</xpath>
</field>

View file

@ -7,9 +7,14 @@
<field name="arch" type="xml">
<xpath
expr="//field[@name='sale_order_line_ids']/tree/field[@name='product_uom_qty']"
position="after"
position="before"
>
<field name="product_uom_ordered_qty" optional="hide"/>
</xpath>
<xpath
expr="//field[@name='sale_order_line_ids']/tree/field[@name='product_uom_qty']"
position="after"
>
<field name="product_uom_max_qty"/>
</xpath>
<xpath expr="//field[@name='product_ids']/tree" position="inside">

View file

@ -5,8 +5,10 @@
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom_qty']" position="after">
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom_qty']" position="before">
<field name="product_uom_ordered_qty" optional="hide"/>
</xpath>
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom_qty']" position="after">
<field name="product_uom_max_qty"/>
</xpath>
</field>

View file

@ -47,6 +47,8 @@ class SaleOrderBatch(models.Model):
sale_order_ids = fields.One2many("sale.order", "batch_id")
sale_order_count = fields.Integer(compute="_compute_sale_order_count")
sale_order_line_ids = fields.Many2many("sale.order.line", compute="_compute_sale_order_line_ids", store=True)
invoice_ids = fields.Many2many("account.move", compute="_compute_invoice_ids")
invoice_count = fields.Integer(compute="_compute_invoice_ids")
amount_total = fields.Float(compute="_compute_amount_total", string="Total")
product_ids = fields.One2many("sale.order.batch.product", "batch_id")
product_count = fields.Integer(compute="_compute_product_count")
@ -60,17 +62,24 @@ class SaleOrderBatch(models.Model):
else:
batch.validity_date = False
@api.depends("sale_order_ids")
def _compute_sale_order_count(self):
for batch in self:
batch.sale_order_count = len(batch.sale_order_ids)
@api.depends("sale_order_ids.order_line")
def _compute_sale_order_line_ids(self):
for batch in self:
order_lines = self.env["sale.order.line"].search([("order_id", "in", batch.sale_order_ids.ids)])
batch.sale_order_line_ids = order_lines
@api.depends("sale_order_ids")
def _compute_sale_order_count(self):
for batch in self:
batch.sale_order_count = len(batch.sale_order_ids)
@api.depends("sale_order_ids.invoice_ids")
def _compute_invoice_ids(self):
for batch in self:
invoices = batch.sale_order_ids.mapped("invoice_ids")
batch.invoice_ids = invoices
batch.invoice_count = len(invoices)
@api.depends("sale_order_ids.amount_total")
def _compute_amount_total(self):
for batch in self:
@ -113,6 +122,25 @@ class SaleOrderBatch(models.Model):
result = {"type": "ir.actions.act_window_close"}
return result
def action_view_invoice(self):
invoices = self.mapped("invoice_ids")
action = self.env["ir.actions.actions"]._for_xml_id("account.action_move_out_invoice_type")
if len(invoices) > 1:
action["domain"] = [("id", "in", invoices.ids)]
elif len(invoices) == 1:
form_view = [(self.env.ref("account.view_move_form").id, "form")]
if "views" in action:
action["views"] = form_view + [(state, view) for state, view in action["views"] if view != "form"]
else:
action["views"] = form_view
action["res_id"] = invoices.id
else:
action = {"type": "ir.actions.act_window_close"}
context = {"default_move_type": "out_invoice"}
action["context"] = context
return action
def action_confirm(self):
for batch in self:
orders = batch.with_context(bypass_batch=True).sale_order_ids

View file

@ -26,6 +26,7 @@
<field name="sale_order_line_ids" widget="section_and_note_one2many">
<tree editable="bottom" create="0">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="order_partner_id"/>
<field name="product_uom_qty"/>
<field name="price_unit"/>

View file

@ -29,6 +29,19 @@
type="object"
attrs="{'invisible': [('state', '!=','open')]}"
/>
<button
id="create_invoices"
name="%(sale.action_view_sale_advance_payment_inv)d"
string="Create Invoices"
type="action"
class="btn-primary"
context="{
'default_sale_order_ids': sale_order_ids,
}"
data-hotkey="q"
attrs="{'invisible': [('state', '!=', 'closed')]}"
/>
<field name="state" widget="statusbar" options="{'clickable': 'true'}"/>
</header>
<div
@ -58,6 +71,15 @@
>
<field string="Products" name="product_count" widget="statinfo"/>
</button>
<button
name="action_view_invoice"
type="object"
class="oe_stat_button"
icon="fa-pencil-square-o"
attrs="{'invisible': [('invoice_count', '=', 0)]}"
>
<field name="invoice_count" widget="statinfo" string="Invoices"/>
</button>
</div>
<h1>
<field name="name"/>
@ -76,7 +98,6 @@
<field
name="sale_order_ids"
domain="[('state','in',['draft','sent']),('batch_id','=',False)]"
attrs="{'readonly': [('state', 'in', ('closed'))]}"
>
<tree>
<field name="name"/>
@ -84,6 +105,14 @@
<field name="date_order"/>
<field name="amount_untaxed"/>
<field name="amount_total"/>
<field
name="invoice_status"
decoration-success="invoice_status == 'invoiced'"
decoration-info="invoice_status == 'to invoice'"
decoration-warning="invoice_status == 'upselling'"
widget="badge"
optional="show"
/>
</tree>
</field>
</page>
@ -95,8 +124,9 @@
>
<tree editable="bottom">
<field name="sequence" widget="handle"/>
<field name="order_id"/>
<field name="order_partner_id"/>
<field name="product_template_id"/>
<field name="product_template_id" optional="hide"/>
<field name="name"/>
<field name="product_uom_qty"/>
<field name="price_unit"/>