From b1df261c67cca259c7f44c3e871af5310b33f0dd Mon Sep 17 00:00:00 2001 From: "elicoidal@hotmail.com" Date: Thu, 10 May 2012 16:38:07 +0800 Subject: [PATCH 01/96] [ADD] several new modules double confirmation, web wysiwyg etc. (../elico-6.0/ rev 42) --- account_invoice_merge/__init__.py | 25 +++ account_invoice_merge/__openerp__.py | 48 ++++++ .../i18n/account_invoice_merge.pot | 76 +++++++++ account_invoice_merge/i18n/zh_CN.po | 85 ++++++++++ account_invoice_merge/invoice.py | 146 ++++++++++++++++++ account_invoice_merge/wizard/__init__.py | 24 +++ account_invoice_merge/wizard/invoice_merge.py | 101 ++++++++++++ .../wizard/invoice_merge_view.xml | 41 +++++ 8 files changed, 546 insertions(+) create mode 100644 account_invoice_merge/__init__.py create mode 100644 account_invoice_merge/__openerp__.py create mode 100644 account_invoice_merge/i18n/account_invoice_merge.pot create mode 100644 account_invoice_merge/i18n/zh_CN.po create mode 100644 account_invoice_merge/invoice.py create mode 100644 account_invoice_merge/wizard/__init__.py create mode 100644 account_invoice_merge/wizard/invoice_merge.py create mode 100644 account_invoice_merge/wizard/invoice_merge_view.xml diff --git a/account_invoice_merge/__init__.py b/account_invoice_merge/__init__.py new file mode 100644 index 00000000000..705773a8086 --- /dev/null +++ b/account_invoice_merge/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2011-2012 Erico-Corp (). +# +# 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 . +# +############################################################################## +import invoice +import wizard + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/account_invoice_merge/__openerp__.py b/account_invoice_merge/__openerp__.py new file mode 100644 index 00000000000..2126dda32e1 --- /dev/null +++ b/account_invoice_merge/__openerp__.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (c) 2010-2011 Elico Corp. All Rights Reserved. +# Author: Ian Li +# +# 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 . +# +############################################################################## + +{ + 'name': 'Account Invoice Merge Wizard', + 'version': '1.1', + 'category': 'Finance', + 'description': """ +This module adds an action in the invoices lists to merge of invoices. Here are the condition to allow merge: +- Type should be the same (customer Invoice, supplier invoice, Customer or Supplier Refund) +- Partner should be the same +- Currency should be the same +- Account receivable account should be the same +No merge is done at invoice line level. + """, + 'author': 'Elico Corp', + 'website': 'http://www.openerp.net.cn', + 'depends': ['base', 'account'], + 'data': [ + 'wizard/invoice_merge_view.xml', + ], + 'test': [ + ], + 'demo': [], + 'installable': True, + 'active': False, + 'certificate': False, +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_invoice_merge/i18n/account_invoice_merge.pot b/account_invoice_merge/i18n/account_invoice_merge.pot new file mode 100644 index 00000000000..fdc6fb62388 --- /dev/null +++ b/account_invoice_merge/i18n/account_invoice_merge.pot @@ -0,0 +1,76 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_invoice_merge +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 6.0.3\n" +"Report-Msgid-Bugs-To: support@openerp.com\n" +"POT-Creation-Date: 2012-05-07 02:54+0000\n" +"PO-Revision-Date: 2012-05-07 02:54+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: account_invoice_merge +#: model:ir.model,name:account_invoice_merge.model_account_invoice +msgid "Invoice" +msgstr "" + +#. module: account_invoice_merge +#: code:addons/account_invoice_merge/wizard/invoice_merge.py:86 +#, python-format +msgid "Partner Invoice" +msgstr "" + +#. module: account_invoice_merge +#: view:invoice.merge:0 +msgid " Please note that: \n" +" \n" +" Invoices will only be merged if: \n" +" * Invoices are in draft \n" +" * Invoices belong to the same partner \n" +" * Invoices are have same company, partner, address, currency, journal, salesman, account, type \n" +" \n" +" Lines will only be merged if: \n" +" * Invoice lines are exactly the same except for the product,quantity and unit \n" +" " +msgstr "" + +#. module: account_invoice_merge +#: code:addons/account_invoice_merge/wizard/invoice_merge.py:48 +#, python-format +msgid "Please select multiple invoice to merge in the list view." +msgstr "" + +#. module: account_invoice_merge +#: view:invoice.merge:0 +msgid "Merge Invoices" +msgstr "" + +#. module: account_invoice_merge +#: code:addons/account_invoice_merge/wizard/invoice_merge.py:47 +#, python-format +msgid "Warning" +msgstr "" + +#. module: account_invoice_merge +#: view:invoice.merge:0 +#: model:ir.actions.act_window,name:account_invoice_merge.action_view_invoice_merge +#: model:ir.model,name:account_invoice_merge.model_invoice_merge +msgid "Merge Partner Invoice" +msgstr "" + +#. module: account_invoice_merge +#: view:invoice.merge:0 +msgid "Cancel" +msgstr "" + +#. module: account_invoice_merge +#: view:invoice.merge:0 +msgid "Are you sure you want to merge these invoices ?" +msgstr "" + diff --git a/account_invoice_merge/i18n/zh_CN.po b/account_invoice_merge/i18n/zh_CN.po new file mode 100644 index 00000000000..4f3640b0e2b --- /dev/null +++ b/account_invoice_merge/i18n/zh_CN.po @@ -0,0 +1,85 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_invoice_merge +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 6.0.3\n" +"Report-Msgid-Bugs-To: support@openerp.com\n" +"POT-Creation-Date: 2012-05-07 02:54+0000\n" +"PO-Revision-Date: 2012-05-07 02:54+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: account_invoice_merge +#: model:ir.model,name:account_invoice_merge.model_account_invoice +msgid "Invoice" +msgstr "发票" + +#. module: account_invoice_merge +#: code:addons/account_invoice_merge/wizard/invoice_merge.py:86 +#, python-format +msgid "Partner Invoice" +msgstr "合作伙伴发票" + +#. module: account_invoice_merge +#: view:invoice.merge:0 +msgid " Please note that: \n" +" \n" +" Invoices will only be merged if: \n" +" * Invoices are in draft \n" +" * Invoices belong to the same partner \n" +" * Invoices are have same company, partner, address, currency, journal, salesman, account, type \n" +" \n" +" Lines will only be merged if: \n" +" * Invoice lines are exactly the same except for the product,quantity and unit \n" +" " +msgstr " 请注意: \n" +" \n" +"仅符合下列条件的发票,才会被合并: \n" +" * 发票确认之前,还在草稿状态。 \n" +" * 发票属于同一合作伙伴。 \n" +" * 发票属于同一公司,有相同币别,账簿,业务员,科目及类型等。 \n" +" \n" +" 发票明细仅在符合下列条件才被合并: \n" +" * 发票明细除了产品,数量,价格,金额等字段相同才被合并。 \n" +" " + +#. module: account_invoice_merge +#: code:addons/account_invoice_merge/wizard/invoice_merge.py:48 +#, python-format +msgid "Please select multiple invoice to merge in the list view." +msgstr "请在列表里选择多个发票来合并。" + +#. module: account_invoice_merge +#: view:invoice.merge:0 +msgid "Merge Invoices" +msgstr "合并发票" + +#. module: account_invoice_merge +#: code:addons/account_invoice_merge/wizard/invoice_merge.py:47 +#, python-format +msgid "Warning" +msgstr "警告" + +#. module: account_invoice_merge +#: view:invoice.merge:0 +#: model:ir.actions.act_window,name:account_invoice_merge.action_view_invoice_merge +#: model:ir.model,name:account_invoice_merge.model_invoice_merge +msgid "Merge Partner Invoice" +msgstr "合并合作伙伴发票" + +#. module: account_invoice_merge +#: view:invoice.merge:0 +msgid "Cancel" +msgstr "取消" + +#. module: account_invoice_merge +#: view:invoice.merge:0 +msgid "Are you sure you want to merge these invoices ?" +msgstr "您确认合并这些发票?" + diff --git a/account_invoice_merge/invoice.py b/account_invoice_merge/invoice.py new file mode 100644 index 00000000000..c0dca94d027 --- /dev/null +++ b/account_invoice_merge/invoice.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# 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 . +# +############################################################################## + +from osv import fields, osv +import netsvc +from tools.translate import _ +from osv.orm import browse_record, browse_null + +class account_invoice(osv.osv): + _inherit = "account.invoice" + + def do_merge(self, cr, uid, ids, context=None): + """ + To merge similar type of account invoices. + Invoices will only be merged if: + * Account invoices are in draft + * Account invoices belong to the same partner + * Account invoices are have same company, partner, address, currency, journal, currency, salesman, account, type + Lines will only be merged if: + * Invoice lines are exactly the same except for the quantity and unit + + @param self: The object pointer. + @param cr: A database cursor + @param uid: ID of the user currently logged in + @param ids: the ID or list of IDs + @param context: A standard dictionary + + @return: new account invoice id + + """ + wf_service = netsvc.LocalService("workflow") + def make_key(br, fields): + list_key = [] + for field in fields: + field_val = getattr(br, field) + if field in ('product_id', 'account_id'): + if not field_val: + field_val = False + if isinstance(field_val, browse_record): + field_val = field_val.id + elif isinstance(field_val, browse_null): + field_val = False + elif isinstance(field_val, list): + field_val = ((6, 0, tuple([v.id for v in field_val])),) + list_key.append((field, field_val)) + list_key.sort() + return tuple(list_key) + + # compute what the new orders should contain + + new_orders = {} + + for porder in [order for order in self.browse(cr, uid, ids, context=context) if order.state == 'draft']: + order_key = make_key(porder, ('partner_id', 'user_id', 'type', 'account_id', 'currency_id', 'journal_id', 'company_id')) + new_order = new_orders.setdefault(order_key, ({}, [])) + new_order[1].append(porder.id) + order_infos = new_order[0] + if not order_infos: + order_infos.update({ + 'origin': '%s' % (porder.origin or '',), + 'partner_id': porder.partner_id.id, + 'address_contact_id': porder.address_contact_id.id, + 'address_invoice_id': porder.address_invoice_id.id, + 'journal_id': porder.journal_id.id, + 'user_id': porder.user_id.id, + 'currency_id': porder.currency_id.id, + 'company_id': porder.company_id.id, + 'type': porder.type, + 'account_id': porder.account_id.id, + 'state': 'draft', + 'invoice_line': {}, + 'reference': '%s' % (porder.reference or '',), + 'name': '%s' % (porder.name or '',), + 'fiscal_position': porder.fiscal_position and porder.fiscal_position.id or False, + 'period_id': porder.period_id and porder.period_id.id or False, + }) + else: + if porder.name: + order_infos['name'] = (order_infos['name'] or '') + (' %s' % (porder.name,)) + if porder.origin: + order_infos['origin'] = (order_infos['origin'] or '') + ' ' + porder.origin + if porder.reference: + order_infos['reference'] = (order_infos['reference'] or '') + (' %s' % (porder.reference,)) + + for order_line in porder.invoice_line: + line_key = make_key(order_line, ('name', 'origin', 'discount', 'invoice_line_tax_id', 'price_unit', 'quantity', 'product_id', 'account_id', 'account_analytic_id')) + o_line = order_infos['invoice_line'].setdefault(line_key, {}) + if o_line: + # merge the line with an existing line + o_line['quantity'] += order_line.quantity + else: + # append a new "standalone" line + for field in ('quantity', 'uos_id'): + field_val = getattr(order_line, field) + if isinstance(field_val, browse_record): + field_val = field_val.id + o_line[field] = field_val + + allorders = [] + orders_info = {} + for order_key, (order_data, old_ids) in new_orders.iteritems(): + # skip merges with only one order + if len(old_ids) < 2: + allorders += (old_ids or []) + continue + + # cleanup order line data + for key, value in order_data['invoice_line'].iteritems(): + #del value['uom_factor'] + value.update(dict(key)) + order_data['invoice_line'] = [(0, 0, value) for value in order_data['invoice_line'].itervalues()] + + # create the new order + neworder_id = self.create(cr, uid, order_data) + orders_info.update({neworder_id: old_ids}) + allorders.append(neworder_id) + + # make triggers pointing to the old orders point to the new order + for old_id in old_ids: + wf_service.trg_redirect(uid, 'account.invoice', old_id, neworder_id, cr) + wf_service.trg_validate(uid, 'account.invoice', old_id, 'invoice_cancel', cr) + #print orders_info + return orders_info + +account_invoice() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/account_invoice_merge/wizard/__init__.py b/account_invoice_merge/wizard/__init__.py new file mode 100644 index 00000000000..109f9a99254 --- /dev/null +++ b/account_invoice_merge/wizard/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2011-2012 Erico-Corp (). +# +# 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 . +# +############################################################################## + +import invoice_merge +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/account_invoice_merge/wizard/invoice_merge.py b/account_invoice_merge/wizard/invoice_merge.py new file mode 100644 index 00000000000..3c103ddcadc --- /dev/null +++ b/account_invoice_merge/wizard/invoice_merge.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2011-2012 Erico-Corp (). +# +# 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 . +# +############################################################################## +import time + +from osv import fields, osv +import netsvc +import pooler +from osv.orm import browse_record, browse_null +from tools.translate import _ + +class invoice_merge(osv.osv_memory): + _name = "invoice.merge" + _description = "Merge Partner Invoice" + + def fields_view_get(self, cr, uid, view_id=None, view_type='form', + context=None, toolbar=False, submenu=False): + """ + Changes the view dynamically + @param self: The object pointer. + @param cr: A database cursor + @param uid: ID of the user currently logged in + @param context: A standard dictionary + @return: New arch of view. + """ + if context is None: + context={} + res = super(invoice_merge, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False) + + if context.get('active_model','') == 'account.invoice' and len(context['active_ids']) < 2: + raise osv.except_osv(_('Warning'), + _('Please select multiple invoice to merge in the list view.')) + return res + + def merge_invoices(self, cr, uid, ids, context=None): + """ + To merge similar type of account invoices. + + @param self: The object pointer. + @param cr: A database cursor + @param uid: ID of the user currently logged in + @param ids: the ID or list of IDs + @param context: A standard dictionary + + @return: account invoice view + + """ + order_obj = self.pool.get('account.invoice') + mod_obj =self.pool.get('ir.model.data') + so_obj = self.pool.get('sale.order') + po_obj = self.pool.get('purchase.order') + + if context is None: + context = {} + result = mod_obj._get_id(cr, uid, 'account', 'invoice_form') + + allorders = order_obj.do_merge(cr, uid, context.get('active_ids',[]), context) + + for new_order in allorders: + todo_ids = [] + todo_ids += so_obj.search(cr, uid, [('invoice_ids', 'in', allorders[new_order])], context=context) + for org_order in so_obj.browse(cr, uid, todo_ids, context=context): + so_obj.write(cr, uid, [org_order.id], {'invoice_ids': [(4, new_order)]}, context) + todo_ids += po_obj.search(cr, uid, [('invoice_ids', 'in', allorders[new_order])], context=context) + for org_order in po_obj.browse(cr, uid, todo_ids, context=context): + po_obj.write(cr, uid, [org_order.id], {'invoice_ids': [(4, new_order)]}, context) + + return { + 'domain': "[('id','in', [" + ','.join(map(str, allorders.keys())) + "])]", + 'name': _('Partner Invoice'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'account.invoice', + 'view_id': [result or False], + #'context': "{'type':'out_invoice'}", + 'type': 'ir.actions.act_window', + #'nodestroy': True, + 'target': 'current', + #'res_id': inv_ids and inv_ids[0] or False, + } + +invoice_merge() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_invoice_merge/wizard/invoice_merge_view.xml b/account_invoice_merge/wizard/invoice_merge_view.xml new file mode 100644 index 00000000000..246288c2166 --- /dev/null +++ b/account_invoice_merge/wizard/invoice_merge_view.xml @@ -0,0 +1,41 @@ + + + + + Merger Partner Invoice + invoice.merge + form + +
+ + +