diff -r 2b9489aee936 trytond/trytond/modules/account_invoice/invoice.py --- a/trytond/trytond/modules/account_invoice/invoice.py Tue Aug 02 22:23:13 2016 +0200 +++ b/trytond/trytond/modules/account_invoice/invoice.py Wed Nov 23 19:31:46 2016 +0100 @@ -890,34 +890,36 @@ ''' Return move line ''' - Currency = Pool().get('currency.currency') - res = {} + pool = Pool() + Currency = pool.get('currency.currency') + MoveLine = pool.get('account.move.line') + line = MoveLine() if self.currency.id != self.company.currency.id: with Transaction().set_context(date=self.currency_date): - res['amount_second_currency'] = Currency.compute( + line.amount_second_currency = Currency.compute( self.company.currency, amount, self.currency) - res['second_currency'] = self.currency.id + line.second_currency = self.currency.id else: - res['amount_second_currency'] = None - res['second_currency'] = None + line.amount_second_currency = None + line.second_currency = None if amount <= 0: - res['debit'], res['credit'] = -amount, 0 + line.debit, line.credit = -amount, 0 else: - res['debit'], res['credit'] = 0, amount - if res['amount_second_currency']: - res['amount_second_currency'] = ( - res['amount_second_currency'].copy_sign( - res['debit'] - res['credit'])) - res['account'] = self.account.id + line.debit, line.credit = 0, amount + if line.amount_second_currency: + line.amount_second_currency = ( + line.amount_second_currency.copy_sign( + line.debit - line.credit)) + line.account = self.account.id if self.account.party_required: - res['party'] = self.party.id - res['maturity_date'] = date - res['description'] = self.description - return res + line.party = self.party.id + line.maturity_date = date + line.description = self.description + return line - def create_move(self): + def get_move(self): ''' - Create account move for the invoice and return the created move + Compute account move for the invoice and return the created move ''' pool = Pool() Move = pool.get('account.move') @@ -933,9 +935,9 @@ total = Decimal('0.0') total_currency = Decimal('0.0') for line in move_lines: - total += line['debit'] - line['credit'] - if line['amount_second_currency']: - total_currency += line['amount_second_currency'] + total += line.debit - line.credit + if line.amount_second_currency: + total_currency += line.amount_second_currency term_lines = self.payment_term.compute(total, self.company.currency, self.invoice_date) @@ -943,28 +945,24 @@ if not term_lines: term_lines = [(Date.today(), total)] for date, amount in term_lines: - val = self._get_move_line(date, amount) - if val['amount_second_currency']: - remainder_total_currency += val['amount_second_currency'] - move_lines.append(val) + line = self._get_move_line(date, amount) + if line.amount_second_currency: + remainder_total_currency += line.amount_second_currency + move_lines.append(line) if not self.currency.is_zero(remainder_total_currency): - move_lines[-1]['amount_second_currency'] -= \ + move_lines[-1].amount_second_currency -= \ remainder_total_currency accounting_date = self.accounting_date or self.invoice_date period_id = Period.find(self.company.id, date=accounting_date) - move, = Move.create([{ - 'journal': self.journal.id, - 'period': period_id, - 'date': accounting_date, - 'origin': str(self), - 'company': self.company.id, - 'lines': [('create', move_lines)], - }]) - self.write([self], { - 'move': move.id, - }) + move = Move() + move.journal = self.journal + move.period = period_id + move.date = accounting_date + move.origin = self + move.company = self.company + move.lines = move_lines return move def set_number(self): @@ -1001,10 +999,9 @@ with Transaction().set_context( date=self.invoice_date or Date.today()): number = Sequence.get_id(sequence.id) - vals = {'number': number} + self.number = number if not self.invoice_date and self.type == 'out': - vals['invoice_date'] = Transaction().context['date'] - self.write([self], vals) + self.invoice_date = Transaction().context['date'] @classmethod def check_modify(cls, invoices): @@ -1064,7 +1061,7 @@ all_invoices += invoices update_tax = [i for i in all_invoices if i.state == 'draft'] super(Invoice, cls).write(*args) - if update_tax: + if update_tax and not Transaction().context.get('skip_update_taxes'): cls.update_taxes(update_tax) @classmethod @@ -1232,18 +1229,16 @@ ''' MoveLine = Pool().get('account.move.line') - new_invoices = [] - for invoice in invoices: - new_invoice, = cls.create([invoice._credit()]) - new_invoices.append(new_invoice) - if refund: - cls.post([new_invoice]) + new_invoices = cls.create([i._credit() for i in invoices]) + cls.update_taxes(new_invoices) + if refund: + cls.post(new_invoices) + for invoice, new_invoice in itertools.izip(invoices, new_invoices): if new_invoice.state == 'posted': MoveLine.reconcile([l for l in invoice.lines_to_pay if not l.reconciliation] + [l for l in new_invoice.lines_to_pay if not l.reconciliation]) - cls.update_taxes(new_invoices) return new_invoices @classmethod @@ -1263,10 +1258,30 @@ @ModelView.button @Workflow.transition('validated') def validate_invoice(cls, invoices): + Move = Pool().get('account.move') + + to_create = [] for invoice in invoices: - if invoice.type == 'in': + if invoice.type in ('in_invoice', 'in_credit_note'): invoice.set_number() - invoice.create_move() + move = invoice.get_move() + if move != invoice.move: + to_create.append(move._save_values) + invoices2move = {} + if to_create: + moves = Move.create(to_create) + for move in moves: + invoices2move[move.origin.id] = move.id + + to_write = [] + for invoice in invoices: + values = invoice._save_values + if invoice.id in invoices2move: + values['move'] = invoices2move[invoice.id] + if values: + to_write.extend(([invoice], values)) + if to_write: + cls.write(*to_write) @classmethod @ModelView.button @@ -1274,14 +1289,29 @@ def post(cls, invoices): Move = Pool().get('account.move') - moves = [] + to_create = [] for invoice in invoices: invoice.set_number() - moves.append(invoice.create_move()) - cls.write([i for i in invoices if i.state != 'posted'], { - 'state': 'posted', - }) - Move.post([m for m in moves if m.state != 'posted']) + move = invoice.get_move() + if move != invoice.move: + to_create.append(move._save_values) + invoices2move = {} + if to_create: + moves = Move.create(to_create) + for move in moves: + invoices2move[move.origin.id] = move.id + to_write = [] + for invoice in invoices: + values = invoice._save_values + if invoice.id in invoices2move: + values['move'] = invoices2move[invoice.id] + if values: + to_write.extend(([invoice], values)) + if to_write: + with Transaction().set_context(skip_update_taxes=True): + cls.write(*to_write) + cls.write(invoices, {'state': 'posted'}) + Move.post([i.move for i in invoices if i.move.state != 'posted']) for invoice in invoices: if invoice.type == 'out': invoice.print_invoice() @@ -1320,14 +1350,17 @@ cancel_moves = [] delete_moves = [] + to_write = [] for invoice in invoices: if invoice.move: if invoice.move.state == 'draft': delete_moves.append(invoice.move) elif not invoice.cancel_move: invoice.cancel_move = invoice.move.cancel() - invoice.save() cancel_moves.append(invoice.cancel_move) + to_write.extend(([invoice], invoice._save_values)) + if to_write: + cls.write(*to_write) if delete_moves: Move.delete(delete_moves) if cancel_moves: @@ -1883,6 +1916,7 @@ def _compute_taxes(self): pool = Pool() Currency = pool.get('currency.currency') + TaxLine = pool.get('account.tax.line') res = [] if self.type != 'line': @@ -1900,53 +1934,56 @@ date=self.invoice.currency_date): amount = Currency.compute(self.invoice.currency, amount, self.invoice.company.currency) - res.append({ - 'code': base_code, - 'amount': amount, - 'tax': tax['tax'], - }) + tax_line = TaxLine() + tax_line.code = base_code + tax_line.amount = amount + tax_line.tax = tax['tax'] + res.append(tax_line) return res def get_move_line(self): ''' - Return a list of move lines values for invoice line + Return a list of move lines instances for invoice line ''' - Currency = Pool().get('currency.currency') - res = {} + pool = Pool() + Currency = pool.get('currency.currency') + MoveLine = pool.get('account.move.line') + if self.type != 'line': return [] - res['description'] = self.description + line = MoveLine() + line.description = self.description if self.invoice.currency != self.invoice.company.currency: with Transaction().set_context(date=self.invoice.currency_date): amount = Currency.compute(self.invoice.currency, self.amount, self.invoice.company.currency) - res['amount_second_currency'] = self.amount - res['second_currency'] = self.invoice.currency.id + line.amount_second_currency = self.amount + line.second_currency = self.invoice.currency.id else: amount = self.amount - res['amount_second_currency'] = None - res['second_currency'] = None + line.amount_second_currency = None + line.second_currency = None if amount >= 0: if self.invoice.type == 'out': - res['debit'], res['credit'] = 0, amount + line.debit, line.credit = 0, amount else: - res['debit'], res['credit'] = amount, 0 + line.debit, line.credit = amount, 0 else: if self.invoice.type == 'out': - res['debit'], res['credit'] = -amount, 0 + line.debit, line.credit = -amount, 0 else: - res['debit'], res['credit'] = 0, -amount - if res['amount_second_currency']: - res['amount_second_currency'] = ( - res['amount_second_currency'].copy_sign( - res['debit'] - res['credit'])) - res['account'] = self.account.id + line.debit, line.credit = 0, -amount + if line.amount_second_currency: + line.amount_second_currency = ( + line.amount_second_currency.copy_sign( + line.debit - line.credit)) + line.account = self.account.id if self.account.party_required: - res['party'] = self.invoice.party.id + line.party = self.invoice.party.id computed_taxes = self._compute_taxes() if computed_taxes: - res['tax_lines'] = [('create', [tax for tax in computed_taxes])] - return [res] + line.tax_lines = computed_taxes + return [line] def _credit(self): ''' @@ -2162,47 +2199,52 @@ def get_move_line(self): ''' - Return a list of move lines values for invoice tax + Return a list of move lines instances for invoice tax ''' - Currency = Pool().get('currency.currency') - res = {} + pool = Pool() + Currency = pool.get('currency.currency') + MoveLine = pool.get('account.move.line') + TaxLine = pool.get('account.tax.line') + if not self.amount: return [] - res['description'] = self.description + + line = MoveLine() + line.description = self.description if self.invoice.currency != self.invoice.company.currency: with Transaction().set_context(date=self.invoice.currency_date): amount = Currency.compute(self.invoice.currency, self.amount, self.invoice.company.currency) - res['amount_second_currency'] = self.amount - res['second_currency'] = self.invoice.currency.id + line.amount_second_currency = self.amount + line.second_currency = self.invoice.currency.id else: amount = self.amount - res['amount_second_currency'] = None - res['second_currency'] = None + line.amount_second_currency = None + line.second_currency = None if amount >= 0: if self.invoice.type == 'out': - res['debit'], res['credit'] = 0, amount + line.debit, line.credit = 0, amount else: - res['debit'], res['credit'] = amount, 0 + line.debit, line.credit = amount, 0 else: if self.invoice.type == 'out': - res['debit'], res['credit'] = -amount, 0 + line.debit, line.credit = -amount, 0 else: - res['debit'], res['credit'] = 0, -amount - if res['amount_second_currency']: - res['amount_second_currency'] = ( - res['amount_second_currency'].copy_sign( - res['debit'] - res['credit'])) - res['account'] = self.account.id + line.debit, line.credit = 0, -amount + if line.amount_second_currency: + line.amount_second_currency = ( + line.amount_second_currency.copy_sign( + line.debit - line.credit)) + line.account = self.account.id if self.account.party_required: - res['party'] = self.invoice.party.id + line.party = self.invoice.party.id if self.tax_code: - res['tax_lines'] = [('create', [{ - 'code': self.tax_code.id, - 'amount': amount * self.tax_sign, - 'tax': self.tax and self.tax.id or None - }])] - return [res] + tax_line = TaxLine() + tax_line.code = self.tax_code + tax_line.amount = amount * self.tax_sign + tax_line.tax = self.tax + line.tax_lines = [tax_line] + return [line] def _credit(self): ''' Index: trytond/trytond/modules/account_payment_type/invoice.py =================================================================== --- a/trytond/trytond/modules/account_payment_type/invoice.py 2016-05-31 15:12:13.270350897 +0200 +++ b/trytond/trytond/modules/account_payment_type/invoice.py 2016-05-31 15:12:13.266350897 +0200 @@ -82,7 +82,7 @@ return self.company.party.customer_payment_type.id def _get_move_line(self, date, amount): - res = super(Invoice, self)._get_move_line(date, amount) + line = super(Invoice, self)._get_move_line(date, amount) if self.payment_type: - res['payment_type'] = self.payment_type - return res + line.payment_type = self.payment_type + return line Index: trytond/trytond/modules/analytic_invoice/invoice.py =================================================================== --- a/trytond/trytond/modules/analytic_invoice/invoice.py 2016-09-01 12:04:30.270350897 +0200 +++ b/trytond/trytond/modules/analytic_invoice/invoice.py 2016-09-01 12:04:30.270350897 +0200 @@ -1,5 +1,7 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. +import datetime + from trytond.model import fields from trytond.pool import PoolMeta, Pool @@ -26,32 +28,33 @@ return result - def get_analytic_entry(self, entry, value): - analytic_entry = {} - analytic_entry['name'] = self.description - analytic_entry['debit'] = value['debit'] - analytic_entry['credit'] = value['credit'] - analytic_entry['account'] = entry.account.id - analytic_entry['journal'] = self.invoice.journal.id - analytic_entry['date'] = (self.invoice.accounting_date or - self.invoice.invoice_date) - analytic_entry['reference'] = self.invoice.reference - analytic_entry['party'] = self.invoice.party.id - return analytic_entry + def get_analytic_entry(self, entry, line): + pool = Pool() + AnalyticLine = pool.get('analytic_account.line') + analytic_line = AnalyticLine() + analytic_line.name = self.description + analytic_line.debit = line.debit + analytic_line.credit = line.credit + analytic_line.account = entry.account + analytic_line.journal = self.invoice.journal + analytic_line.date = (self.invoice.accounting_date + or self.invoice.invoice_date or datetime.date.today()) + analytic_line.reference = self.invoice.reference + analytic_line.party = self.invoice.party + return analytic_line def get_move_line(self): - values = super(InvoiceLine, self).get_move_line() + lines = super(InvoiceLine, self).get_move_line() if self.analytic_accounts: - for value in values: - value['analytic_lines'] = [] - to_create = [] + for line in lines: + analytic_lines = [] for entry in self.analytic_accounts: if not entry.account: continue - to_create.append(self.get_analytic_entry(entry, value)) - if to_create: - value['analytic_lines'] = [('create', to_create)] - return values + analytic_lines.append(self.get_analytic_entry(entry, + line)) + line.analytic_lines = analytic_lines + return lines class AnalyticAccountEntry: