[MERGE] opw 18200 : don't erase unit price when erasing the product in invoice line
[odoo/odoo.git] / addons / account / invoice.py
old mode 100755 (executable)
new mode 100644 (file)
index c1872db..7f02f07
@@ -88,32 +88,14 @@ class account_invoice(osv.osv):
         return [('none', _('Free Reference'))]
 
     def _amount_residual(self, cr, uid, ids, name, args, context=None):
-        res = {}
-        if context is None:
-            context = {}
-
-        cur_obj = self.pool.get('res.currency')
-        data_inv = self.browse(cr, uid, ids, context=context)
-        for inv in data_inv:
-            if inv.reconciled:
-                res[inv.id] = 0.0
-                continue
-            inv_total = inv.amount_total
-            context_unreconciled = context.copy()
-            for lines in inv.move_lines:
-                if lines.currency_id and lines.currency_id.id == inv.currency_id.id:
-                    if inv.type in ('out_invoice','in_refund'):
-                        inv_total += lines.amount_currency
-                    else:
-                        inv_total -= lines.amount_currency
-                else:
-                   context_unreconciled.update({'date': lines.date})
-                   amount_in_invoice_currency = cur_obj.compute(cr, uid, inv.company_id.currency_id.id, inv.currency_id.id,abs(lines.debit-lines.credit),round=False,context=context_unreconciled)
-                   inv_total -= amount_in_invoice_currency
-
-            result = inv_total
-            res[inv.id] =  self.pool.get('res.currency').round(cr, uid, inv.currency_id, result)
-        return res
+        result = {}
+        for invoice in self.browse(cr, uid, ids, context=context):
+            result[invoice.id] = 0.0
+            if invoice.move_id:
+                for m in invoice.move_id.line_id:
+                    if m.account_id.type in ('receivable','payable'):
+                        result[invoice.id] += m.amount_residual_currency
+        return result
 
     # Give Journal Items related to the payment reconciled to this invoice
     # Return ids of partial and total payments related to the selected invoices
@@ -229,8 +211,8 @@ class account_invoice(osv.osv):
             \n* The \'Open\' state is used when user create invoice,a invoice number is generated.Its in open state till user does not pay invoice. \
             \n* The \'Paid\' state is set automatically when invoice is paid.\
             \n* The \'Cancelled\' state is used when user cancel invoice.'),
-        'date_invoice': fields.date('Invoice Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, help="Keep empty to use the current date"),
-        'date_due': fields.date('Due Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]},
+        'date_invoice': fields.date('Invoice Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, select=True, help="Keep empty to use the current date"),
+        'date_due': fields.date('Due Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, select=True,
             help="If you use payment terms, the due date will be computed automatically at the generation "\
                 "of accounting entries. If you keep the payment term and the due date empty, it means direct payment. The payment term may compute several due dates, for example 50% now, 50% in one month."),
         'partner_id': fields.many2one('res.partner', 'Partner', change_default=True, readonly=True, required=True, states={'draft':[('readonly',False)]}),
@@ -283,7 +265,7 @@ class account_invoice(osv.osv):
         'move_lines':fields.function(_get_lines, method=True, type='many2many', relation='account.move.line', string='Entry Lines'),
         'residual': fields.function(_amount_residual, method=True, digits_compute=dp.get_precision('Account'), string='Residual',
             store={
-                'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line'], 50),
+                'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line','move_id'], 50),
                 'account.invoice.tax': (_get_invoice_tax, None, 50),
                 'account.invoice.line': (_get_invoice_line, ['price_unit','invoice_line_tax_id','quantity','discount','invoice_id'], 50),
                 'account.move.line': (_get_invoice_from_line, None, 50),
@@ -346,8 +328,7 @@ class account_invoice(osv.osv):
     def get_log_context(self, cr, uid, context=None):
         if context is None:
             context = {}
-        mob_obj = self.pool.get('ir.model.data')
-        res = mob_obj.get_object_reference(cr, uid, 'account', 'invoice_form')
+        res = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', 'invoice_form')
         view_id = res and res[1] or False
         context.update({'view_id': view_id})
         return context
@@ -372,6 +353,8 @@ class account_invoice(osv.osv):
                 raise orm.except_orm(_('Unknown Error'), str(e))
 
     def confirm_paid(self, cr, uid, ids, context=None):
+        if context is None:
+            context = {}
         self.write(cr, uid, ids, {'state':'paid'}, context=context)
         for inv_id, name in self.name_get(cr, uid, ids, context=context):
             message = _("Invoice '%s' is paid.") % name
@@ -379,6 +362,8 @@ class account_invoice(osv.osv):
         return True
 
     def unlink(self, cr, uid, ids, context=None):
+        if context is None:
+            context = {}
         invoices = self.read(cr, uid, ids, ['state'], context=context)
         unlink_ids = []
         for t in invoices:
@@ -559,7 +544,11 @@ class account_invoice(osv.osv):
             journal_ids = obj_journal.search(cr, uid, [('company_id','=',company_id), ('type', '=', journal_type)])
             if journal_ids:
                 val['journal_id'] = journal_ids[0]
-            else:
+            res_journal_default = self.pool.get('ir.values').get(cr, uid, 'default', 'type=%s' % (type), ['account.invoice'])
+            for r in res_journal_default:
+                if r[1] == 'journal_id' and r[2] in journal_ids:
+                    val['journal_id'] = r[2]
+            if not val.get('journal_id', False):
                 raise osv.except_osv(_('Configuration Error !'), (_('Can\'t find any account journal of %s type for this company.\n\nYou can create one in the menu: \nConfiguration\Financial Accounting\Accounts\Journals.') % (journal_type)))
             dom = {'journal_id':  [('id', 'in', journal_ids)]}
         else:
@@ -577,7 +566,6 @@ class account_invoice(osv.osv):
                 val['currency_id'] = False
             else:
                 val['currency_id'] = company.currency_id.id
-
         return {'value': val, 'domain': dom}
 
     # go from canceled state to draft state
@@ -614,12 +602,15 @@ class account_invoice(osv.osv):
         return res
 
     def copy(self, cr, uid, id, default={}, context=None):
+        if context is None:
+            context = {}
         default.update({
             'state':'draft',
             'number':False,
             'move_id':False,
             'move_name':False,
             'internal_number': False,
+            'period_id': False
         })
         if 'date_invoice' not in default:
             default.update({
@@ -926,7 +917,7 @@ class account_invoice(osv.osv):
             }
             period_id = inv.period_id and inv.period_id.id or False
             if not period_id:
-                period_ids = self.pool.get('account.period').search(cr, uid, [('date_start','<=',inv.date_invoice or time.strftime('%Y-%m-%d')),('date_stop','>=',inv.date_invoice or time.strftime('%Y-%m-%d'))])
+                period_ids = self.pool.get('account.period').search(cr, uid, [('date_start','<=',inv.date_invoice or time.strftime('%Y-%m-%d')),('date_stop','>=',inv.date_invoice or time.strftime('%Y-%m-%d')), ('company_id', '=', inv.company_id.id)])
                 if period_ids:
                     period_id = period_ids[0]
             if period_id:
@@ -1009,7 +1000,7 @@ class account_invoice(osv.osv):
         return True
 
     def action_cancel(self, cr, uid, ids, *args):
-        context = {} # TODO in v6.1
+        context = {} # TODO: Use context from arguments
         account_move_obj = self.pool.get('account.move')
         invoices = self.read(cr, uid, ids, ['move_id', 'payment_ids'])
         move_ids = [] # ones that we will need to remove
@@ -1268,7 +1259,7 @@ class account_invoice_line(osv.osv):
                     t = t - (p * l[2].get('quantity'))
                     taxes = l[2].get('invoice_line_tax_id')
                     if len(taxes[0]) >= 3 and taxes[0][2]:
-                        taxes = tax_obj.browse(cr, uid, taxes[0][2])
+                        taxes = tax_obj.browse(cr, uid, list(taxes[0][2]))
                         for tax in tax_obj.compute_all(cr, uid, taxes, p,l[2].get('quantity'), context.get('address_invoice_id', False), l[2].get('product_id', False), context.get('partner_id', False))['taxes']:
                             t = t - tax['amount']
             return t
@@ -1291,7 +1282,7 @@ class account_invoice_line(osv.osv):
         'invoice_line_tax_id': fields.many2many('account.tax', 'account_invoice_line_tax', 'invoice_line_id', 'tax_id', 'Taxes', domain=[('parent_id','=',False)]),
         'note': fields.text('Notes'),
         'account_analytic_id':  fields.many2one('account.analytic.account', 'Analytic Account'),
-        'company_id': fields.related('invoice_id','company_id',type='many2one',relation='res.company',string='Company',store=True),
+        'company_id': fields.related('invoice_id','company_id',type='many2one',relation='res.company',string='Company', store=True, readonly=True),
         'partner_id': fields.related('invoice_id','partner_id',type='many2one',relation='res.partner',string='Partner',store=True)
     }
     _defaults = {
@@ -1307,10 +1298,7 @@ class account_invoice_line(osv.osv):
         if not partner_id:
             raise osv.except_osv(_('No Partner Defined !'),_("You must first select a partner !") )
         if not product:
-            if type in ('in_invoice', 'in_refund'):
-                return {'value': {'categ_id': False}, 'domain':{'product_uom':[]}}
-            else:
-                return {'value': {'price_unit': 0.0, 'categ_id': False}, 'domain':{'product_uom':[]}}
+            return {'value': {'price_unit': 0.0, 'categ_id': False}, 'domain':{'product_uom':[]}}
         part = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context)
         fpos_obj = self.pool.get('account.fiscal.position')
         fpos = fposition_id and fpos_obj.browse(cr, uid, fposition_id, context=context) or False
@@ -1320,65 +1308,6 @@ class account_invoice_line(osv.osv):
         result = {}
         res = self.pool.get('product.product').browse(cr, uid, product, context=context)
 
-        if company_id:
-            property_obj = self.pool.get('ir.property')
-            account_obj = self.pool.get('account.account')
-            in_pro_id = property_obj.search(cr, uid, [('name','=','property_account_income'),('res_id','=','product.template,'+str(res.product_tmpl_id.id)+''),('company_id','=',company_id)])
-            if not in_pro_id:
-                in_pro_id = property_obj.search(cr, uid, [('name','=','property_account_income_categ'),('res_id','=','product.template,'+str(res.categ_id.id)+''),('company_id','=',company_id)])
-            exp_pro_id = property_obj.search(cr, uid, [('name','=','property_account_expense'),('res_id','=','product.template,'+str(res.product_tmpl_id.id)+''),('company_id','=',company_id)])
-            if not exp_pro_id:
-                exp_pro_id = property_obj.search(cr, uid, [('name','=','property_account_expense_categ'),('res_id','=','product.template,'+str(res.categ_id.id)+''),('company_id','=',company_id)])
-
-            if not in_pro_id:
-                in_acc = res.product_tmpl_id.property_account_income
-                in_acc_cate = res.categ_id.property_account_income_categ
-                if in_acc:
-                    app_acc_in = in_acc
-                else:
-                    app_acc_in = in_acc_cate
-            else:
-                # Get the fields from the ir.property record
-                my_value = property_obj.read(cr,uid,in_pro_id,['name','value_reference','res_id'])
-                # Parse the value_reference field to get the ID of the account.account record
-                account_id = int (my_value[0]["value_reference"].split(",")[1])
-                # Use the ID of the account.account record in the browse for the account.account record
-                app_acc_in = account_obj.browse(cr, uid, account_id, context=context)
-            if not exp_pro_id:
-                ex_acc = res.product_tmpl_id.property_account_expense
-                ex_acc_cate = res.categ_id.property_account_expense_categ
-                if ex_acc:
-                    app_acc_exp = ex_acc
-                else:
-                    app_acc_exp = ex_acc_cate
-            else:
-                app_acc_exp = account_obj.browse(cr, uid, exp_pro_id, context=context)[0]
-            if not in_pro_id and not exp_pro_id:
-                in_acc = res.product_tmpl_id.property_account_income
-                in_acc_cate = res.categ_id.property_account_income_categ
-                ex_acc = res.product_tmpl_id.property_account_expense
-                ex_acc_cate = res.categ_id.property_account_expense_categ
-                if in_acc or ex_acc:
-                    app_acc_in = in_acc
-                    app_acc_exp = ex_acc
-                else:
-                    app_acc_in = in_acc_cate
-                    app_acc_exp = ex_acc_cate
-            if app_acc_in and app_acc_in.company_id.id != company_id and app_acc_exp and app_acc_exp.company_id.id != company_id:
-                in_res_id = account_obj.search(cr, uid, [('name','=',app_acc_in.name),('company_id','=',company_id)])
-                exp_res_id = account_obj.search(cr, uid, [('name','=',app_acc_exp.name),('company_id','=',company_id)])
-                if not in_res_id and not exp_res_id:
-                    raise osv.except_osv(_('Configuration Error !'),
-                        _('Can not find account chart for this company, Please Create account.'))
-                in_obj_acc = account_obj.browse(cr, uid, in_res_id, context=context)
-                exp_obj_acc = account_obj.browse(cr, uid, exp_res_id, context=context)
-                if in_acc or ex_acc:
-                    res.product_tmpl_id.property_account_income = in_obj_acc[0]
-                    res.product_tmpl_id.property_account_expense = exp_obj_acc[0]
-                else:
-                    res.categ_id.property_account_income_categ = in_obj_acc[0]
-                    res.categ_id.property_account_expense_categ = exp_obj_acc[0]
-
         if type in ('out_invoice','out_refund'):
             a = res.product_tmpl_id.property_account_income.id
             if not a:
@@ -1405,6 +1334,7 @@ class account_invoice_line(osv.osv):
 
         domain = {}
         result['uos_id'] = res.uom_id.id or uom or False
+        result['note'] = res.description
         if result['uos_id']:
             res2 = res.uom_id.category_id.id
             if res2:
@@ -1548,7 +1478,7 @@ class account_invoice_tax(osv.osv):
         'base_amount': fields.float('Base Code Amount', digits_compute=dp.get_precision('Account')),
         'tax_code_id': fields.many2one('account.tax.code', 'Tax Code', help="The tax basis of the tax declaration."),
         'tax_amount': fields.float('Tax Code Amount', digits_compute=dp.get_precision('Account')),
-        'company_id': fields.related('account_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True),
+        'company_id': fields.related('account_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
         'factor_base': fields.function(_count_factor, method=True, string='Multipication factor for Base code', type='float', multi="all"),
         'factor_tax': fields.function(_count_factor, method=True, string='Multipication factor Tax code', type='float', multi="all")
     }