Browse Source

Initial Commit

pull/81/head
cybroodoo 8 years ago
parent
commit
ec795043b0
  1. 3
      sale_discout_total/__init__.py
  2. 33
      sale_discout_total/__openerp__.py
  3. 4
      sale_discout_total/models/__init__.py
  4. 80
      sale_discout_total/models/account_invoice.py
  5. 87
      sale_discout_total/models/discount_approval.py
  6. 145
      sale_discout_total/models/sale.py
  7. 2
      sale_discout_total/reports/__init__.py
  8. 20
      sale_discout_total/reports/invoice_report.py
  9. 13
      sale_discout_total/reports/sale_report.py
  10. BIN
      sale_discout_total/static/description/Disc_appr_conf.png
  11. BIN
      sale_discout_total/static/description/Disc_appr_wrkfl.png
  12. BIN
      sale_discout_total/static/description/Discount_inv_amnt.png
  13. BIN
      sale_discout_total/static/description/Discount_so_perc.png
  14. BIN
      sale_discout_total/static/description/icon.png
  15. 39
      sale_discout_total/static/description/index.html
  16. 41
      sale_discout_total/views/account_invoice_view.xml
  17. 18
      sale_discout_total/views/invoice_report.xml
  18. 28
      sale_discout_total/views/res_config_view.xml
  19. 21
      sale_discout_total/views/sale_order_report.xml
  20. 43
      sale_discout_total/views/sale_view.xml

3
sale_discout_total/__init__.py

@ -0,0 +1,3 @@
import models
import reports

33
sale_discout_total/__openerp__.py

@ -0,0 +1,33 @@
{
'name': 'Sale Discount on Total Amount',
'version': '1.0',
'category': 'sale',
'summary': "Discount on total in Sale and invoice with Discount limit and approval",
'author': 'Cybrosys Techno Solutions',
'company': 'Cybrosys Techno Solutions',
'website': 'http://www.cybrosys.com',
'description': """
Sale Discount for Total Amount
=======================
Module to manage discount on total amount in Sale.
as an specific amount or percentage
""",
'depends': ['sale',
'account'
],
'data': [
'views/sale_view.xml',
'views/account_invoice_view.xml',
'views/invoice_report.xml',
'views/sale_order_report.xml',
'views/res_config_view.xml',
],
'demo': [
],
'application': True,
'installable': True,
'auto_install': False,
}

4
sale_discout_total/models/__init__.py

@ -0,0 +1,4 @@
import sale
import account_invoice
import discount_approval

80
sale_discout_total/models/account_invoice.py

@ -0,0 +1,80 @@
from openerp import api, fields, models
import openerp.addons.decimal_precision as dp
class AccountInvoice(models.Model):
_inherit = "account.invoice"
@api.one
@api.depends('invoice_line_ids.price_subtotal', 'tax_line_ids.amount', 'currency_id', 'company_id', 'date_invoice')
def _compute_amount(self):
self.amount_untaxed = sum(line.price_subtotal for line in self.invoice_line_ids)
self.amount_tax = sum(line.amount for line in self.tax_line_ids)
self.amount_total = self.amount_untaxed + self.amount_tax
self.amount_discount = sum((line.quantity * line.price_unit * line.discount)/100 for line in self.invoice_line_ids)
amount_total_company_signed = self.amount_total
amount_untaxed_signed = self.amount_untaxed
if self.currency_id and self.currency_id != self.company_id.currency_id:
currency_id = self.currency_id.with_context(date=self.date_invoice)
amount_total_company_signed = currency_id.compute(self.amount_total, self.company_id.currency_id)
amount_untaxed_signed = currency_id.compute(self.amount_untaxed, self.company_id.currency_id)
sign = self.type in ['in_refund', 'out_refund'] and -1 or 1
self.amount_total_company_signed = amount_total_company_signed * sign
self.amount_total_signed = self.amount_total * sign
self.amount_untaxed_signed = amount_untaxed_signed * sign
discount_type = fields.Selection([('percent', 'Percentage'), ('amount', 'Amount')], string='Discount Type',
readonly=True, states={'draft': [('readonly', False)]}, default='percent')
discount_rate = fields.Float('Discount Amount', digits=(16, 2), readonly=True, states={'draft': [('readonly', False)]})
amount_discount = fields.Monetary(string='Discount', store=True, readonly=True, compute='_compute_amount',
track_visibility='always')
@api.onchange('discount_type', 'discount_rate', 'invoice_line_ids')
def supply_rate(self):
for inv in self:
if inv.discount_type == 'percent':
for line in inv.invoice_line_ids:
line.discount = inv.discount_rate
else:
total = discount = 0.0
for line in inv.invoice_line_ids:
total += (line.quantity * line.price_unit)
if inv.discount_rate != 0:
discount = (inv.discount_rate / total) * 100
else:
discount = inv.discount_rate
for line in inv.invoice_line_ids:
line.discount = discount
@api.multi
def compute_invoice_totals(self, company_currency, invoice_move_lines):
total = 0
total_currency = 0
for line in invoice_move_lines:
if self.currency_id != company_currency:
currency = self.currency_id.with_context(date=self.date_invoice or fields.Date.context_today(self))
line['currency_id'] = currency.id
line['amount_currency'] = currency.round(line['price'])
line['price'] = currency.compute(line['price'], company_currency)
else:
line['currency_id'] = False
line['amount_currency'] = False
line['price'] = line['price']
if self.type in ('out_invoice', 'in_refund'):
total += line['price']
total_currency += line['amount_currency'] or line['price']
line['price'] = - line['price']
else:
total -= line['price']
total_currency -= line['amount_currency'] or line['price']
return total, total_currency, invoice_move_lines
@api.multi
def button_dummy(self):
self.supply_rate()
return True
class AccountInvoiceLine(models.Model):
_inherit = "account.invoice.line"
discount = fields.Float(string='Discount (%)', digits=(16, 20), default=0.0)

87
sale_discout_total/models/discount_approval.py

@ -0,0 +1,87 @@
from openerp import api, fields, models
class sale_discount(models.Model):
_inherit = 'sale.order'
state = fields.Selection([
('draft', 'Quotation'),
('sent', 'Quotation Sent'),
('waiting', 'Waiting Approval'),
('sale', 'Sales Order'),
('done', 'Locked'),
('cancel', 'Cancelled'),
], string='Status', readonly=True, copy=False, index=True, track_visibility='onchange', default='draft')
@api.multi
def action_confirm(self):
discnt = 0.0
no_line = 0.0
for order in self:
if order.company_id.discount_approval:
print order.company_id.discount_approval
for line in order.order_line:
no_line += 1
discnt += line.discount
discnt = (discnt / no_line)
if order.company_id.limit_discount and discnt > order.company_id.limit_discount:
order.state = 'waiting'
return True
order.state = 'sale'
order.confirmation_date = fields.Datetime.now()
if self.env.context.get('send_email'):
self.force_quotation_send()
order.order_line._action_procurement_create()
if self.env['ir.values'].get_default('sale.config.settings', 'auto_done_setting'):
self.action_done()
return True
@api.multi
def action_approve(self):
for order in self:
order.state = 'sale'
order.confirmation_date = fields.Datetime.now()
if self.env.context.get('send_email'):
self.force_quotation_send()
order.order_line._action_procurement_create()
if self.env['ir.values'].get_default('sale.config.settings', 'auto_done_setting'):
self.action_done()
return True
class Company(models.Model):
_inherit = 'res.company'
limit_discount = fields.Float(string="Discount limit requires approval %",
help="Discount after which approval of sale is required.")
discount_approval = fields.Boolean("Force two levels of approvals",
help='Provide a double validation mechanism for sale exceeding minimum discount.')
@api.multi
def set_default_discount(self):
if self.discount_approval and self.discount_approval != self.company_id.discount_approval:
self.company_id.write({'discount_approval': self.discount_approval})
if self.limit_discount and self.limit_discount != self.company_id.limit_discount:
self.company_id.write({'limit_discount': self.limit_discount})
class AccountDiscountSettings(models.TransientModel):
_inherit = 'account.config.settings'
limit_discount = fields.Float(string="Discount limit requires approval in %",
related='company_id.limit_discount',
help="Discount after which approval of sale is required.")
discount_approval = fields.Boolean("Force two levels of approval on discount",
related='company_id.discount_approval',
help='Provide a double validation mechanism for sale exceeding maximum discount limit.')
@api.onchange('company_id')
def onchange_company_id(self):
if self.company_id:
company = self.company_id
self.discount_approval = company.discount_approval
self.limit_discount = company.limit_discount
res = super(AccountDiscountSettings, self).onchange_company_id()
return res

145
sale_discout_total/models/sale.py

@ -0,0 +1,145 @@
from openerp import api, fields, models
import openerp.addons.decimal_precision as dp
class SaleOrder(models.Model):
_inherit = "sale.order"
@api.depends('order_line.price_total')
def _amount_all(self):
"""
Compute the total amounts of the SO.
"""
for order in self:
amount_untaxed = amount_tax = amount_discount = 0.0
for line in order.order_line:
amount_untaxed += line.price_subtotal
amount_tax += line.price_tax
amount_discount += (line.product_uom_qty * line.price_unit * line.discount)/100
order.update({
'amount_untaxed': order.pricelist_id.currency_id.round(amount_untaxed),
'amount_tax': order.pricelist_id.currency_id.round(amount_tax),
'amount_discount': order.pricelist_id.currency_id.round(amount_discount),
'amount_total': amount_untaxed + amount_tax,
})
discount_type = fields.Selection([('percent', 'Percentage'), ('amount', 'Amount')], string='Discount type',
readonly=True,states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
default='percent')
discount_rate = fields.Float('Discount Rate', digits_compute=dp.get_precision('Account'),
readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]})
amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True, readonly=True, compute='_amount_all',
track_visibility='always')
amount_tax = fields.Monetary(string='Taxes', store=True, readonly=True, compute='_amount_all',
track_visibility='always')
amount_total = fields.Monetary(string='Total', store=True, readonly=True, compute='_amount_all',
track_visibility='always')
amount_discount = fields.Monetary(string='Discount', store=True, readonly=True, compute='_amount_all',
digits_compute=dp.get_precision('Account'), track_visibility='always')
@api.onchange('discount_type', 'discount_rate', 'order_line')
def supply_rate(self):
for order in self:
if order.discount_type == 'percent':
for line in order.order_line:
line.discount = order.discount_rate
else:
total = discount = 0.0
for line in order.order_line:
total += round((line.product_uom_qty * line.price_unit))
if order.discount_rate != 0:
discount = (order.discount_rate / total) * 100
else:
discount = order.discount_rate
for line in order.order_line:
line.discount = discount
@api.multi
def _prepare_invoice(self,):
invoice_vals = super(SaleOrder, self)._prepare_invoice()
invoice_vals.update({
'discount_type': self.discount_type,
'discount_rate': self.discount_rate
})
return invoice_vals
@api.multi
def button_dummy(self):
self.supply_rate()
return True
class AccountTax(models.Model):
_inherit = 'account.tax'
@api.multi
def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None):
print "hello"
if len(self) == 0:
company_id = self.env.user.company_id
else:
company_id = self[0].company_id
if not currency:
currency = company_id.currency_id
taxes = []
prec = currency.decimal_places
round_tax = False if company_id.tax_calculation_rounding_method == 'round_globally' else True
round_total = True
if 'round' in self.env.context:
round_tax = bool(self.env.context['round'])
round_total = bool(self.env.context['round'])
if not round_tax:
prec += 5
# total_excluded = total_included = base = round(price_unit * quantity, prec)
total_excluded = total_included = base = (price_unit * quantity)
for tax in self.sorted(key=lambda r: r.sequence):
if tax.amount_type == 'group':
ret = tax.children_tax_ids.compute_all(price_unit, currency, quantity, product, partner)
total_excluded = ret['total_excluded']
base = ret['base']
total_included = ret['total_included']
tax_amount = total_included - total_excluded
taxes += ret['taxes']
continue
tax_amount = tax._compute_amount(base, price_unit, quantity, product, partner)
if not round_tax:
tax_amount = round(tax_amount, prec)
else:
tax_amount = currency.round(tax_amount)
if tax.price_include:
total_excluded -= tax_amount
base -= tax_amount
else:
total_included += tax_amount
if tax.include_base_amount:
base += tax_amount
taxes.append({
'id': tax.id,
'name': tax.with_context(**{'lang': partner.lang} if partner else {}).name,
'amount': tax_amount,
'sequence': tax.sequence,
'account_id': tax.account_id.id,
'refund_account_id': tax.refund_account_id.id,
'analytic': tax.analytic,
})
print "total_excluded:",total_excluded
print "total_included:",total_included
return {
'taxes': sorted(taxes, key=lambda k: k['sequence']),
'total_excluded': total_excluded,
'total_included': total_included,
'base': base,
}
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
discount = fields.Float(string='Discount (%)', digits=(16, 20), default=0.0)

2
sale_discout_total/reports/__init__.py

@ -0,0 +1,2 @@
import invoice_report
import sale_report

20
sale_discout_total/reports/invoice_report.py

@ -0,0 +1,20 @@
from openerp import fields, models
class AccountInvoiceReport(models.Model):
_inherit = 'account.invoice.report'
discount = fields.Float('Discount', readonly=True)
def _select(self):
res = super(AccountInvoiceReport,self)._select()
select_str = res + """, sub.discount AS discount """
return select_str
def _sub_select(self):
res = super(AccountInvoiceReport,self)._sub_select()
select_str = res + """,SUM(CASE
WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text])
THEN - ((ail.quantity / u.factor * u2.factor) * ail.price_unit * (ail.discount) / 100.0)
ELSE ((ail.quantity / u.factor * u2.factor) * ail.price_unit * (ail.discount) / 100.0) END) as discount"""
return select_str

13
sale_discout_total/reports/sale_report.py

@ -0,0 +1,13 @@
from openerp import fields, models
class DiscountSaleReport(models.Model):
_inherit = 'sale.report'
discount = fields.Float('Discount', readonly=True)
def _select(self):
res = super(DiscountSaleReport,self)._select()
select_str = res+""",sum(l.product_uom_qty / u.factor * u2.factor * cr.rate * l.price_unit * l.discount / 100.0)
as discount"""
return select_str

BIN
sale_discout_total/static/description/Disc_appr_conf.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
sale_discout_total/static/description/Disc_appr_wrkfl.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
sale_discout_total/static/description/Discount_inv_amnt.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
sale_discout_total/static/description/Discount_so_perc.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
sale_discout_total/static/description/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

39
sale_discout_total/static/description/index.html

@ -0,0 +1,39 @@
<section class="oe_container">
<div class="oe_row">
<h2 class="oe_slogan">Discount On Sale</h2>
<!--<h3 class="oe_slogan">It Fits Your Sales Approach</h3>-->
<div>
<p>
This module allows you to mention discount on Total of sale order and Total of Customer Invoice in two ways
</p>
<hr>
<p>
1. As percentage<br>
Select 'Percentage' from Discount type and give discount percentage as Discount rate.
System will update the value of Discount and Total
</p>
<div class="oe_row_img oe_centered oe_mt32">
<img class="oe_picture oe_screenshot" src="Discount_so_perc.png">
</div>
<hr>
<p>
2. As amount<br>
Select 'Amount' from Discount type and give discount amount as Discount rate.
System will update the value of Discount and Total
</p>
<div class="oe_row_img oe_centered oe_mt32">
<img class="oe_picture oe_screenshot" src="Discount_inv_amnt.png">
</div>
<hr>
<p>
And the module also allows you to set a limit for total discount in percentage under accounting settings. Exceeding this limit
will require approval.
</p>
<div class="oe_row_img oe_centered oe_mt32">
<img class="oe_picture oe_screenshot" src="Disc_appr_conf.png"><hr>
<img class="oe_picture oe_screenshot" src="Disc_appr_wrkfl.png">
</div>
</div>
</div>
</section>

41
sale_discout_total/views/account_invoice_view.xml

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="discount_account_invoice_view_form" model="ir.ui.view">
<field name="name">discount.account.invoice</field>
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='discount']" position="attributes">
<attribute name="digits">(16, 2)</attribute>
</xpath>
<xpath expr="//field[@name='amount_untaxed']" position="after">
<field name="amount_discount"/>
</xpath>
<xpath expr="//field[@name='comment']" position="before">
<div>
<label for="discount_type" string="Discount Type :"/>
<field name="discount_type" class="oe_inline"/>
</div>
<div>
<label for="discount_rate" string="Discount Rate :"/>
<field name="discount_rate" class="oe_inline"/>
</div>
</xpath>
</field>
</record>
<record id="discount_view_invoice_line_tree" model="ir.ui.view">
<field name="name">discount.account.invoice.line.tree</field>
<field name="model">account.invoice.line</field>
<field name="inherit_id" ref="account.view_invoice_line_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='discount']" position="attributes">
<attribute name="digits">(16, 2)</attribute>
</xpath>
</field>
</record>
</data>
</openerp>

18
sale_discout_total/views/invoice_report.xml

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="report_invoice_customized" inherit_id="account.report_invoice_document">
<xpath expr="//tr[@class='border-black']" position="after">
<tr>
<td>Discount</td>
<td class="text-right">
<span t-field="o.amount_discount"
t-field-options='{"widget": "monetary", "display_currency": "o.currency_id"}'/>
</td>
</tr>
</xpath>
</template>
</data>
</openerp>

28
sale_discout_total/views/res_config_view.xml

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_discount_config" model="ir.ui.view">
<field name="name">discount.config</field>
<field name="model">account.config.settings</field>
<field name="inherit_id" ref="account.view_account_config_settings"/>
<field name="arch" type="xml">
<xpath expr="//form/group[7]" position="after">
<group>
<label for="id" string="Discount"/>
<div>
<div>
<field name="discount_approval" class="oe_inline"/>
<label for="discount_approval"/>
</div>
<div>
<label for="limit_discount"/>
<field name="limit_discount" attrs="{'required': [('discount_approval','=',True)]}"
class="oe_inline"/>
</div>
</div>
</group>
</xpath>
</field>
</record>
</data>
</openerp>

21
sale_discout_total/views/sale_order_report.xml

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="report_saleorder_customized" inherit_id="sale.report_saleorder_document">
<xpath expr="//span[@t-field='l.discount']" position="replace">
<span t-esc="'%.2f'%(l.discount)"/>
</xpath>
<xpath expr="//tr[@class='border-black']" position="after">
<tr>
<td>Total Discount</td>
<td class="text-right">
<span t-field="doc.amount_discount"
t-field-options='{"widget": "monetary", "display_currency": "doc.pricelist_id.currency_id"}'/>
</td>
</tr>
</xpath>
</template>
</data>
</openerp>

43
sale_discout_total/views/sale_view.xml

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="discount_sale_view_form" model="ir.ui.view">
<field name="name">discount.sale.order.form</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='state']" position="before">
<button string="Approve" type="object" name="action_approve" states="waiting" class="oe_highlight"
groups="base.group_sale_manager"/>
</xpath>
<xpath expr="//button[@name='action_cancel']" position="attributes">
<attribute name ="states">draft,sent,sale,waiting</attribute>
</xpath>
<xpath expr="//tree/field[@name='discount']" position="attributes">
<attribute name="digits">(16, 2)</attribute>
</xpath>
<xpath expr="//group[@name='sale_total']" position="replace">
<group col="4">
<group name="discount" colspan="2">
<field name="discount_type"/>
<field name="discount_rate"/>
</group>
<group class="oe_subtotal_footer oe_right" colspan="2" name="sale_total">
<field name="amount_untaxed" widget='monetary' options="{'currency_field': 'currency_id'}"/>
<field name="amount_discount" widget='monetary' options="{'currency_field': 'currency_id'}"/>
<field name="amount_tax" widget='monetary' options="{'currency_field': 'currency_id'}"/>
<div class="oe_subtotal_footer_separator oe_inline">
<label for="amount_total" />
<button name="button_dummy"
states="draft,sent" string="(update)" type="object" class="oe_edit_only oe_link"/>
</div>
<field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator" widget='monetary' options="{'currency_field': 'currency_id'}"/>
</group>
</group>
</xpath>
</field>
</record>
</data>
</openerp>
Loading…
Cancel
Save