Skip to content

Commit

Permalink
[IMP] contract_invoice_merge_by_partner: Don't require to merge invoi…
Browse files Browse the repository at this point in the history
…ces later

Adapting source contract module, we don't need to rely on account_invoice_merge
functionality for having all the invoices merged.
  • Loading branch information
pedrobaeza committed Aug 1, 2017
1 parent 27fc8f9 commit b63340a
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 73 deletions.
3 changes: 2 additions & 1 deletion contract/__openerp__.py
@@ -1,11 +1,12 @@
# -*- coding: utf-8 -*-
# © 2004-2010 OpenERP SA
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# © 2015-2017 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
'name': 'Contracts Management recurring',
'version': '9.0.1.1.0',
'version': '9.0.1.1.1',
'category': 'Contract Management',
'license': 'AGPL-3',
'author': "OpenERP SA,"
Expand Down
89 changes: 55 additions & 34 deletions contract/models/contract.py
@@ -1,17 +1,16 @@
# -*- coding: utf-8 -*-
# © 2004-2010 OpenERP SA
# © 2014 Angel Moya <angel.moya@domatix.com>
# © 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# © 2015-2017 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from dateutil.relativedelta import relativedelta
import logging

from openerp import api, fields, models
from openerp import _, api, fields, models
from openerp.addons.decimal_precision import decimal_precision as dp
from openerp.exceptions import ValidationError
from openerp.tools.translate import _

_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -216,72 +215,94 @@ def _prepare_invoice_line(self, line, invoice_id):

@api.multi
def _prepare_invoice(self):
self.ensure_one()
if not self.partner_id:
contract = self[:1]
if not contract.partner_id:
raise ValidationError(
_("You must first select a Customer for Contract %s!") %
self.name)
journal = self.journal_id or self.env['account.journal'].search(
contract.name)
journal = contract.journal_id or self.env['account.journal'].search(
[('type', '=', 'sale'),
('company_id', '=', self.company_id.id)],
('company_id', '=', contract.company_id.id)],
limit=1)
if not journal:
raise ValidationError(
_("Please define a sale journal for the company '%s'.") %
(self.company_id.name or '',))
(contract.company_id.name or '',))
currency = (
self.pricelist_id.currency_id or
self.partner_id.property_product_pricelist.currency_id or
self.company_id.currency_id
contract.pricelist_id.currency_id or
contract.partner_id.property_product_pricelist.currency_id or
contract.company_id.currency_id
)
invoice = self.env['account.invoice'].new({
'reference': self.code,
'reference': ', '.join(self.filtered('code').mapped('code')),
'type': 'out_invoice',
'partner_id': self.partner_id.address_get(
'partner_id': contract.partner_id.address_get(
['invoice'])['invoice'],
'currency_id': currency.id,
'journal_id': journal.id,
'date_invoice': self.recurring_next_date,
'origin': self.name,
'company_id': self.company_id.id,
'contract_id': self.id,
'user_id': self.partner_id.user_id.id,
'date_invoice': contract.recurring_next_date,
'origin': ', '.join(self.mapped('name')),
'company_id': contract.company_id.id,
'contract_id': contract.id,
'user_id': contract.partner_id.user_id.id,
})
# Get other invoice values from partner onchange
invoice._onchange_partner_id()
return invoice._convert_to_write(invoice._cache)

@api.multi
def _create_invoice(self):
self.ensure_one()
"""Create the invoice from the source contracts.
:param self: Contract records. Invoice header data will be obtained
from the first record of this recordset.
:return Created invoice record.
"""
invoice_vals = self._prepare_invoice()
invoice = self.env['account.invoice'].create(invoice_vals)
for line in self.recurring_invoice_line_ids:
invoice_line_vals = self._prepare_invoice_line(line, invoice.id)
self.env['account.invoice.line'].create(invoice_line_vals)
invoice.compute_taxes()
return invoice

@api.multi
def recurring_create_invoice(self):
invoices = self.env['account.invoice']
for contract in self:
old_date = fields.Date.from_string(
contract.recurring_next_date or fields.Date.today())
contract.recurring_next_date or fields.Date.today(),
)
new_date = old_date + self.get_relalive_delta(
contract.recurring_rule_type, contract.recurring_interval)
contract.recurring_rule_type, contract.recurring_interval,
)
ctx = self.env.context.copy()
ctx.update({
'old_date': old_date,
'next_date': new_date,
# Force company for correct evaluate domain access rules
# For correct evaluating of domain access rules + properties
'force_company': contract.company_id.id,
})
# Re-read contract with correct company
invoices |= contract.with_context(ctx)._create_invoice()
obj = self.with_context(ctx)
for line in contract.recurring_invoice_line_ids:
invoice_line_vals = obj._prepare_invoice_line(line, invoice.id)
self.env['account.invoice.line'].create(invoice_line_vals)
contract.write({
'recurring_next_date': new_date.strftime('%Y-%m-%d')
})
invoice.compute_taxes()
return invoice

@api.multi
def _get_contracts2invoice(self, rest_contracts):
"""Method for being inherited by other modules to specify contract
grouping rules. By default, each contract is invoiced separately.
:param rest_contracts: Rest of the outstanding contracts to be invoiced
"""
self.ensure_one()
return self

@api.multi
def recurring_create_invoice(self):
invoices = self.env['account.invoice']
contracts = self
while contracts:
contracts2invoice = contracts[0]._get_contracts2invoice(contracts)
contracts -= contracts2invoice
invoices |= contracts2invoice._create_invoice()
return invoices

@api.model
Expand Down
7 changes: 0 additions & 7 deletions contract_invoice_merge_by_partner/README.rst
Expand Up @@ -8,13 +8,6 @@ Contract Invoice Merge By Partner

This module merges same partner invoices generated by contracts.

Installation
============

To install this module you need *account_invoice_merge*, available in:

* Install repository `OCA/account-invoicing <https://github.com/OCA/account-invoicing>`_.

Usage
=====

Expand Down
4 changes: 2 additions & 2 deletions contract_invoice_merge_by_partner/__openerp__.py
@@ -1,21 +1,21 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# Copyright 2017 Vicent Cubells <vicent.cubells@tecnativa.com>
# Copyright 2016-2017 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
'name': 'Contract Invoice Merge By Partner',
'summary': 'This module merges same partner invoices generated by '
'contracts',
'version': '9.0.1.0.0',
'version': '9.0.2.0.0',
'category': 'Account',
'license': 'AGPL-3',
'author': "Tecnativa, "
"Odoo Community Association (OCA)",
'website': 'http://www.tecnativa.com',
'depends': [
'contract',
'account_invoice_merge',
],
'data': [
'views/res_partner_view.xml',
Expand Down
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# Copyright 2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2016-2017 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2017 Vicent Cubells <vicent.cubells@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

Expand All @@ -11,17 +11,13 @@ class AccountAnalyticAccount(models.Model):
_inherit = 'account.analytic.account'

@api.multi
def recurring_create_invoice(self):
invoices = super(
AccountAnalyticAccount, self).recurring_create_invoice()
invoices_info = {}
invoices2unlink = AccountInvoice = self.env['account.invoice']
for partner in invoices.mapped('partner_id'):
invoices2merge = invoices.filtered(
lambda x: x.partner_id == partner)
if partner.contract_invoice_merge and len(invoices2merge) > 1:
invoices_info.update(invoices2merge.do_merge())
invoices2unlink += invoices2merge
invoices -= invoices2unlink
invoices2unlink.unlink()
return invoices | AccountInvoice.browse(invoices_info.keys())
def _get_contracts2invoice(self, rest_contracts):
"""Invoice together contracts from partners that have the option
checked and that have several contracts to invoice"""
if self.partner_id.contract_invoice_merge:
return rest_contracts.filtered(
lambda x: x.partner_id == self.partner_id
) | self
return super(AccountAnalyticAccount, self)._get_contracts2invoice(
rest_contracts
)
Expand Up @@ -43,14 +43,10 @@ def test_invoices_merged(self):
'product_id': self.product.id,
'uom_id': self.uom.id})],
})
self.contract2 = self.contract1.copy()
self.contract3 = self.contract1.copy()
self.contract4 = self.contract1.copy()
contracts = self.env['account.analytic.account'].search([
('partner_id', '=', self.partner.id)
])
invoices = contracts.recurring_create_invoice()
inv_draft = invoices.filtered(lambda x: x.state == 'draft')
self.assertEqual(len(inv_draft), 1)
inv_cancel = invoices.filtered(lambda x: x.state == 'cancel')
self.assertFalse(inv_cancel)
contract2 = self.contract1.copy()
contract3 = self.contract1.copy()
contract4 = self.contract1.copy()
contracts = self.contract1 + contract2 + contract3 + contract4
invoice = contracts.recurring_create_invoice()
self.assertEqual(len(invoice), 1)
self.assertEqual(len(invoice.invoice_line_ids), 4)
9 changes: 6 additions & 3 deletions contract_payment_mode/models/contract.py
Expand Up @@ -19,7 +19,10 @@ def on_change_partner_id(self):
@api.multi
def _prepare_invoice(self):
invoice_vals = super(AccountAnalyticAccount, self)._prepare_invoice()
if self.payment_mode_id:
invoice_vals['payment_mode_id'] = self.payment_mode_id.id
invoice_vals['partner_bank_id'] = self.partner_id.bank_ids[:1].id
contract = self[:1]
if contract.payment_mode_id:
invoice_vals['payment_mode_id'] = contract.payment_mode_id.id
invoice_vals['partner_bank_id'] = (
contract.partner_id.bank_ids[:1].id
)
return invoice_vals

0 comments on commit b63340a

Please sign in to comment.