sale_usability: add a wizard to write discount on all lines
The wizard is available under the "Action" menu. It has an option to apply only on product or service lines. Add a button "Send ack by email" on confirmed sale.order
This commit is contained in:
@@ -1 +1,2 @@
|
||||
from . import models
|
||||
from . import wizards
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
'views/account_move.xml',
|
||||
'views/res_company.xml',
|
||||
"views/res_partner.xml",
|
||||
'wizards/sale_invoice_discount_all_lines_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
3
sale_usability/security/ir.model.access.csv
Normal file
3
sale_usability/security/ir.model.access.csv
Normal file
@@ -0,0 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_sale_invoice_discount_all_lines_sale,Full access on sale.invoice.discount.all.lines to Sale user,model_sale_invoice_discount_all_lines,sales_team.group_sale_salesman,1,1,1,1
|
||||
access_sale_invoice_discount_all_lines_invoice,Full access on sale.invoice.discount.all.lines to Invoice user,model_sale_invoice_discount_all_lines,account.group_account_invoice,1,1,1,1
|
||||
|
@@ -32,6 +32,9 @@
|
||||
<xpath expr="//field[@name='order_line']/tree/field[@name='product_template_id']" position="after">
|
||||
<field name="product_barcode" optional="hide"/>
|
||||
</xpath>
|
||||
<button name="action_quotation_send" attrs="{'invisible': ['|', ('state', '=', 'draft'), ('invoice_count','>=',1)]}" position="before">
|
||||
<button name="action_quotation_send" type="object" string="Send Order Acknowledgement" attrs="{'invisible': ['|', ('state', 'not in', ('sale', 'done')), ('invoice_count','>=',1)]}"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
1
sale_usability/wizards/__init__.py
Normal file
1
sale_usability/wizards/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import sale_invoice_discount_all_lines
|
||||
95
sale_usability/wizards/sale_invoice_discount_all_lines.py
Normal file
95
sale_usability/wizards/sale_invoice_discount_all_lines.py
Normal file
@@ -0,0 +1,95 @@
|
||||
# Copyright 2022 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models, fields, _
|
||||
from odoo.tools import float_compare
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class SaleInvoiceDiscountAllLines(models.TransientModel):
|
||||
_name = 'sale.invoice.discount.all.lines'
|
||||
_description = 'Apply discount on all lines of a sale order or invoice'
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super().default_get(fields_list)
|
||||
if self._context.get('active_id'):
|
||||
if self._context.get('active_model') == 'sale.order':
|
||||
res['sale_id'] = self._context['active_id']
|
||||
elif self._context.get('active_model') == 'account.move':
|
||||
res['move_id'] = self._context['active_id']
|
||||
move = self.env['account.move'].browse(res['move_id'])
|
||||
if move.state != 'draft':
|
||||
raise UserError(
|
||||
_("Invoice '%s' is not in draft state.")
|
||||
% self.move_id.display_name)
|
||||
else:
|
||||
# I don't translate this because it should never happen.
|
||||
raise UserError(
|
||||
"This wizard can only work on a sale order or an invoice.")
|
||||
else:
|
||||
# I don't translate this because it should never happen.
|
||||
raise UserError("Missing active_id in context. It should never happen.")
|
||||
return res
|
||||
|
||||
sale_id = fields.Many2one(
|
||||
'sale.order', string='Order', readonly=True)
|
||||
move_id = fields.Many2one(
|
||||
'account.move', string='Invoice', readonly=True)
|
||||
discount = fields.Float(
|
||||
string='Discount', digits='Discount', required=True)
|
||||
line_type = fields.Selection([
|
||||
('all', 'All Lines'),
|
||||
('products', 'All Product Lines'),
|
||||
('services', 'All Service Lines'),
|
||||
], default='all', required=True, string='Apply on')
|
||||
|
||||
def run(self):
|
||||
prec = self.env['decimal.precision'].precision_get('Discount')
|
||||
if float_compare(self.discount, 0, precision_digits=prec) < 0:
|
||||
raise UserError(_("Discount cannot be negative."))
|
||||
if self.sale_id:
|
||||
record = self.sale_id
|
||||
line_obj = self.env['sale.order.line']
|
||||
domain = [('order_id', '=', self.sale_id.id)]
|
||||
elif self.move_id:
|
||||
record = self.move_id
|
||||
if self.move_id.state != 'draft':
|
||||
raise UserError(_(
|
||||
"Invoice '%s' is not in draft state.") % self.move_id.display_name)
|
||||
line_obj = self.env['account.move.line']
|
||||
domain = [
|
||||
('move_id', '=', self.move_id.id),
|
||||
('exclude_from_invoice_tab', '=', False),
|
||||
]
|
||||
else:
|
||||
# I don't translate this because it should never happen.
|
||||
raise UserError(
|
||||
"The wizard is not linked to a sale order nor an invoice. "
|
||||
"This should never happen.")
|
||||
domain += [('display_type', '=', False)]
|
||||
if self.line_type == 'products':
|
||||
domain += [
|
||||
('product_id', '!=', False),
|
||||
('product_id.type', '!=', 'service'),
|
||||
]
|
||||
elif self.line_type == 'services':
|
||||
domain += [
|
||||
('product_id', '!=', False),
|
||||
('product_id.type', '=', 'service'),
|
||||
]
|
||||
lines = line_obj.search(domain)
|
||||
if not lines:
|
||||
raise UserError(_("There are no lines to apply the discount on."))
|
||||
lines.with_context(check_move_validity=False).write({'discount': self.discount})
|
||||
if self.move_id:
|
||||
self.move_id.with_context(
|
||||
check_move_validity=False)._recompute_dynamic_lines(
|
||||
recompute_all_taxes=True)
|
||||
self.move_id._check_balanced()
|
||||
record.message_post(body=_(
|
||||
"Applied a {discount}% discount on {line_type}.").format(
|
||||
discount=self.discount,
|
||||
line_type=self._fields['line_type'].convert_to_export(
|
||||
self.line_type, self)))
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2022 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="sale_invoice_discount_all_lines_form" model="ir.ui.view">
|
||||
<field name="model">sale.invoice.discount.all.lines</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<group name="main">
|
||||
<field name="sale_id" attrs="{'invisible': [('sale_id', '=', False)]}"/>
|
||||
<field name="move_id" attrs="{'invisible': [('move_id', '=', False)]}"/>
|
||||
<label for="discount"/>
|
||||
<div name="discount">
|
||||
<field name="discount" class="oe_inline"/> %%
|
||||
</div>
|
||||
<field name="line_type"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="run" type="object"
|
||||
class="btn-primary" string="Apply"/>
|
||||
<button special="cancel" string="Cancel" class="btn-default"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_move_discount_all_lines_action" model="ir.actions.act_window">
|
||||
<field name="name">Discount on all lines</field>
|
||||
<field name="res_model">sale.invoice.discount.all.lines</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="groups_id" eval="[(4, ref('account.group_account_invoice'))]"/>
|
||||
<field name="binding_model_id" ref="account.model_account_move" />
|
||||
<field name="binding_view_types">form</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_discount_all_lines_action" model="ir.actions.act_window">
|
||||
<field name="name">Discount on all lines</field>
|
||||
<field name="res_model">sale.invoice.discount.all.lines</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="groups_id" eval="[(4, ref('sales_team.group_sale_salesman'))]"/>
|
||||
<field name="binding_model_id" ref="sale.model_sale_order" />
|
||||
<field name="binding_view_types">form</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user