ACCOUNT, ACCOUNT_TAX_INCLUDE, PURCHASE, PURCHASE_TAX_INCLUDE, SALE_TAX_INCLUDE: fix...
[odoo/odoo.git] / addons / account_tax_include / invoice_tax_incl.py
index 1866dc7..15d6f3a 100644 (file)
@@ -34,36 +34,42 @@ from osv import fields, osv
 import ir
 
 class account_invoice(osv.osv):
-       def _amount_untaxed(self, cr, uid, ids, prop, unknow_none,unknow_dict):
+       def _amount_untaxed(self, cr, uid, ids, name, args, context={}):
                res = {}
                for invoice in self.browse(cr,uid,ids):
-                       res[invoice.id]= reduce( lambda x, y: x+y.price_subtotal,
-                                                                       invoice.invoice_line,0)
+                       if invoice.price_type == 'tax_included':
+                               res[invoice.id]= invoice.amount_total - invoice.amount_tax
+                       else:
+                               res[invoice.id] = super(account_invoice, self)._amount_untaxed(cr, uid, [invoice.id], name, args, context)[invoice.id]
                return res
 
-       def _amount_total(self, cr, uid, ids, prop, unknow_none,unknow_dict):
+       def _amount_tax(self, cr, uid, ids, name, args, context={}):
                res = {}
                for invoice in self.browse(cr,uid,ids):
-                       res[invoice.id]= reduce( lambda x, y: x+y.price_subtotal_incl,
-                                                                       invoice.invoice_line,0)
+                       if invoice.price_type == 'tax_included':
+                               res[invoice.id] = reduce( lambda x, y: x+y.amount, invoice.tax_line,0)
+                       else:
+                               res[invoice.id] = super(account_invoice, self)._amount_tax(cr, uid, [invoice.id], name, args, context)[invoice.id]
                return res
 
-       def _amount_tax(self, cr, uid, ids, prop, unknow_none,unknow_dict):
+       def _amount_total(self, cr, uid, ids, name, args, context={}):
                res = {}
                for invoice in self.browse(cr,uid,ids):
-                       res[invoice.id]= reduce( lambda x, y: x+y.amount,
-                                                                       invoice.tax_line,0)
+                       if invoice.price_type == 'tax_included':
+                               res[invoice.id]= reduce( lambda x, y: x+y.price_subtotal_incl, invoice.invoice_line,0)
+                       else:
+                               res[invoice.id] = super(account_invoice, self)._amount_total(cr, uid, [invoice.id], name, args, context)[invoice.id]
                return res
 
        _inherit = "account.invoice"
        _columns = {
                'price_type': fields.selection([('tax_included','Tax included'),
                                                                                ('tax_excluded','Tax excluded')],
-                                                                          'Price method', required=True, readonly=True,
-                                                                          states={'draft':[('readonly',False)]}),
+                                                                               'Price method', required=True, readonly=True,
+                                                                               states={'draft':[('readonly',False)]}),
                'amount_untaxed': fields.function(_amount_untaxed, digits=(16,2), method=True,string='Untaxed Amount'),
-               'amount_tax': fields.function(_amount_tax, method=True, string='Tax'),
-               'amount_total': fields.function(_amount_total, method=True, string='Total'),
+               'amount_tax': fields.function(_amount_tax, method=True, string='Tax', store=True),
+               'amount_total': fields.function(_amount_total, method=True, string='Total', store=True),
        }
        _defaults = {
                'price_type': lambda *a: 'tax_excluded',
@@ -72,66 +78,65 @@ account_invoice()
 
 class account_invoice_line(osv.osv):
        _inherit = "account.invoice.line"
-       def _amount_line(self, cr, uid, ids, prop, unknow_none,unknow_dict):
+       def _amount_line(self, cr, uid, ids, name, args, context={}):
                """
                Return the subtotal excluding taxes with respect to price_type.
                """
-               #cur_obj = self.pool.get('res.currency')
-               cur = False
-               res = {}
-               tax_obj = self.pool.get('account.tax')
-               for line in self.browse(cr, uid, ids):
-                       res[line.id] = line.price_unit * line.quantity * (1-(line.discount or 0.0)/100.0)
-               
-                       if line.product_id and line.invoice_id.price_type == 'tax_included':
-                               taxes = tax_obj.compute_inv(cr, uid,line.product_id.taxes_id,
-                                                                                       res[line.id],
-                                                                                       line.quantity)
-                               amount = 0
-                               for t in taxes : amount = amount + t['amount']
-                               cur = cur or line.invoice_id.currency_id
-                               res[line.id]= cur.round(cr, uid, cur, res[line.id] - amount) 
-               return res
-
-       def _amount_line_incl(self, cr, uid, ids, prop, unknow_none,unknow_dict):
-               """
-               Return the subtotal including taxes with respect to price_type.
-               """
                res = {}
-               cur = False
                tax_obj = self.pool.get('account.tax')
+               res = super(account_invoice_line, self)._amount_line(cr, uid, ids, name, args, context)
+               res2 = res.copy()
                for line in self.browse(cr, uid, ids):
-                       res[line.id] = line.price_unit * line.quantity * (1-(line.discount or 0.0)/100.0)
-                       if line.product_id:
-                               prod_taxe_ids = line.product_id and [t.id for t in line.product_id.taxes_id ] or []
-                               prod_taxe_ids.sort()
-                               line_taxe_ids = [ t.id for t in line.invoice_line_tax_id if t]
-                               line_taxe_ids.sort()
-                               if prod_taxe_ids == line_taxe_ids :
-                                       continue
-                       else : continue
-                       
-                       res[line.id] = line.price_unit * line.quantity * (1-(line.discount or 0.0)/100.0)
-                       if line.invoice_id.price_type == 'tax_included':                        
-                               # remove product taxes
-                               taxes = tax_obj.compute_inv(cr, uid,line.product_id.taxes_id,
-                                                                                       res[line.id],
-                                                                                       line.quantity)
-                               amount = 0
-                               for t in taxes : amount = amount + t['amount']
-                               res[line.id]= res[line.id] - amount
-                       ## Add line taxes
-                       taxes = tax_obj.compute(cr, uid,line.invoice_line_tax_id, res[line.id], line.quantity)
-                       amount = 0
-                       for t in taxes : amount = amount + t['amount']
-                       cur = cur or line.invoice_id.currency_id                                        
-                       res[line.id]= cur.round(cr, uid, cur, res[line.id] + amount) 
+                       if line.invoice_id.price_type == 'tax_included':
+                               product_taxes = None
+                               if line.product_id:
+                                       if line.invoice_id.type in ('out_invoice', 'out_refund'):
+                                               product_taxes = line.product_id.taxes_id
+                                       else:
+                                               product_taxes = line.product_id.supplier_taxes_id
+                               if product_taxes:
+                                       for tax in tax_obj.compute_inv(cr, uid, product_taxes, res[line.id]/line.quantity, line.quantity):
+                                               res[line.id] = res[line.id] - tax['amount']
+                               else:
+                                       for tax in tax_obj.compute_inv(cr, uid,line.invoice_line_tax_id, res[line.id]/line.quantity, line.quantity):
+                                               res[line.id] = res[line.id] - tax['amount']
+                       if name == 'price_subtotal_incl' and line.invoice_id.price_type == 'tax_included':
+                               prod_taxe_ids = None
+                               line_taxe_ids = None
+                               if product_taxes:
+                                       prod_taxe_ids = [ t.id for t in product_taxes ]
+                                       prod_taxe_ids.sort()
+                                       line_taxe_ids = [ t.id for t in line.invoice_line_tax_id ]
+                                       line_taxe_ids.sort()
+                               if product_taxes and prod_taxe_ids == line_taxe_ids:
+                                       res[line.id] = res2[line.id]
+                               elif not line.product_id:
+                                       res[line.id] = res2[line.id]
+                               else:
+                                       for tax in tax_obj.compute(cr, uid, line.invoice_line_tax_id, res[line.id]/line.quantity, line.quantity):
+                                               res[line.id] = res[line.id] + tax['amount']
+                       res[line.id]= round(res[line.id], 2)
                return res
 
+       def _price_unit_default(self, cr, uid, context={}):
+               if 'check_total' in context:
+                       t = context['check_total']
+                       if context.get('price_type', False) == 'tax_included':
+                               for l in context.get('invoice_line', {}):
+                                       if len(l) >= 3 and l[2]:
+                                               p = l[2].get('price_unit', 0) * (1-l[2].get('discount', 0)/100.0)
+                                               t = t - (p * l[2].get('quantity'))
+                               return t
+                       return super(account_invoice_line, self)._price_unit_default(cr, uid, context)
+               return 0
 
        _columns = {
-               'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal w/o vat'),
-               'price_subtotal_incl': fields.function(_amount_line_incl, method=True, string='Subtotal'),
+               'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal w/o tax'),
+               'price_subtotal_incl': fields.function(_amount_line, method=True, string='Subtotal'),
+       }
+
+       _defaults = {
+               'price_unit': _price_unit_default,
        }
 
        #
@@ -150,37 +155,55 @@ class account_invoice_line(osv.osv):
                cur = inv.currency_id
 
                for line in inv.invoice_line:
-                       price_unit = line.price_unit
-                       if line.product_id:
-                               prod_taxe_ids = [ t.id for t in line.product_id.taxes_id ]
-                               prod_taxe_ids.sort()
-                               line_taxe_ids = [ t.id for t in line.invoice_line_tax_id]
-                               line_taxe_ids.sort()
-                       if line.product_id and prod_taxe_ids != line_taxe_ids :
-                               price_unit= reduce( lambda x, y: x-y['amount'],
-                                                                       tax_obj.compute_inv(cr, uid,line.product_id.taxes_id,
-                                                                                                               line.price_unit * (1-(line.discount or 0.0)/100.0), line.quantity),
-                                                                       price_unit)
-                               taxes =tax_obj.compute(cr, uid, line.invoice_line_tax_id,
-                                                                          (price_unit *(1.0-(line['discount'] or 0.0)/100.0)),
-                                                                          line.quantity, inv.address_invoice_id.id)
-                       else:
-                               taxes= 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)
-
-                       res.append( {
-                               'type':'src', 
-                               'name':line.name, 
-                               'price_unit':price_unit, 
-                               'quantity':line.quantity, 
-                               'price':line.quantity*price_unit * (1.0- (line.discount or 0.0)/100.0),
+                       res.append( self.move_line_get_item(cr, uid, line, context))
+                       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, inv.partner_id):
+                               if inv.type in ('out_invoice', 'in_invoice'):
+                                       res[-1]['tax_code_id'] = tax['base_code_id']
+                                       res[-1]['tax_amount'] = tax['price_unit'] * line['quantity'] * tax['base_sign']
+                               else:
+                                       res[-1]['ta_code_id'] = tax['ref_base_code_id']
+                                       res[-1]['tax_amount'] = tax['price_unit'] * line['quantity'] * tax['ref_base_sign']
+               return res
+
+       def move_line_get_item(self, cr, uid, line, context={}):
+               return {
+                               'type':'src',
+                               'name':line.name,
+                               'price_unit':line.price_unit,
+                               'quantity':line.quantity,
+                               'price':line.price_subtotal,
                                'account_id':line.account_id.id,
                                'product_id': line.product_id.id,
                                'uos_id':line.uos_id.id,
                                'account_analytic_id':line.account_analytic_id.id,
-                       })
-                       for tax in taxes:
+                       }
+
+       def product_id_change_unit_price_inv(self, cr, uid, tax_id, price_unit, qty, address_invoice_id, product, partner_id, context={}):
+               if context.get('price_type', False) == 'tax_included':
+                       return {'price_unit': price_unit,'invoice_line_tax_id': tax_id}
+               else:
+                       return super(account_invoice_line, self).product_id_change_unit_price_inv(cr, uid, tax_id, price_unit, qty, address_invoice_id, product, partner_id, context=context)
+
+       def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, price_unit=False, address_invoice_id=False, price_type='tax_excluded', context={}):
+               context.update({'price_type': price_type})
+               return super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, price_unit, address_invoice_id, context=context)
+account_invoice_line()
+
+class account_invoice_tax(osv.osv):
+       _inherit = "account.invoice.tax"
+
+       def compute(self, cr, uid, invoice_id):
+               tax_grouped = {}
+               tax_obj = self.pool.get('account.tax')
+               cur_obj = self.pool.get('res.currency')
+               inv = self.pool.get('account.invoice').browse(cr, uid, invoice_id)
+               cur = inv.currency_id
+
+               if inv.price_type=='tax_excluded':
+                       return super(account_invoice_tax,self).compute(cr, uid, invoice_id)
+
+               for line in inv.invoice_line:
+                       for tax in tax_obj.compute_inv(cr, uid, line.invoice_line_tax_id, (line.price_unit * (1-(line.discount or 0.0)/100.0)), line.quantity, inv.address_invoice_id.id, line.product_id, inv.partner_id):
                                val={}
                                val['invoice_id'] = inv.id
                                val['name'] = tax['name']
@@ -189,11 +212,6 @@ class account_invoice_line(osv.osv):
                                val['sequence'] = tax['sequence']
                                val['base'] = tax['price_unit'] * line['quantity']
 
-                               res[-1]['price']-=tax['amount']
-
-                               #
-                               # Setting the tax account and amount for the line
-                               #
                                if inv.type in ('out_invoice','in_invoice'):
                                        val['base_code_id'] = tax['base_code_id']
                                        val['tax_code_id'] = tax['tax_code_id']
@@ -207,9 +225,6 @@ class account_invoice_line(osv.osv):
                                        val['tax_amount'] = val['amount'] * tax['ref_tax_sign']
                                        val['account_id'] = tax['account_paid_id'] or line.account_id.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] = val
@@ -218,10 +233,7 @@ class account_invoice_line(osv.osv):
                                        tax_grouped[key]['base'] += val['base']
                                        tax_grouped[key]['base_amount'] += val['base_amount']
                                        tax_grouped[key]['tax_amount'] += val['tax_amount']
-                       res[-1]['price']=cur_obj.round(cr, uid, cur, res[-1]['price'])
-               # delete automatic tax lines for this invoice
-               cr.execute("DELETE FROM account_invoice_tax WHERE NOT manual AND invoice_id=%d", (invoice_id,))
-               for t in tax_grouped.values():
-                       ait_obj.create(cr, uid, t)
-               return res
-account_invoice_line()
+
+               return tax_grouped
+account_invoice_tax()
+