Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[9.0] [MIG] account_invoice_merge #209

Merged
merged 2 commits into from
Dec 8, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions account_invoice_merge/README.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3

==============
Merge invoices
==============

Expand All @@ -10,15 +15,20 @@ the conditions to allow merging:
* Currency should be the same
* Account receivable account should be the same

Usage
=====

.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/95/9.0

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/account-invoicing/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
`here <https://github.com/OCA/account-invoicing/issues/new?body=module:%20account_invoice_merge%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Bugs are tracked on `GitHub Issues
<https://github.com/OCA/account-invoicing/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.

Credits
=======
Expand All @@ -32,12 +42,14 @@ Contributors
Maintainer
----------

.. image:: http://odoo-community.org/logo.png
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: http://odoo-community.org
:target: https://odoo-community.org

This module is maintained by the OCA.

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

To contribute to this module, please visit http://odoo-community.org.
To contribute to this module, please visit https://odoo-community.org.
22 changes: 2 additions & 20 deletions account_invoice_merge/__init__.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (c) 2010-2011 Elico Corp. All Rights Reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import invoice

from . import models
from . import wizard
32 changes: 5 additions & 27 deletions account_invoice_merge/__openerp__.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,11 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (c) 2010-2011 Elico Corp. All Rights Reserved.
# Author: Ian Li <ian.li@elico-corp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# © 2010-2011 Elico Corp. All Rights Reserved.
# Author: Ian Li <ian.li@elico-corp.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
'name': 'Account Invoice Merge Wizard',
'version': '8.0.1.1.1',
'version': '9.0.1.0.0',
'category': 'Finance',
'author': "Elico Corp,Odoo Community Association (OCA)",
'website': 'http://www.openerp.net.cn',
Expand All @@ -31,10 +14,5 @@
'data': [
'wizard/invoice_merge_view.xml',
],
'test': [
],
'demo': [],
'installable': False,
'active': False,
'certificate': False,
'installable': True,
}
3 changes: 3 additions & 0 deletions account_invoice_merge/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-

from . import account_invoice
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
from openerp import models, api
from openerp import workflow
from openerp.osv.orm import browse_record, browse_null
from openerp.tools import float_is_zero


class account_invoice(models.Model):
class AccountInvoice(models.Model):
_inherit = "account.invoice"

@api.model
Expand All @@ -36,8 +37,9 @@ def _get_invoice_key_cols(self):
@api.model
def _get_invoice_line_key_cols(self):
fields = [
'name', 'origin', 'discount', 'invoice_line_tax_id', 'price_unit',
'name', 'origin', 'discount', 'invoice_line_tax_ids', 'price_unit',
'product_id', 'account_id', 'account_analytic_id',
'uom_id'
]
for field in ['analytics_id']:
if field in self.env['account.invoice.line']._fields:
Expand All @@ -58,15 +60,17 @@ def _get_first_invoice_fields(self, invoice):
'state': 'draft',
'reference': '%s' % (invoice.reference or '',),
'name': '%s' % (invoice.name or '',),
'fiscal_position': invoice.fiscal_position.id,
'payment_term': invoice.payment_term.id,
'period_id': invoice.period_id.id,
'invoice_line': {},
'fiscal_position_id': invoice.fiscal_position_id.id,
'payment_term_id': invoice.payment_term_id.id,
# 'period_id': invoice.period_id.id,
'invoice_line_ids': {},
'partner_bank_id': invoice.partner_bank_id.id,
}

@api.multi
def do_merge(self, keep_references=True, date_invoice=False):
def do_merge(
self, keep_references=True, date_invoice=False,
remove_empty_invoice_lines=True):
"""
To merge similar type of account invoices.
Invoices will only be merged if:
Expand All @@ -83,6 +87,7 @@ def do_merge(self, keep_references=True, date_invoice=False):
@return: new account invoice id

"""

def make_key(br, fields):
list_key = []
for field in fields:
Expand All @@ -91,12 +96,12 @@ def make_key(br, fields):
if not field_val:
field_val = False
if (isinstance(field_val, browse_record) and
field != 'invoice_line_tax_id'):
field != 'invoice_line_tax_ids'):
field_val = field_val.id
elif isinstance(field_val, browse_null):
field_val = False
elif (isinstance(field_val, list) or
field == 'invoice_line_tax_id'):
field == 'invoice_line_tax_ids'):
field_val = ((6, 0, tuple([v.id for v in field_val])),)
list_key.append((field, field_val))
list_key.sort()
Expand Down Expand Up @@ -143,44 +148,55 @@ def make_key(br, fields):
(invoice_infos['reference'] or '') + \
(' %s' % (account_invoice.reference,))
client_refs.add(account_invoice.reference)
for invoice_line in account_invoice.invoice_line:

for invoice_line in account_invoice.invoice_line_ids:
cols = self._get_invoice_line_key_cols()
line_key = make_key(
invoice_line, self._get_invoice_line_key_cols())
o_line = invoice_infos['invoice_line'].setdefault(line_key, {})
uos_factor = (invoice_line.uos_id and
invoice_line.uos_id.factor or 1.0)
invoice_line, cols)

o_line = invoice_infos['invoice_line_ids'].setdefault(line_key,
{})

if o_line:
# merge the line with an existing line
o_line['quantity'] += invoice_line.quantity * \
uos_factor / o_line['uom_factor']
o_line['quantity'] += invoice_line.quantity
else:
# append a new "standalone" line
for field in ('quantity', 'uos_id'):
field_val = getattr(invoice_line, field)
if isinstance(field_val, browse_record):
field_val = field_val.id
o_line[field] = field_val
o_line['uom_factor'] = uos_factor
o_line['quantity'] = invoice_line.quantity

allinvoices = []
allnewinvoices = []
invoices_info = {}
qty_prec = self.env['decimal.precision'].precision_get(
'Product Unit of Measure')
for invoice_key, (invoice_data, old_ids) in new_invoices.iteritems():
# skip merges with only one invoice
if len(old_ids) < 2:
allinvoices += (old_ids or [])
continue
# cleanup invoice line data
for key, value in invoice_data['invoice_line'].iteritems():
del value['uom_factor']
for key, value in invoice_data['invoice_line_ids'].iteritems():
value.update(dict(key))
invoice_data['invoice_line'] = [
(0, 0, value) for value in
invoice_data['invoice_line'].itervalues()]

if remove_empty_invoice_lines:
invoice_data['invoice_line_ids'] = [
(0, 0, value) for value in
invoice_data['invoice_line_ids'].itervalues() if
not float_is_zero(
value['quantity'], precision_digits=qty_prec)]
else:
invoice_data['invoice_line_ids'] = [
(0, 0, value) for value in
invoice_data['invoice_line_ids'].itervalues()]

if date_invoice:
invoice_data['date_invoice'] = date_invoice

# create the new invoice
newinvoice = self.with_context(is_merge=True).create(invoice_data)
invoices_info.update({newinvoice.id: old_ids})
allinvoices.append(newinvoice.id)
allnewinvoices.append(newinvoice)
# make triggers pointing to the old invoices point to the new
# invoice
for old_id in old_ids:
Expand All @@ -190,9 +206,10 @@ def make_key(br, fields):
workflow.trg_validate(
self.env.uid, 'account.invoice', old_id, 'invoice_cancel',
self.env.cr)

# make link between original sale order or purchase order
# None if sale is not installed
so_obj = self.env['sale.order']\
so_obj = self.env['sale.order'] \
if 'sale.order' in self.env.registry else False
invoice_line_obj = self.env['account.invoice.line']
# None if purchase is not installed
Expand All @@ -209,6 +226,7 @@ def make_key(br, fields):
if invoice_line_ids:
so_line.write(
{'invoice_lines': [(6, 0, invoice_line_ids)]})

# recreate link (if any) between original analytic account line
# (invoice time sheet for example) and this new invoice
anal_line_obj = self.env['account.analytic.line']
Expand All @@ -217,4 +235,8 @@ def make_key(br, fields):
todos = anal_line_obj.search(
[('invoice_id', 'in', invoices_info[new_invoice_id])])
todos.write({'invoice_id': new_invoice_id})

for new_invoice in allnewinvoices:
new_invoice.compute_taxes()

return invoices_info
19 changes: 0 additions & 19 deletions account_invoice_merge/wizard/__init__.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,3 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (c) 2010-2011 Elico Corp. All Rights Reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from . import invoice_merge
32 changes: 7 additions & 25 deletions account_invoice_merge/wizard/invoice_merge.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,12 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (c) 2010-2011 Elico Corp. All Rights Reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# © 2010-2011 Elico Corp. All Rights Reserved.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from openerp import models, fields, api, exceptions
from openerp.tools.translate import _


class invoice_merge(models.TransientModel):
class InvoiceMerge(models.TransientModel):
_name = "invoice.merge"
_description = "Merge Partner Invoice"

Expand All @@ -39,10 +23,8 @@ def _dirty_check(self):
raise exceptions.Warning(
_('Please select multiple invoice to merge in the list '
'view.'))
inv_obj = self.env['account.invoice']
invs = inv_obj.read(ids,
['account_id', 'state', 'type', 'company_id',
'partner_id', 'currency_id', 'journal_id'])

invs = self.env['account.invoice'].browse(ids)
for d in invs:
if d['state'] != 'draft':
raise exceptions.Warning(
Expand Down Expand Up @@ -78,7 +60,7 @@ def fields_view_get(self, view_id=None, view_type='form', toolbar=False,
@param context: A standard dictionary
@return: New arch of view.
"""
res = super(invoice_merge, self).fields_view_get(
res = super(InvoiceMerge, self).fields_view_get(
view_id=view_id, view_type=view_type, toolbar=toolbar,
submenu=False)
self._dirty_check()
Expand Down