[FIX] bugfixed the incoming tax on onchange of product in supplier invoice and refund
[odoo/odoo.git] / addons / account / invoice.py
index abfbeb2..de343ee 100644 (file)
@@ -107,8 +107,8 @@ class account_invoice(osv.osv):
             paid_amt = 0.0
             to_pay = inv.amount_total
             for lines in inv.move_lines:
-                paid_amt = paid_amt + lines.credit + lines.debit
-            res[inv.id] = to_pay - paid_amt
+                paid_amt = paid_amt - lines.credit + lines.debit
+            res[inv.id] = to_pay - abs(paid_amt)
         return res
 
     def _get_lines(self, cr, uid, ids, name, arg, context=None):
@@ -196,11 +196,11 @@ class account_invoice(osv.osv):
             ('in_refund','Supplier Refund'),
             ],'Type', readonly=True, select=True),
 
-        'number': fields.char('Invoice Number', size=32, readonly=True, help="Uniq number of the invoice, computed automatically when the invoice is created."),
+        'number': fields.char('Invoice Number', size=32, readonly=True, help="Unique number of the invoice, computed automatically when the invoice is created."),
         'reference': fields.char('Invoice Reference', size=64, help="The partner reference of this invoice."),
         'reference_type': fields.selection(_get_reference_type, 'Reference Type',
             required=True),
-        'comment': fields.text('Additionnal Information'),
+        'comment': fields.text('Additional Information'),
 
         'state': fields.selection([
             ('draft','Draft'),
@@ -208,7 +208,7 @@ class account_invoice(osv.osv):
             ('proforma2','Pro-forma'),
             ('open','Open'),
             ('paid','Done'),
-            ('cancel','Canceled')
+            ('cancel','Cancelled')
         ],'State', select=True, readonly=True),
 
         'date_invoice': fields.date('Date Invoiced', states={'open':[('readonly',True)],'close':[('readonly',True)]}),
@@ -255,7 +255,11 @@ class account_invoice(osv.osv):
         'company_id': fields.many2one('res.company', 'Company', required=True),
         'check_total': fields.float('Total', digits=(16,2), states={'open':[('readonly',True)],'close':[('readonly',True)]}),
         'reconciled': fields.function(_reconciled, method=True, string='Paid/Reconciled', type='boolean',
-            store=True, help="The account moves of the invoice have been reconciled with account moves of the payment(s)."),
+            store={
+                'account.invoice': (lambda self, cr, uid, ids, c={}: ids, None, 50),
+                'account.move.line': (_get_invoice_from_line, None, 50),
+                'account.move.reconcile': (_get_invoice_from_reconcile, None, 50),
+            }, help="The account moves of the invoice have been reconciled with account moves of the payment(s)."),
         'partner_bank': fields.many2one('res.partner.bank', 'Bank Account',
             help='The bank account to pay to or to be paid from'),
         'move_lines':fields.function(_get_lines , method=True,type='many2many' , relation='account.move.line',string='Move Lines'),
@@ -270,6 +274,7 @@ class account_invoice(osv.osv):
             help="Remaining amount due."),
         'payment_ids': fields.function(_compute_lines, method=True, relation='account.move.line', type="many2many", string='Payments'),
         'move_name': fields.char('Account Move', size=64),
+        'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position')
     }
     _defaults = {
         'type': _get_type,
@@ -283,7 +288,7 @@ class account_invoice(osv.osv):
         'reference_type': lambda *a: 'none',
     }
 
-    def unlink(self, cr, uid, ids):
+    def unlink(self, cr, uid, ids, context=None):
         invoices = self.read(cr, uid, ids, ['state'])
         unlink_ids = []
         for t in invoices:
@@ -291,7 +296,7 @@ class account_invoice(osv.osv):
                 unlink_ids.append(t['id'])
             else:
                 raise osv.except_osv(_('Invalid action !'), _('Cannot delete invoice(s) which are already opened or paid !'))
-        osv.osv.unlink(self, cr, uid, unlink_ids)
+        osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
         return True
 
 #   def get_invoice_address(self, cr, uid, ids):
@@ -305,6 +310,7 @@ class account_invoice(osv.osv):
         partner_payment_term = False
         acc_id = False
         bank_id = False
+        fiscal_position = False
 
         opt = [('uid', str(uid))]
         if partner_id:
@@ -318,7 +324,7 @@ class account_invoice(osv.osv):
                 acc_id = p.property_account_receivable.id
             else:
                 acc_id = p.property_account_payable.id
-
+            fiscal_position = p.property_account_position and p.property_account_position.id or False
             partner_payment_term = p.property_payment_term and p.property_payment_term.id or False
             if p.bank_ids:
                 bank_id = p.bank_ids[0].id
@@ -328,6 +334,7 @@ class account_invoice(osv.osv):
             'address_invoice_id': invoice_addr_id,
             'account_id': acc_id,
             'payment_term': partner_payment_term,
+            'fiscal_position': fiscal_position
             }
         }
 
@@ -426,7 +433,8 @@ class account_invoice(osv.osv):
             for taxe in ait_obj.compute(cr, uid, id).values():
                 ait_obj.create(cr, uid, taxe)
          # Update the stored value (fields.function), so we write to trigger recompute
-        self.pool.get('account.invoice').write(cr, uid, ids, {}, context=context)
+        self.pool.get('account.invoice').write(cr, uid, ids, {}, context=context)    
+#        self.pool.get('account.invoice').write(cr, uid, ids, {}, context=context)
         return True
 
     def button_compute(self, cr, uid, ids, context=None, set_total=False):
@@ -473,12 +481,11 @@ class account_invoice(osv.osv):
     def action_move_create(self, cr, uid, ids, *args):
         ait_obj = self.pool.get('account.invoice.tax')
         cur_obj = self.pool.get('res.currency')
-        self.button_compute(cr, uid, ids, context={}, set_total=False)
+
         for inv in self.browse(cr, uid, ids):
             if inv.move_id:
                 continue
-            if inv.type in ('in_invoice', 'in_refund') and abs(inv.check_total - inv.amount_total) >= (inv.currency_id.rounding/2.0):
-                raise osv.except_osv(_('Bad total !'), _('Please verify the price of the invoice !\nThe real total does not match the computed total.'))
+
             if not inv.date_invoice:
                 self.write(cr, uid, [inv.id], {'date_invoice':time.strftime('%Y-%m-%d')})
             company_currency = inv.company_id.currency_id.id
@@ -508,6 +515,9 @@ class account_invoice(osv.osv):
                     if not key in tax_key:
                         raise osv.except_osv(_('Warning !'), _('Taxes missing !'))
 
+            if inv.type in ('in_invoice', 'in_refund') and abs(inv.check_total - inv.amount_total) >= (inv.currency_id.rounding/2.0):
+                raise osv.except_osv(_('Bad total !'), _('Please verify the price of the invoice !\nThe real total does not match the computed total.'))
+
             # one move line per tax line
             iml += ait_obj.move_line_get(cr, uid, inv.id)
 
@@ -616,7 +626,7 @@ class account_invoice(osv.osv):
             journal = self.pool.get('account.journal').browse(cr, uid, journal_id)
             if journal.centralisation:
                 raise osv.except_osv(_('UserError'),
-                        _('Can not create invoice move on centralized journal'))
+                        _('Can not create invoice move on centralised journal'))
             move = {'ref': inv.number, 'line_id': line, 'journal_id': journal_id, 'date': date}
             period_id=inv.period_id and inv.period_id.id or False
             if not period_id:
@@ -628,9 +638,6 @@ class account_invoice(osv.osv):
                 for i in line:
                     i[2]['period_id'] = period_id
 
-            if not 'name' in move:
-                move['name'] = inv.name or '/'
-
             move_id = self.pool.get('account.move').create(cr, uid, move)
             new_move_name = self.pool.get('account.move').browse(cr, uid, move_id).name
             # make the invoice point to that move
@@ -666,13 +673,10 @@ class account_invoice(osv.osv):
         obj_inv = self.browse(cr, uid, ids)[0]
         for (id, invtype, number, move_id, reference) in cr.fetchall():
             if not number:
-                flag = True
-                for seq in obj_inv.journal_id.fy_seq_id:
-                    if seq.fiscalyear_id.id == obj_inv.move_id.period_id.fiscalyear_id.id:
-                        number =  self.pool.get('ir.sequence').get_id(cr, uid,seq.sequence_id.id)
-                        flag = False
-                        break
-                if flag:
+                if obj_inv.journal_id.invoice_sequence_id:
+                    sid = obj_inv.journal_id.invoice_sequence_id.id
+                    number = self.pool.get('ir.sequence').get_id(cr, uid, sid, 'id=%s', {'fiscalyear_id': obj_inv.period_id.fiscalyear_id.id})
+                else:
                     number = self.pool.get('ir.sequence').get(cr, uid,
                             'account.invoice.' + invtype)
                 if invtype in ('in_invoice', 'in_refund'):
@@ -860,7 +864,8 @@ class account_invoice(osv.osv):
             'ref':invoice.number,
         }
 
-        name = invoice.invoice_line and invoice.invoice_line[0].name or invoice.number
+        if not name:
+            name = invoice.invoice_line and invoice.invoice_line[0].name or invoice.number
         l1['name'] = name
         l2['name'] = name
 
@@ -873,7 +878,7 @@ class account_invoice(osv.osv):
         line = self.pool.get('account.move.line')
         cr.execute('select id from account_move_line where move_id in ('+str(move_id)+','+str(invoice.move_id.id)+')')
         lines = line.browse(cr, uid, map(lambda x: x[0], cr.fetchall()) )
-        for l in lines:
+        for l in lines+invoice.payment_ids:
             if l.account_id.id==src_account_id:
                 line_ids.append(l.id)
                 total += (l.debit or 0.0) - (l.credit or 0.0)
@@ -943,7 +948,7 @@ class account_invoice_line(osv.osv):
                 price_unit = price_unit - tax['amount']
         return {'price_unit': price_unit,'invoice_line_tax_id': tax_id}
 
-    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, context=None):
+    def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, address_invoice_id=False, context=None):
         if context is None:
             context = {}
         if not partner_id:
@@ -954,22 +959,12 @@ class account_invoice_line(osv.osv):
             else:
                 return {'value': {'price_unit': 0.0}, 'domain':{'product_uom':[]}}
         part = self.pool.get('res.partner').browse(cr, uid, partner_id)
+        fpos = fposition_id and self.pool.get('account.fiscal.position').browse(cr, uid, fposition_id) or False
+
         lang=part.lang
         context.update({'lang': lang})
+        result = {}
         res = self.pool.get('product.product').browse(cr, uid, product, context=context)
-        taxep=None
-        tax_obj = self.pool.get('account.tax')
-        if type in ('out_invoice', 'out_refund'):
-            tax_id = self.pool.get('account.fiscal.position').map_tax(cr, uid, part, res.taxes_id)
-        else:
-            tax_id = self.pool.get('account.fiscal.position').map_tax(cr, uid, part, res.supplier_taxes_id)
-        if type in ('in_invoice', 'in_refund'):
-            result = self.product_id_change_unit_price_inv(cr, uid, tax_id, price_unit, qty, address_invoice_id, product, partner_id, context=context)
-        else:
-            result = {'price_unit': res.list_price, 'invoice_line_tax_id': tax_id}
-
-        if not name:
-            result['name'] = res.name
 
         if type in ('out_invoice','out_refund'):
             a =  res.product_tmpl_id.property_account_income.id
@@ -980,10 +975,27 @@ class account_invoice_line(osv.osv):
             if not a:
                 a = res.categ_id.property_account_expense_categ.id
 
-        a = self.pool.get('account.fiscal.position').map_account(cr, uid, part, a)
+        a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, a)
         if a:
             result['account_id'] = a
 
+        taxep=None
+        tax_obj = self.pool.get('account.tax')
+        if type in ('out_invoice', 'out_refund'):
+            taxes = res.taxes_id and res.taxes_id or (a and self.pool.get('account.account').browse(cr, uid,a).tax_ids or False)
+            tax_id = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, taxes)
+        else:
+            taxes = res.supplier_taxes_id and res.supplier_taxes_id or (a and self.pool.get('account.account').browse(cr, uid,a).tax_ids or False)
+            tax_id = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, taxes)
+        if type in ('in_invoice', 'in_refund'):
+            to_update = self.product_id_change_unit_price_inv(cr, uid, tax_id, price_unit, qty, address_invoice_id, product, partner_id, context=context)
+            result.update(to_update)
+        else:
+            result.update({'price_unit': res.list_price, 'invoice_line_tax_id': tax_id})
+
+        if not name:
+            result['name'] = res.name
+
         domain = {}
         result['uos_id'] = uom or res.uom_id.id or False
         if result['uos_id']:
@@ -1048,15 +1060,14 @@ class account_invoice_line(osv.osv):
             'taxes':line.invoice_line_tax_id,
         }
     #
-    # Set the tax field according to the account and the partner
+    # Set the tax field according to the account and the fiscal position
     #
-    def onchange_account_id(self, cr, uid, ids, partner_id,account_id):
-        if not (partner_id and account_id):
+    def onchange_account_id(self, cr, uid, ids, fposition_id, account_id):
+        if not account_id:
             return {}
         taxes = self.pool.get('account.account').browse(cr, uid, account_id).tax_ids
-        part = self.pool.get('res.partner').browse(cr, uid, partner_id)
-
-        res = self.pool.get('account.fiscal.position').map_tax(cr, uid, part, taxes)
+        fpos = fposition_id and self.pool.get('account.fiscal.position').browse(cr, uid, fposition_id) or False
+        res = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, taxes)
         r = {'value':{'invoice_line_tax_id': res}}
         return r
 account_invoice_line()