diff --git a/addons/account_voucher/__openerp__.py b/addons/account_voucher/__openerp__.py index 6d6203d3d69..e7c75881ee9 100644 --- a/addons/account_voucher/__openerp__.py +++ b/addons/account_voucher/__openerp__.py @@ -43,6 +43,7 @@ "account_voucher_report.xml", "wizard/account_voucher_unreconcile_view.xml", "wizard/account_statement_from_invoice_view.xml", + "wizard/account_voucher_payment_option.xml", "account_voucher_view.xml", "voucher_payment_receipt_view.xml", "voucher_sales_purchase_view.xml", diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index 24bc8ca43c1..58709bbdbc7 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -539,6 +539,38 @@ class account_voucher(osv.osv): self.write(cr, uid, ids, res) return True + def do_check(self, cr, uid, ids, context=None): + cur_obj = self.pool.get('res.currency') + mod_obj = self.pool.get('ir.model.data') + if context is None: + context = {} + voucher = self.browse(cr, uid, [ids[0]], context=context)[0] + debit= credit = 0.0 + if voucher.line_dr_ids: + for line in voucher.line_dr_ids: + debit += line.amount_original + if voucher.line_cr_ids: + for line in voucher.line_cr_ids: + credit += line.amount_original + if (voucher.amount + debit) != credit: + model_data_ids = mod_obj.search(cr, uid,[('model', '=', 'ir.ui.view'), ('name', '=', 'view_account_voucher_pay_writeoff')], context=context) + resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id'] + context.update({'voucher_id': ids[0]}) + return { + 'name': _('Information addendum'), + 'context': context, + 'view_type': 'form', + 'view_mode': 'tree,form', + 'res_model': 'account.voucher.pay.writeoff', + 'views': [(resource_id, 'form')], + 'type': 'ir.actions.act_window', + 'target': 'new', + 'nodestroy': True + } + else: + self.action_move_line_create(cr, uid, ids, context=context) + return True + def unlink(self, cr, uid, ids, context=None): for t in self.read(cr, uid, ids, ['state'], context=context): if t['state'] not in ('draft', 'cancel'): @@ -566,7 +598,6 @@ class account_voucher(osv.osv): return {'value':res} def action_move_line_create(self, cr, uid, ids, context=None): - def _get_payment_term_lines(term_id, amount): term_pool = self.pool.get('account.payment.term') if term_id and amount: @@ -646,7 +677,6 @@ class account_voucher(osv.osv): line_total = line_total - currency_pool.compute(cr, uid, inv.currency_id.id, company_currency, inv.tax_amount) elif inv.type == 'purchase': line_total = line_total + currency_pool.compute(cr, uid, inv.currency_id.id, company_currency, inv.tax_amount) - for line in inv.line_ids: if not line.amount: continue @@ -714,7 +744,6 @@ class account_voucher(osv.osv): else: account_id = inv.partner_id.property_account_payable.id move_line['account_id'] = account_id - move_line_pool.create(cr, uid, move_line) self.write(cr, uid, [inv.id], { @@ -728,6 +757,110 @@ class account_voucher(osv.osv): move_line_pool.reconcile_partial(cr, uid, rec_ids) return True + def pay_and_reconcile(self, cr, uid, ids, pay_amount, pay_account_id, period_id, pay_journal_id, writeoff_acc_id, writeoff_period_id, writeoff_journal_id, context=None, name=''): + if context is None: + context = {} + seq_obj = self.pool.get('ir.sequence') + #TODO check if we can use different period for payment and the writeoff line + assert len(ids)==1, "Can only pay one voucher at a time" + voucher = self.browse(cr, uid, ids[0]) + if voucher.number: + name = voucher.number + elif voucher.journal_id.sequence_id: + name = seq_obj.get_id(cr, uid, voucher.journal_id.sequence_id.id) + else: + raise osv.except_osv(_('Error !'), _('Please define a sequence on the journal !')) + if not voucher.reference: + ref = name.replace('/','') + else: + ref = voucher.reference + + src_account_id = voucher.account_id.id + # Take the seq as name for move + types = {'sale': -1, 'purchase': 1, 'payment': 1, 'receipt': -1} + direction = types[voucher.type] + #take the choosen date + if 'date_p' in context and context['date_p']: + date = context['date_p'] + else: + date = time.strftime('%Y-%m-%d') + # Take the amount in currency and the currency of the payment + if 'amount_currency' in context and context['amount_currency'] and 'currency_id' in context and context['currency_id']: + amount_currency = context['amount_currency'] + currency_id = context['currency_id'] + else: + amount_currency = False + currency_id = False + pay_journal = self.pool.get('account.journal').read(cr, uid, pay_journal_id, ['type'], context=context) + if voucher.type in ('sale', 'receipt'): + if pay_journal['type'] == 'bank': + entry_type = 'bank_pay_voucher' # Bank payment + else: + entry_type = 'pay_voucher' # Cash payment + else: + entry_type = 'cont_voucher' + + # Pay attention to the sign for both debit/credit AND amount_currency + l1 = { + 'debit': direction * pay_amount>0 and direction * pay_amount, + 'credit': direction * pay_amount<0 and - direction * pay_amount, + 'account_id': src_account_id, + 'partner_id': voucher.partner_id.id, + 'ref':ref, + 'date': date, + 'currency_id':currency_id, + 'amount_currency':amount_currency and direction * amount_currency or 0.0, + 'company_id': voucher.company_id.id, + } + l2 = { + 'debit': direction * pay_amount<0 and - direction * pay_amount, + 'credit': direction * pay_amount>0 and direction * pay_amount, + 'account_id': pay_account_id, + 'partner_id': voucher.partner_id.id, + 'ref':ref, + 'date': date, + 'currency_id':currency_id, + 'amount_currency':amount_currency and - direction * amount_currency or 0.0, + 'company_id': voucher.company_id.id, + } + + if not name: + name = voucher.line_ids and voucher.line_ids[0].name or voucher.number + l1['name'] = name + l2['name'] = name + lines = [(0, 0, l1), (0, 0, l2)] + move = {'ref': ref, 'line_id': lines, 'journal_id': pay_journal_id, 'period_id': period_id, 'name': name, 'date': date} + move_id = self.pool.get('account.move').create(cr, uid, move, context=context) + + line_ids = [] + total = 0.0 + line = self.pool.get('account.move.line') + move_ids = [move_id,] + if voucher.move_id: + move_ids.append(voucher.move_id.id) + cr.execute('SELECT id FROM account_move_line '\ + 'WHERE move_id IN %s', + ((move_id,),)) + lines = line.browse(cr, uid, map(lambda x: x[0], cr.fetchall()) ) + for l in lines: + if l.account_id.id == src_account_id: + line_ids.append(l.id) + total += (l.debit or 0.0) - (l.credit or 0.0) + + voc_id, name = self.name_get(cr, uid, [voucher.id], context=context)[0] + if (not round(total,self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))) or writeoff_acc_id: + self.pool.get('account.move.line').reconcile(cr, uid, line_ids, 'manual', writeoff_acc_id, writeoff_period_id, writeoff_journal_id, context) + else: + code = voucher.currency_id.code + # TODO: use currency's formatting function + msg = _("Invoice '%s' is paid partially: %s%s of %s%s (%s%s remaining)") % \ + (name, pay_amount, code, voucher.amount_total, code, total, code) + self.log(cr, uid, voc_id, msg) + self.pool.get('account.move.line').reconcile_partial(cr, uid, line_ids, 'manual', context) + # Update the stored value (fields.function), so we write to trigger recompute + self.write(cr, uid, ids, {'state':'posted'}, context=context) + return True + def copy(self, cr, uid, id, default={}, context=None): default.update({ 'state': 'draft', diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index 83b6243a627..1fdb54f1edc 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -217,7 +217,7 @@