Improve tax:

- fix tax code
 - define tax account for invoice and refund
 - add supplier tax to product
 - don't overwrite tax_code on the creation for account line

bzr revid: ced-0b62574858f1f113fb59dd6ccbf59fec0b8dc2e3
This commit is contained in:
ced 2007-01-12 10:03:39 +00:00
parent 42d54dcfdd
commit 2347a84431
7 changed files with 104 additions and 117 deletions

View File

@ -669,7 +669,7 @@ class account_move(osv.osv):
code = getattr(tax,field_base+'base_code_id').id
amount = getattr(tax, field_base+'base_sign') * (line.debit + line.credit)
break
if code:
if code and not (line.tax_code_id or line.tax_amount):
self.pool.get('account.move.line').write(cr, uid, [line.id], {
'tax_code_id': code,
'tax_amount': amount
@ -685,7 +685,7 @@ class account_move(osv.osv):
elif line.account_id.id in account:
code = account[line.account_id.id][0]
amount = account[line.account_id.id][1] * (line.debit + line.credit)
if code or amount:
if (code or amount) and not (line.tax_code_id or line.tax_amount):
self.pool.get('account.move.line').write(cr, uid, [line.id], {
'tax_code_id': code,
'tax_amount': amount
@ -802,8 +802,8 @@ class account_tax(osv.osv):
'type': fields.selection( [('percent','Percent'), ('fixed','Fixed'), ('none','None'), ('code','Python Code')], 'Tax Type', required=True),
'applicable_type': fields.selection( [('true','True'), ('code','Python Code')], 'Applicable Type', required=True),
'domain':fields.char('Domain', size=32, help="This field is only used if you develop your own module allowing developpers to create specific taxes in a custom domain."),
'account_collected_id':fields.many2one('account.account', 'Collected Tax Account'),
'account_paid_id':fields.many2one('account.account', 'Paid Tax Account'),
'account_collected_id':fields.many2one('account.account', 'Invoice Tax Account'),
'account_paid_id':fields.many2one('account.account', 'Refund Tax Account'),
'parent_id':fields.many2one('account.tax', 'Parent Tax Account', select=True),
'child_ids':fields.one2many('account.tax', 'parent_id', 'Childs Tax Account'),
'child_depend':fields.boolean('Tax on Childs', help="Indicate if the tax computation is based on the value computed for the computation of child taxes or based on the total amount."),
@ -865,9 +865,9 @@ class account_tax(osv.osv):
# we compute the amount for the current tax object and append it to the result
if tax.type=='percent':
amount = cur_price_unit * tax.amount
res.append({'id':tax.id, 'name':tax.name, 'amount':amount, 'account_collected_id':tax.account_collected_id.id, 'account_paid_id':tax.account_paid_id.id, 'base_code_id': tax.base_code_id.id, 'ref_base_code_id': tax.ref_base_code_id.id, 'sequence': tax.sequence, 'base_sign': tax.base_sign, 'ref_base_sign': tax.ref_base_sign, 'price_unit': cur_price_unit, 'tax_code_id': tax.tax_code_id.id,})
res.append({'id':tax.id, 'name':tax.name, 'amount':amount, 'account_collected_id':tax.account_collected_id.id, 'account_paid_id':tax.account_paid_id.id, 'base_code_id': tax.base_code_id.id, 'ref_base_code_id': tax.ref_base_code_id.id, 'sequence': tax.sequence, 'base_sign': tax.base_sign, 'tax_sign': tax.tax_sign, 'ref_base_sign': tax.ref_base_sign, 'ref_tax_sign': tax.ref_tax_sign, 'price_unit': cur_price_unit, 'tax_code_id': tax.tax_code_id.id, 'ref_tax_code_id': tax.ref_tax_code_id.id,})
elif tax.type=='fixed':
res.append({'id':tax.id, 'name':tax.name, 'amount':tax.amount, 'account_collected_id':tax.account_collected_id.id, 'account_paid_id':tax.account_paid_id.id, 'base_code_id': tax.base_code_id.id, 'ref_base_code_id': tax.ref_base_code_id.id, 'sequence': tax.sequence, 'base_sign': tax.base_sign, 'ref_base_sign': tax.ref_base_sign, 'price_unit': 1, 'tax_code_id': tax.tax_code_id.id,})
res.append({'id':tax.id, 'name':tax.name, 'amount':tax.amount, 'account_collected_id':tax.account_collected_id.id, 'account_paid_id':tax.account_paid_id.id, 'base_code_id': tax.base_code_id.id, 'ref_base_code_id': tax.ref_base_code_id.id, 'sequence': tax.sequence, 'base_sign': tax.base_sign, 'tax_sign': tax.tax_sign, 'ref_base_sign': tax.ref_base_sign, 'ref_tax_sign': tax.ref_tax_sign, 'price_unit': 1, 'tax_code_id': tax.tax_code_id.id, 'ref_tax_code_id': tax.ref_tax_code_id.id,})
elif tax.type=='code':
address = address_id and self.pool.get('res.partner.address').browse(cr, uid, address_id) or None
localdict = {'price_unit':cur_price_unit, 'address':address}
@ -883,9 +883,12 @@ class account_tax(osv.osv):
'ref_base_code_id': tax.ref_base_code_id.id,
'sequence': tax.sequence,
'base_sign': tax.base_sign,
'tax_sign': tax.tax_sign,
'ref_base_sign': tax.ref_base_sign,
'ref_tax_sign': tax.ref_tax_sign,
'price_unit': cur_price_unit,
'tax_code_id': tax.tax_code_id.id,
'ref_tax_code_id': tax.ref_tax_code_id.id,
})
amount2 = res[-1]['amount']
if len(tax.child_ids):

View File

@ -292,6 +292,7 @@ class account_invoice(osv.osv):
# one move line per tax line
iml += self.pool.get('account.invoice.tax').move_line_get(cr, uid, inv['id'])
# create one move line for the total and possibly adjust the other lines amount
total = 0
@ -552,7 +553,11 @@ class account_invoice_line(osv.osv):
lang=self.pool.get('res.partner').read(cr, uid, [partner_id])[0]['lang']
context={'lang': lang}
res = self.pool.get('product.product').browse(cr, uid, product, context=context)
result = {'price_unit': res.list_price, 'invoice_line_tax_id':map(lambda x: x.id, res.taxes_id)}
if type in ('out_invoice', 'out_refund'):
result = {'price_unit': res.list_price, 'invoice_line_tax_id':map(lambda x: x.id, res.taxes_id)}
else:
result = {'price_unit': res.list_price, 'invoice_line_tax_id':map(lambda x: x.id, res.supplier_taxes_id)}
if not name:
result['name'] = res.name
@ -580,6 +585,7 @@ class account_invoice_line(osv.osv):
tax_grouped = {}
tax_obj = self.pool.get('account.tax')
cur_obj = self.pool.get('res.currency')
ait_obj = self.pool.get('account.invoice.tax')
#TODO: rewrite using browse instead of the manual SQL queries
# cr.execute('SELECT id FROM account_invoice_line WHERE invoice_id=%d', (invoice_id,))
inv = self.pool.get('account.invoice').browse(cr, uid, invoice_id)
@ -595,78 +601,46 @@ class account_invoice_line(osv.osv):
'account_id':line.account_id.id
})
for tax in tax_obj.compute(cr, uid, line.invoice_line_tax_id, (line.price_unit *(1.0-(line['discount'] or 0.0)/100.0)), line.quantity, inv.address_invoice_id.id, line.product_id):
tax['amount'] = cur_obj.round(cr, uid, cur, tax['amount'])
tax['sequence'] = tax['sequence']
val={}
val['invoice_id'] = inv.id
val['name'] = tax['name']
val['amount'] = cur_obj.round(cr, uid, cur, tax['amount'])
val['manual'] = False
val['sequence'] = tax['sequence']
val['base'] = tax['price_unit'] * line['quantity']
#
# Setting the tax account and amount for the line
#
if inv.type in ('out_invoice','out_refund'):
res[-1]['tax_code_id'] = tax['base_code_id']
res[-1]['tax_amount'] = tax['amount'] * tax['base_sign']
if inv.type in ('out_invoice','in_invoice'):
val['base_code_id'] = tax['base_code_id']
val['tax_code_id'] = tax['tax_code_id']
val['base_amount'] = val['base'] * tax['base_sign']
val['tax_amount'] = val['amount'] * tax['tax_sign']
val['account_id'] = tax['account_collected_id'] or line.account_id.id
else:
res[-1]['tax_code_id'] = tax['ref_base_code_id']
res[-1]['tax_amount'] = tax['amount'] * tax['ref_base_sign']
if inv.type in ('out_refund','in_refund'):
res[-1]['tax_amount'] = -res[-1]['tax_amount']
val['base_code_id'] = tax['ref_base_code_id']
val['tax_code_id'] = tax['ref_tax_code_id']
val['base_amount'] = val['base'] * tax['ref_base_sign']
val['tax_amount'] = val['amount'] * tax['ref_tax_sign']
val['account_id'] = tax['account_paid_id'] or line.account_id.id
if inv.type in ('out_invoice','out_refund'):
tax['account_id'] = tax['account_collected_id'] or line.account_id.id
else:
tax['account_id'] = tax['account_paid_id'] or line.account_id.id
#
# Revoir la clé: tax.id ?
#
key = (res[-1]['tax_code_id'], tax['account_id'])
res[-1]['tax_code_id'] = val['base_code_id']
res[-1]['tax_amount'] = val['base_amount']
key = (val['tax_code_id'], val['base_code_id'], val['account_id'])
if not key in tax_grouped:
tax_grouped[key] = tax
tax_grouped[key]['base'] = tax['price_unit'] * line['quantity']
tax_grouped[key] = val
else:
tax_grouped[key]['amount'] += tax['amount']
tax_grouped[key]['base'] += tax['price_unit'] * line['quantity']
tax_grouped[key]['amount'] += val['amount']
tax_grouped[key]['base'] += val['base']
tax_grouped[key]['base_amount'] += val['base_amount']
tax_grouped[key]['tax_amount'] += val['tax_amount']
# delete automatic tax lines for this invoice
cr.execute("DELETE FROM account_invoice_tax WHERE NOT manual AND invoice_id=%d", (invoice_id,))
self.move_line_tax_create(cr, uid, inv, tax_grouped, context)
return res
def move_line_tax_create(self, cr, uid, inv, tax_grouped, context={}):
# (re)create them
ait = self.pool.get('account.invoice.tax')
for t in tax_grouped.values():
tax = self.pool.get('account.tax').browse(cr, uid, t['id'])
val = {
'invoice_id':inv.id,
'name':t['name'],
'account_id':t['account_id'],
'amount':t['amount'],
'manual':False,
'sequence':t['sequence'],
'base': t['base'],
}
if inv.type in ('out_invoice','out_refund'):
val.update({
'base_code_id': tax.base_code_id.id or False,
'tax_code_id': tax.tax_code_id.id or False,
'base_amount': tax.base_sign * t['base'],
'tax_amount': tax.tax_sign * t['amount']
})
elif inv.type in ('in_invoice','in_refund'):
val.update({
'base_code_id': tax.ref_base_code_id.id or False,
'tax_code_id': tax.ref_tax_code_id.id or False,
'base_amount': tax.ref_base_sign * t['base'],
'tax_amount': tax.ref_tax_sign * t['amount']
})
if inv.type in ('out_refund','in_refund'):
val.update({
'base_amount': -val['base_amount'],
'tax_amount': -val['tax_amount']
})
ait.create(cr, uid, val)
#ait.create(cr, uid, {'invoice_id':invoice_id, 'name':t['name'], 'account_id':t['account_id'], 'amount':t['amount'], 'manual':False, 'sequence':t['sequence'], 'base':t['base']})
return True
ait_obj.create(cr, uid, t)
return res
#
# Set the tax field according to the account and the partner

View File

@ -62,24 +62,25 @@ product_category()
class product_template(osv.osv):
_inherit = "product.template"
_columns = {
'taxes_id': fields.many2many('account.tax', 'product_taxes_rel', 'prod_id', 'tax_id', 'Product Taxes', domain=[('parent_id','=',False)]),
'taxes_id': fields.many2many('account.tax', 'product_taxes_rel', 'prod_id', 'tax_id', 'Customer Taxes', domain=[('parent_id','=',False)]),
'supplier_taxes_id': fields.many2many('account.tax', 'product_supplier_taxes_rel', 'prod_id', 'tax_id', 'Supplier Taxes', domain=[('parent_id', '=', False)]),
'property_account_income': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Income Account",
method=True,
view_load=True,
group_name="Accounting Properties",
help="This account will be used, instead of the default one, to value incoming stock for the current product"),
'account.account',
type='many2one',
relation='account.account',
string="Income Account",
method=True,
view_load=True,
group_name="Accounting Properties",
help="This account will be used, instead of the default one, to value incoming stock for the current product"),
'property_account_expense': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Expense Account",
method=True,
view_load=True,
group_name="Accounting Properties",
help="This account will be used, instead of the default one, to value outgoing stock for the current product"),
'account.account',
type='many2one',
relation='account.account',
string="Expense Account",
method=True,
view_load=True,
group_name="Accounting Properties",
help="This account will be used, instead of the default one, to value outgoing stock for the current product"),
}
product_template()

View File

@ -9,6 +9,7 @@
<field name="arch" type="xml">
<field name="product_manager" position="after">
<newline/>
<field name="supplier_taxes_id" colspan="3"/>
<field name="taxes_id" colspan="3"/>
</field>
</field>
@ -22,6 +23,7 @@
<field name="arch" type="xml">
<field name="cost_method" position="after">
<newline/>
<field name="supplier_taxes_id" colspan="3"/>
<field name="taxes_id" colspan="3"/>
</field>
</field>

View File

@ -50,9 +50,9 @@ class account_tax(osv.osv):
# we compute the amount for the current tax object and append it to the result
if tax.type=='percent':
amount = cur_price_unit - (cur_price_unit / (1 + tax.amount))
res.append({'id':tax.id, 'name':tax.name, 'amount':amount, 'account_collected_id':tax.account_collected_id.id, 'account_paid_id':tax.account_paid_id.id, 'base_code_id': tax.base_code_id.id, 'ref_base_code_id': tax.ref_base_code_id.id, 'sequence': tax.sequence, 'base_sign': tax.base_sign, 'ref_base_sign': tax.ref_base_sign, 'price_unit': cur_price_unit - amount,})
res.append({'id':tax.id, 'name':tax.name, 'amount':amount, 'account_collected_id':tax.account_collected_id.id, 'account_paid_id':tax.account_paid_id.id, 'base_code_id': tax.base_code_id.id, 'ref_base_code_id': tax.ref_base_code_id.id, 'sequence': tax.sequence, 'base_sign': tax.base_sign, 'tax_sign': tax.tax_sign, 'ref_base_sign': tax.ref_base_sign, 'ref_tax_sign': tax.ref_tax_sign, 'price_unit': cur_price_unit - amount, 'tax_code_id': tax.tax_code_id.id, 'ref_tax_code_id': tax.ref_tax_code_id.id,})
elif tax.type=='fixed':
res.append({'id':tax.id, 'name':tax.name, 'amount':tax.amount, 'account_collected_id':tax.account_collected_id.id, 'account_paid_id':tax.account_paid_id.id, 'base_code_id': tax.base_code_id.id, 'ref_base_code_id': tax.ref_base_code_id.id, 'sequence': tax.sequence, 'base_sign': tax.base_sign, 'ref_base_sign': tax.ref_base_sign, 'price_unit': 1,})
res.append({'id':tax.id, 'name':tax.name, 'amount':tax.amount, 'account_collected_id':tax.account_collected_id.id, 'account_paid_id':tax.account_paid_id.id, 'base_code_id': tax.base_code_id.id, 'ref_base_code_id': tax.ref_base_code_id.id, 'sequence': tax.sequence, 'base_sign': tax.base_sign, 'tax_sign': tax.tax_sign, 'ref_base_sign': tax.ref_base_sign, 'ref_tax_sign': tax.ref_tax_sign, 'price_unit': 1, 'tax_code_id': tax.tax_code_id.id, 'ref_tax_code_id': tax.ref_tax_code_id.id,})
elif tax.type=='code':
address = address_id and self.pool.get('res.partner.address').browse(cr, uid, address_id) or None
localdict = {'price_unit':cur_price_unit, 'address':address, 'product':product,}
@ -68,8 +68,12 @@ class account_tax(osv.osv):
'ref_base_code_id': tax.ref_base_code_id.id,
'sequence': tax.sequence,
'base_sign': tax.base_sign,
'tax_sign': tax.tax_sign,
'ref_base_sign': tax.ref_base_sign,
'ref_tax_sign': tax.ref_tax_sign,
'price_unit': cur_price_unit - amount,
'tax_code_id': tax.tax_code_id.id,
'ref_tax_code_id': tax.ref_tax_code_id.id,
})
amount2 = res[-1]['amount']
if len(tax.child_ids):

View File

@ -91,7 +91,9 @@ class account_invoice_line(osv.osv):
tax_grouped = {}
tax_obj = self.pool.get('account.tax')
cur_obj = self.pool.get('res.currency')
ait_obj = self.pool.get('account.invoice.tax')
cur = inv.currency_id
for line in inv.invoice_line:
res.append( {
'type':'src',
@ -100,45 +102,46 @@ class account_invoice_line(osv.osv):
'quantity':line.quantity,
'price':round(line.quantity*line.price_unit * (1.0- (line.discount or 0.0)/100.0),2),
'account_id':line.account_id.id,
'tax_amount': 0.0
})
for tax in tax_obj.compute_inv(cr, uid, line.invoice_line_tax_id, (line.price_unit *(1.0-(line['discount'] or 0.0)/100.0)), line.quantity, inv.address_invoice_id.id, line.product_id):
tax['amount'] = cur_obj.round(cr, uid, cur, tax['amount'])
tax['sequence'] = tax['sequence']
val={}
val['invoice_id'] = inv.id
val['name'] = tax['name']
val['amount'] = cur_obj.round(cr, uid, cur, tax['amount'])
val['manual'] = False
val['sequence'] = tax['sequence']
val['base'] = tax['price_unit'] * line['quantity']
#res[-1]['tax_amount'] += (line['price_unit'] * line['quantity'] * (1.0- (line['discount'] or 0.0)/100.0) * tax2.base_sign)
#
# Setting the tax account and amount for the line
#
if inv.type in ('out_invoice','out_refund'):
res[-1]['tax_code_id'] = tax['base_code_id']
res[-1]['tax_amount'] = tax['amount'] * tax['base_sign']
if inv.type in ('out_invoice','in_invoice'):
val['base_code_id'] = tax['base_code_id']
val['tax_code_id'] = tax['tax_code_id']
val['base_amount'] = tax['base'] * tax['base_sign']
val['tax_amount'] = tax['amount'] * tax['tax_sign']
val['account_id'] = tax['account_collected_id'] or line.account_id.id
else:
res[-1]['tax_code_id'] = tax['ref_base_code_id']
res[-1]['tax_amount'] = tax['amount'] * tax['ref_base_sign']
if inv.type in ('out_refund','in_refund'):
res[-1]['tax_amount'] = -res[-1]['tax_amount']
val['base_code_id'] = tax['ref_base_code_id']
val['tax_code_id'] = tax['ref_tax_code_id']
val['base_amount'] = val['base'] * tax['ref_base_sign']
val['tax_amount'] = val['amount'] * tax['ref_tax_sign']
val['account_id'] = tax['account_paid_id'] or line.account_id.id
if inv.type in ('out_invoice','out_refund'):
tax['account_id'] = tax['account_collected_id'] or line.account_id.id
else:
tax['account_id'] = tax['account_paid_id'] or line.account_id.id
#
# Revoir la clé: tax.id ?
#
key = (res[-1]['tax_code_id'], tax['account_id'])
#res[-1]['price'] -= tax['amount']
#res[-1]['tax_amount'] -= (tax['amount']* tax2.base_sign)
res[-1]['tax_code_id'] = val['base_code_id']
res[-1]['tax_amount'] = val['base_amount']
key = (val['tax_code_id'], val['base_code_id'], val['account_id'])
if not key in tax_grouped:
tax_grouped[key] = tax
#tax_grouped[key]['base'] = res[-1]['price']
tax_grouped[key]['base'] = tax['price_unit'] * line['quantity']
tax_grouped[key] = val
else:
tax_grouped[key]['amount'] += tax['amount']
#tax_grouped[key]['base'] += res[-1]['price']
tax_grouped[key]['base'] += tax['price_unit'] * line['quantity']
tax_grouped[key]['amount'] += val['amount']
tax_grouped[key]['base'] += val['base']
tax_grouped[key]['base_amount'] += val['base_amount']
tax_grouped[key]['tax_amount'] += val['tax_amount']
# delete automatic tax lines for this invoice
cr.execute("DELETE FROM account_invoice_tax WHERE NOT manual AND invoice_id=%d", (invoice_id,))
self.move_line_tax_create(cr, uid, inv, tax_grouped, context)
for t in tax_grouped.values():
ait_obj.create(cr, uid, t)
return res
account_invoice_line()

View File

@ -328,10 +328,10 @@ class purchase_order_line(osv.osv):
lang=self.pool.get('res.partner').read(cr, uid, [partner_id])[0]['lang']
context={'lang':lang}
price = self.pool.get('product.pricelist').price_get(cr,uid,[pricelist], product, qty or 1.0, partner_id, {'uom': uom})[pricelist]
prod = self.pool.get('product.product').read(cr, uid, [product], ['taxes_id','name','seller_delay','uom_po_id','description_purchase'])[0]
prod = self.pool.get('product.product').read(cr, uid, [product], ['supplier_taxes_id','name','seller_delay','uom_po_id','description_purchase'])[0]
dt = (DateTime.now() + DateTime.RelativeDateTime(days=prod['seller_delay'] or 0.0)).strftime('%Y-%m-%d')
prod_name = self.pool.get('product.product').name_get(cr, uid, [product], context=context)[0][1]
res = {'value': {'price_unit': price, 'name':prod_name, 'taxes_id':prod['taxes_id'], 'date_planned': dt,'notes':prod['description_purchase']}}
res = {'value': {'price_unit': price, 'name':prod_name, 'taxes_id':prod['supplier_taxes_id'], 'date_planned': dt,'notes':prod['description_purchase']}}
domain = {}
if not uom:
res['value']['product_uom'] = prod['uom_po_id'][0]