'taxes': [] # List of taxes, see compute for the format
}
"""
+
+ # By default, for each tax, tax amount will first be computed
+ # and rounded at the 'Account' decimal precision for each
+ # PO/SO/invoice line and then these rounded amounts will be
+ # summed, leading to the total amount for that tax. But, if the
+ # company has tax_calculation_rounding_method = round_globally,
+ # we still follow the same method, but we use a much larger
+ # precision when we round the tax amount for each line (we use
+ # the 'Account' decimal precision + 5), and that way it's like
+ # rounding after the sum of the tax amounts of each line
precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
+ tax_compute_precision = precision
+ if taxes and taxes[0].company_id.tax_calculation_rounding_method == 'round_globally':
+ tax_compute_precision += 5
totalin = totalex = round(price_unit * quantity, precision)
tin = []
tex = []
tex.append(tax)
else:
tin.append(tax)
- tin = self.compute_inv(cr, uid, tin, price_unit, quantity, product=product, partner=partner)
+ tin = self.compute_inv(cr, uid, tin, price_unit, quantity, product=product, partner=partner, precision=tax_compute_precision)
for r in tin:
totalex -= r.get('amount', 0.0)
totlex_qty = 0.0
totlex_qty = totalex/quantity
except:
pass
- tex = self._compute(cr, uid, tex, totlex_qty, quantity,product=product, partner=partner)
+ tex = self._compute(cr, uid, tex, totlex_qty, quantity, product=product, partner=partner, precision=tax_compute_precision)
for r in tex:
totalin += r.get('amount', 0.0)
return {
_logger.warning("Deprecated, use compute_all(...)['taxes'] instead of compute(...) to manage prices with tax included")
return self._compute(cr, uid, taxes, price_unit, quantity, product, partner)
- def _compute(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None):
+ def _compute(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None, precision=None):
"""
Compute tax values for given PRICE_UNIT, QUANTITY and a buyer/seller ADDRESS_ID.
tax = {'name':'', 'amount':0.0, 'account_collected_id':1, 'account_paid_id':2}
one tax for each tax id in IDS and their children
"""
+ if not precision:
+ precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
res = self._unit_compute(cr, uid, taxes, price_unit, product, partner, quantity)
total = 0.0
- precision_pool = self.pool.get('decimal.precision')
for r in res:
if r.get('balance',False):
- r['amount'] = round(r.get('balance', 0.0) * quantity, precision_pool.precision_get(cr, uid, 'Account')) - total
+ r['amount'] = round(r.get('balance', 0.0) * quantity, precision) - total
else:
- r['amount'] = round(r.get('amount', 0.0) * quantity, precision_pool.precision_get(cr, uid, 'Account'))
+ r['amount'] = round(r.get('amount', 0.0) * quantity, precision)
total += r['amount']
return res
r['todo'] = 0
return res
- def compute_inv(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None):
+ def compute_inv(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None, precision=None):
"""
Compute tax values for given PRICE_UNIT, QUANTITY and a buyer/seller ADDRESS_ID.
Price Unit is a VAT included price
tax = {'name':'', 'amount':0.0, 'account_collected_id':1, 'account_paid_id':2}
one tax for each tax id in IDS and their children
"""
+ if not precision:
+ precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
res = self._unit_compute_inv(cr, uid, taxes, price_unit, product, partner=None)
total = 0.0
- obj_precision = self.pool.get('decimal.precision')
for r in res:
- prec = obj_precision.precision_get(cr, uid, 'Account')
if r.get('balance',False):
- r['amount'] = round(r['balance'] * quantity, prec) - total
+ r['amount'] = round(r['balance'] * quantity, precision) - total
else:
- r['amount'] = round(r['amount'] * quantity, prec)
+ r['amount'] = round(r['amount'] * quantity, precision)
total += r['amount']
return res
_inherit = "res.company"
_columns = {
'expects_chart_of_accounts': fields.boolean('Expects a Chart of Accounts'),
+ 'tax_calculation_rounding_method': fields.selection([
+ ('round_per_line', 'Round per line'),
+ ('round_globally', 'Round globally'),
+ ], 'Tax calculation rounding method',
+ help="If you select 'Round per line' : for each tax, the tax amount will first be computed and rounded for each PO/SO/invoice line and then these rounded amounts will be summed, leading to the total amount for that tax. If you select 'Round globally': for each tax, the tax amount will be computed for each PO/SO/invoice line, then these amounts will be summed and eventually this total tax amount will be rounded. If you sell with tax included, you should choose 'Round per line' because you certainly want the sum of your tax-included line subtotals to be equal to the total amount with taxes."),
'paypal_account': fields.char("Paypal Account", size=128, help="Paypal username (usually email) for receiving online payments."),
'overdue_msg': fields.text('Overdue Payments Message', translate=True),
'property_reserve_and_surplus_account': fields.property(
_defaults = {
'expects_chart_of_accounts': True,
+ 'tax_calculation_rounding_method': 'round_per_line',
'overdue_msg': '''Dear Sir, dear Madam,
Our records indicate that some payments on your account are still due. Please find details below.
'has_chart_of_accounts': fields.boolean('Company has a chart of accounts'),
'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', domain="[('visible','=', True)]"),
'code_digits': fields.integer('# of Digits', help="No. of Digits to use for account code"),
+ 'tax_calculation_rounding_method': fields.related('company_id',
+ 'tax_calculation_rounding_method', type='selection', selection=[
+ ('round_per_line', 'Round per line'),
+ ('round_globally', 'Round globally'),
+ ], string='Tax calculation rounding method',
+ help="If you select 'Round per line' : for each tax, the tax amount will first be computed and rounded for each PO/SO/invoice line and then these rounded amounts will be summed, leading to the total amount for that tax. If you select 'Round globally': for each tax, the tax amount will be computed for each PO/SO/invoice line, then these amounts will be summed and eventually this total tax amount will be rounded. If you sell with tax included, you should choose 'Round per line' because you certainly want the sum of your tax-included line subtotals to be equal to the total amount with taxes."),
'sale_tax': fields.many2one("account.tax.template", "Default Sale Tax"),
'purchase_tax': fields.many2one("account.tax.template", "Default Purchase Tax"),
'sale_tax_rate': fields.float('Sales Tax (%)'),
'has_chart_of_accounts': has_chart_of_accounts,
'has_fiscal_year': bool(fiscalyear_count),
'chart_template_id': False,
+ 'tax_calculation_rounding_method': company.tax_calculation_rounding_method,
}
# update journals and sequences
for journal_type in ('sale', 'sale_refund', 'purchase', 'purchase_refund'):