Merge lp:~extra-addons-commiter/e-commerce-addons/7.0-sale-method into lp:~extra-addons-commiter/e-commerce-addons/7.0

Proposed by Guewen Baconnier @ Camptocamp
Status: Merged
Merged at revision: 283
Proposed branch: lp:~extra-addons-commiter/e-commerce-addons/7.0-sale-method
Merge into: lp:~extra-addons-commiter/e-commerce-addons/7.0
Diff against target: 1633 lines (+977/-392)
18 files modified
sale_automatic_workflow/invoice.py (+41/-17)
sale_payment_method/__init__.py (+24/-26)
sale_payment_method/__openerp__.py (+40/-45)
sale_payment_method/account_move.py (+30/-0)
sale_payment_method/i18n/fr.po (+142/-0)
sale_payment_method/i18n/sale_payment_method.pot (+141/-0)
sale_payment_method/migrations/0.1/post-migration.py (+2/-2)
sale_payment_method/payment_method.py (+39/-34)
sale_payment_method/payment_method_view.xml (+27/-15)
sale_payment_method/sale.py (+282/-151)
sale_payment_method/sale_view.xml (+40/-16)
sale_quick_payment/__init__.py (+22/-0)
sale_quick_payment/__openerp__.py (+55/-0)
sale_quick_payment/account_voucher.py (+0/-33)
sale_quick_payment/sale_view.xml (+40/-0)
sale_quick_payment/wizard/__init__.py (+1/-1)
sale_quick_payment/wizard/pay_sale_order.py (+50/-51)
sale_quick_payment/wizard/pay_sale_order.xml (+1/-1)
To merge this branch: bzr merge lp:~extra-addons-commiter/e-commerce-addons/7.0-sale-method
Reviewer Review Type Date Requested Status
Maxime Chambreuil (http://www.savoirfairelinux.com) Approve
Sébastien BEAU - http://www.akretion.com Approve
Yannick Vaucher @ Camptocamp Approve
Review via email: mp+155916@code.launchpad.net

Commit message

[IMP] review of sale_quick_payment for the new release of the connectors:

* split module in sale_payment_method and sale_quick_payment
* generate bare account move lines instead of voucher
* onchange when the payment method is modified
* new method to generate a payment using the payment terms and the payment method

Description of the change

This is part of the migration of the connectors (especially magentoerpconnect for my part) to version 7.0 of OpenERP.

This merge proposal aims to improve / adapt the module sale_quick_payment for this new release of the Magentoerpconnect.

Most of the changes were discussed with Sébastien Beau.

List of changes:

* The module 'sale_quick_payment' has been split in 2 modules:
  - 'sale_payment_method' which is the 'underwater' part of the module, it manages the payment methods and the creation of payments
  - 'sale_quick_payment' depends on the former and adds a wizard to generate the payments from the sale order and display them in the 'Automation Information' tab.
  This split allows to use the automatic payments from the connectors without using the manual wizard.

* Pursuing the voucher's killing spree, the payment generated are no longer vouchers but bare accounting move lines.

* In version 6.1, the default fiscal position was directly set by the connectors. Now, it is set by an onchange (the onchange will also be used to set the workflow process in my next merge proposal). The connectors still have to call the onchange.

* New method to generate a payment respecting the terms of the payment terms. The connectors should call this method when they generate a payment. It will allow a correct credit control.

* Fix: when a method is used in a sale order, it can no longer be deleted (FK 'restrict' instead of 'set null')

@Sébastien: I didn't do the migration, you said me you could do it yourself. I pushed my branch on the group extra-addons-commiter so you should be able to add it here.

To post a comment you must log in.
Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Hi,

Can I have some reviews on this one please? This will be necessary for the release of the new Magento Connector ;-)

297. By Guewen Baconnier @ Camptocamp

[FIX] fr_FR.po files not loaded, should be named fr.po

Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

Nitpicking

l35: one space to be removed
l434 and l435 aren't aligned as well
l436: missing #

Or

What about removing those trailing and bothering # as you did in sale_payment_method/sale.py?
:%s/\s\+#$//

in xml files name of the module is named in header comment shouldn't we change it to new name sale_payment_method for this splitted part?

l488 misleader name for view this one is in sale_payment_method and not in sale_quick_payment

l600 + l1222
import of decimal_precision should be
import openerp.addons.decimal_precision as dp

in pay_sale_order.xml there is another
            <field name="type">form</field>
you can remove as you did it in edited xml files

review: Needs Fixing (code, no test)
298. By Guewen Baconnier @ Camptocamp

[CHG] removed the trailing # in the headers

299. By Guewen Baconnier @ Camptocamp

[FIX] use explicit relative import

300. By Guewen Baconnier @ Camptocamp

[FIX] misleading module name

301. By Guewen Baconnier @ Camptocamp

[FIX] misleading module name in views names

302. By Guewen Baconnier @ Camptocamp

[CHG] remove trailing # in headers

303. By Guewen Baconnier @ Camptocamp

[FIX] imports

304. By Guewen Baconnier @ Camptocamp

[FIX] removed deprecated view type

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Thanks for the review, I made the changes.

Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

Thanks for the changes

LGTM

review: Approve
305. By Sébastien BEAU - http://www.akretion.com

[IMP] sale_payment_method add the possibility to add the description when adding a payment

306. By Sébastien BEAU - http://www.akretion.com

[IMP] sale_quick_payment : add the posibility to specify the description when adding a payment with the wizard

307. By Sébastien BEAU - http://www.akretion.com

[REF] start to refactor sale_payment_method, the aim is to link the sale order to the move line and not the move. Indeed when we import a bank statement and we used the module account_bank_statement_one_move we have 1 one with X customer payment. So we have no choice the sale must be linked to the move lines

308. By Sébastien BEAU - http://www.akretion.com

[FIX] fix bug to due previous refactor, compute correctly the amount paid, link the payment with the sale order, and improve the payment view

Revision history for this message
Sébastien BEAU - http://www.akretion.com (sebastien.beau) wrote :

Hi Guewen,
As talk before it's better to link the account_move_line instead of the account_move (indeed a move can have X line and each line can be linked to a specific sale order).
I made the change and also I add the possibility to specify a description.

For the migration script I don't know was will be the best solution because we move three time the data model (payment_id => payment_ids => then account move => then account_move_line). Due to this change the actual migration script is broken (indeed the script will not work because the payment is not a voucher anymore). I propose for now to remove the actual migration script and working on it when a customer will want to migrate from 6.1 to 7. What do you think?

As always thanks for your really good

309. By Sébastien BEAU - http://www.akretion.com

[REF] adapte sale_automatic_workflow due to the change as sale order are linked to a account move line

310. By Sébastien BEAU - http://www.akretion.com

[IMP] sle_automatic_workflow : add partial reconciliation

Revision history for this message
Sébastien BEAU - http://www.akretion.com (sebastien.beau) wrote :

I forget to push some change on sale_automatic workflow, now it ok for me

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

I agree with Sebastien's changes.

Revision history for this message
Sébastien BEAU - http://www.akretion.com (sebastien.beau) :
review: Approve
Revision history for this message
Maxime Chambreuil (http://www.savoirfairelinux.com) (max3903) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'sale_automatic_workflow/invoice.py'
--- sale_automatic_workflow/invoice.py 2012-12-26 13:22:11 +0000
+++ sale_automatic_workflow/invoice.py 2013-10-13 16:10:00 +0000
@@ -30,21 +30,41 @@
30 'sale_ids': fields.many2many('sale.order', 'sale_order_invoice_rel', 'invoice_id', 'order_id', 'Sale Orders')30 'sale_ids': fields.many2many('sale.order', 'sale_order_invoice_rel', 'invoice_id', 'order_id', 'Sale Orders')
31 }31 }
3232
33 def _get_payment(self, cr, uid, invoice, context=None):
34 if invoice.type == "out_invoice" and invoice.sale_ids:
35 return invoice.sale_ids[0].payment_ids
36 return []
37
33 def _can_be_reconciled(self, cr, uid, invoice, context=None):38 def _can_be_reconciled(self, cr, uid, invoice, context=None):
34 if not (invoice.sale_ids and invoice.sale_ids[0].payment_ids and invoice.move_id):39 payments = self._get_payment(cr, uid, invoice, context=context)
40 if not (payments and invoice.move_id):
35 return False41 return False
36 #Check currency42 # Check currency
37 for payment in invoice.sale_ids[0].payment_ids:43 company_currency_id = invoice.company_id.currency_id.id
38 for move in payment.move_ids:44 for payment in payments:
39 if (move.currency_id.id or invoice.company_id.currency_id.id) != invoice.currency_id.id:45 currency_id = payment.currency_id.id or company_currency_id
40 return False46 if currency_id != invoice.currency_id.id:
47 return False
41 return True48 return True
4249
43 def _get_sum_invoice_move_line(self, cr, uid, move_lines, context=None):50 def _get_sum_invoice_move_line(self, cr, uid, move_lines,\
44 return self._get_sum_move_line(cr, uid, move_lines, 'debit', context=None)51 invoice_type, context=None):
4552 if invoice_type in ['in_refund', 'out_invoice']:
46 def _get_sum_payment_move_line(self, cr, uid, move_lines, context=None):53 line_type = 'debit'
47 return self._get_sum_move_line(cr, uid, move_lines, 'credit', context=None)54 else:
55 line_type = 'credit'
56 return self._get_sum_move_line(cr, uid, move_lines,\
57 line_type, context=None)
58
59 def _get_sum_payment_move_line(self, cr, uid, move_lines,\
60 invoice_type, context=None):
61 if invoice_type in ['in_refund', 'out_invoice']:
62 line_type = 'credit'
63 else:
64 line_type = 'debit'
65 return self._get_sum_move_line(cr, uid, move_lines,\
66 line_type, context=None)
67
4868
49 def _get_sum_move_line(self, cr, uid, move_lines, line_type, context=None):69 def _get_sum_move_line(self, cr, uid, move_lines, line_type, context=None):
50 res = {70 res = {
@@ -93,20 +113,24 @@
93 obj_move_line = self.pool.get('account.move.line')113 obj_move_line = self.pool.get('account.move.line')
94 for invoice in self.browse(cr, uid, ids, context=context):114 for invoice in self.browse(cr, uid, ids, context=context):
95 use_currency = invoice.currency_id.id != invoice.company_id.currency_id.id115 use_currency = invoice.currency_id.id != invoice.company_id.currency_id.id
116 reconcile = False
117 payment_move_lines = self._get_payment(cr, uid, invoice, context=context)
118 res_payment = self._get_sum_payment_move_line(cr, uid, payment_move_line, invoice.type, context=context)
119 res_invoice = self._get_sum_invoice_move_line(cr, uid, invoice.move_id.line_id, invoice.type, context=context)
120 line_ids = res_invoice['line_ids'] + res_payment['line_ids']
96 if self._can_be_reconciled(cr, uid, invoice, context=context):121 if self._can_be_reconciled(cr, uid, invoice, context=context):
97 payment_move_line = []
98 for payment in invoice.sale_ids[0].payment_ids:
99 payment_move_line += payment.move_ids
100 res_payment = self._get_sum_payment_move_line(cr, uid, payment_move_line, context=context)
101 res_invoice = self._get_sum_invoice_move_line(cr, uid, invoice.move_id.line_id, context=context)
102 line_ids = res_invoice['line_ids'] + res_payment['line_ids']
103 if not use_currency:122 if not use_currency:
104 balance = abs(res_invoice['total_amount']-res_payment['total_amount'])123 balance = abs(res_invoice['total_amount']-res_payment['total_amount'])
105 if line_ids and not round(balance, precision):124 if line_ids and not round(balance, precision):
106 obj_move_line.reconcile(cr, uid, line_ids, context=context)125 obj_move_line.reconcile(cr, uid, line_ids, context=context)
126 reconcile=True
107 else:127 else:
108 balance = abs(res_invoice['total_amount_currency']-res_payment['total_amount_currency'])128 balance = abs(res_invoice['total_amount_currency']-res_payment['total_amount_currency'])
109 if line_ids and not round(balance, precision):129 if line_ids and not round(balance, precision):
110 kwargs = self._prepare_write_off(cr, uid, invoice, res_invoice, res_payment, context=context)130 kwargs = self._prepare_write_off(cr, uid, invoice, res_invoice, res_payment, context=context)
111 obj_move_line.reconcile(cr, uid, line_ids, **kwargs)131 obj_move_line.reconcile(cr, uid, line_ids, **kwargs)
132 reconcile = True
133 unreconciled_payment = [line for line in payment_move_lines if not line.reconcile_partial_id]
134 if not reconcile and unreconciled_payment:
135 move_line_obj.reconcile_partial(cr, uid, line_ids, context=context)
112 return True136 return True
113137
=== renamed directory 'sale_quick_payment' => 'sale_payment_method'
=== modified file 'sale_payment_method/__init__.py'
--- sale_quick_payment/__init__.py 2012-12-26 13:13:25 +0000
+++ sale_payment_method/__init__.py 2013-10-13 16:10:00 +0000
@@ -1,26 +1,24 @@
1# -*- encoding: utf-8 -*-1# -*- coding: utf-8 -*-
2#################################################################################2##############################################################################
3# #3#
4# sale_quick_payment for OpenERP #4# sale_payment_method for OpenERP
5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com> #5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>
6# #6#
7# This program is free software: you can redistribute it and/or modify #7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as #8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the #9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version. #10# License, or (at your option) any later version.
11# #11#
12# This program is distributed in the hope that it will be useful, #12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details. #15# GNU Affero General Public License for more details.
16# #16#
17# You should have received a copy of the GNU Affero General Public License #17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19# #19#
20#################################################################################20##############################################################################
2121
2222from . import sale
23import sale23from . import payment_method
24import payment_method24from . import account_move
25import wizard
26import account_voucher
2725
=== modified file 'sale_payment_method/__openerp__.py'
--- sale_quick_payment/__openerp__.py 2012-12-26 13:22:58 +0000
+++ sale_payment_method/__openerp__.py 2013-10-13 16:10:00 +0000
@@ -1,54 +1,49 @@
1# -*- encoding: utf-8 -*-1# -*- coding: utf-8 -*-
2###############################################################################2##############################################################################
3# #3#
4# sale_quick_payment for OpenERP #4# sale_payment_method for OpenERP
5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com> #5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>
6# #6#
7# This program is free software: you can redistribute it and/or modify #7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as #8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the #9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version. #10# License, or (at your option) any later version.
11# #11#
12# This program is distributed in the hope that it will be useful, #12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details. #15# GNU Affero General Public License for more details.
16# #16#
17# You should have received a copy of the GNU Affero General Public License #17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19# #19#
20###############################################################################20##############################################################################
21
2221
23{22{
24 'name': 'sale_quick_payment',23 'name': 'Sale Payment Method',
25 'version': '0.1',24 'version': '0.2',
26 'category': 'Generic Modules/Others',25 'category': 'Generic Modules/Others',
27 'license': 'AGPL-3',26 'license': 'AGPL-3',
28 'description': """27 'description': """
29 Sale Quick Payment give the posibility to paid an sale order.28Sale Payment Method
30 The payment will be linked to the sale order29===================
31 If you install the module Sale Automatic Workflow you can forbid the validation30
32 of an unpaid order and also the Invoice will be automatically reconciled with31This module adds low-level features used for instance by modules:
33 the payment.32
34 This module was design for e-commerce sector.33- Sale Automatic Workflow
35 """,34- Sale Quick Payment
35
36It adds a payment method on the sales orders and allow to register
37payments entries on sales orders.
38""",
36 'author': 'Akretion',39 'author': 'Akretion',
37 'website': 'http://www.akretion.com/',40 'website': 'http://www.akretion.com/',
38 'depends': [41 'depends': ['sale',
39 'sale_exceptions',42 ],
40 'account_voucher',43 'data': ['sale_view.xml',
41 ], 44 'payment_method_view.xml',
42 'init_xml': [],45 'security/ir.model.access.csv',
43 'update_xml': [46 ],
44 'wizard/pay_sale_order.xml',47 'demo': [],
45 'sale_view.xml',
46 'payment_method_view.xml',
47 'security/ir.model.access.csv',
48 'settings/sale.exception.csv',
49 ],
50 'demo_xml': [],
51 'installable': True,48 'installable': True,
52 'active': False,
53}49}
54
5550
=== added file 'sale_payment_method/account_move.py'
--- sale_payment_method/account_move.py 1970-01-01 00:00:00 +0000
+++ sale_payment_method/account_move.py 2013-10-13 16:10:00 +0000
@@ -0,0 +1,30 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Guewen Baconnier
5# Copyright 2013 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22from openerp.osv import orm, fields
23
24
25class account_move_line(orm.Model):
26 _inherit = 'account.move.line'
27
28 _columns = {
29 'sale_ids': fields.many2many('sale.order', string='Sales Orders'),
30 }
031
=== added directory 'sale_payment_method/i18n'
=== added file 'sale_payment_method/i18n/fr.po'
--- sale_payment_method/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ sale_payment_method/i18n/fr.po 2013-10-13 16:10:00 +0000
@@ -0,0 +1,142 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * sale_payment_method
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 7.0\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2013-05-02 07:06+0000\n"
10"PO-Revision-Date: 2013-05-02 07:06+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: sale_payment_method
19#: view:sale.order:0
20msgid "Automation Information"
21msgstr "Informations d'automatisation"
22
23#. module: sale_payment_method
24#: help:payment.method,journal_id:0
25msgid "If a journal a selected, when a payment is recorded on a backend, payment entries will be created in this journal. "
26msgstr "Si un journal est sélectionné, lorsqu'un paiement est enregistré sur le backend, des lignes de paiement seront générées dans ce journal."
27
28#. module: sale_payment_method
29#: view:payment.method:0
30msgid "Even if the E-commerce backend receives a payment for a sale order,\n"
31" no payment entries will be generated."
32msgstr "Même si le backend e-commerce reçoit un payment pour un bon de commande, aucune ligne de paiement ne sera générée."
33
34#. module: sale_payment_method
35#: view:payment.method:0
36msgid "Default Values"
37msgstr "Valeurs par défaut"
38
39#. module: sale_payment_method
40#: model:ir.model,name:sale_payment_method.model_payment_method
41#: field:sale.order,payment_method_id:0
42msgid "Payment Method"
43msgstr "Méthode de paiement"
44
45#. module: sale_payment_method
46#: view:sale.order:0
47msgid "View Automatic Payment"
48msgstr "Voir les paiements automatiques"
49
50#. module: sale_payment_method
51#: help:sale.order,payment_exists:0
52msgid "It indicates that sales order has at least one payment."
53msgstr "Indique que la commande a reçu au moins un paiement."
54
55#. module: sale_payment_method
56#: field:payment.method,journal_id:0
57msgid "Journal"
58msgstr "Journal"
59
60#. module: sale_payment_method
61#: model:ir.actions.act_window,name:sale_payment_method.act_payment_method_form
62#: model:ir.ui.menu,name:sale_payment_method.menu_action_paymetn_method_form
63msgid "Payment Methods "
64msgstr "Méthodes de paiement"
65
66#. module: sale_payment_method
67#: field:account.move,order_ids:0
68msgid "Sales Orders"
69msgstr "Bons de commande"
70
71#. module: sale_payment_method
72#: view:sale.order:0
73msgid "Other Information"
74msgstr "Autres informations"
75
76#. module: sale_payment_method
77#: view:payment.method:0
78msgid "Payment Methods"
79msgstr "Méthodes de paiement"
80
81#. module: sale_payment_method
82#: field:payment.method,name:0
83msgid "Name"
84msgstr "Nom"
85
86#. module: sale_payment_method
87#: field:sale.order,payment_ids:0
88msgid "Payments Entries"
89msgstr "Écritures de paiement"
90
91#. module: sale_payment_method
92#: view:payment.method:0
93msgid "When the E-commerce backend will receive a payment for a sale order,\n"
94" payment entries will be generated in the selected journal."
95msgstr "Lorsque le backend e-commerce reçoit un paiement pour la commande,\n"
96" des écritures de paiement sont générées dans le journal sélectionné."
97
98#. module: sale_payment_method
99#: view:payment.method:0
100msgid "Journal for payment"
101msgstr "Journal pour le paiement"
102
103#. module: sale_payment_method
104#: field:sale.order,residual:0
105msgid "Balance"
106msgstr "Solde"
107
108#. module: sale_payment_method
109#: model:ir.model,name:sale_payment_method.model_account_move
110msgid "Account Entry"
111msgstr "Ecriture"
112
113#. module: sale_payment_method
114#: help:payment.method,payment_term_id:0
115msgid "Default payment term of a sale order using this method."
116msgstr "Condition de règlement par défaut pour les commandes utilisant cette méthode."
117
118#. module: sale_payment_method
119#: field:payment.method,payment_term_id:0
120msgid "Payment Term"
121msgstr "Condition de règlement"
122
123#. module: sale_payment_method
124#: view:sale.order:0
125msgid "Create Invoice"
126msgstr "Créer la facture"
127
128#. module: sale_payment_method
129#: help:payment.method,name:0
130msgid "The name of the method on the backend"
131msgstr "Nom de la méthode sur le backend"
132
133#. module: sale_payment_method
134#: model:ir.model,name:sale_payment_method.model_sale_order
135msgid "Sales Order"
136msgstr "Bon de commande"
137
138#. module: sale_payment_method
139#: field:sale.order,payment_exists:0
140msgid "Has automatic payment"
141msgstr "A un paiement automatique"
142
0143
=== added file 'sale_payment_method/i18n/sale_payment_method.pot'
--- sale_payment_method/i18n/sale_payment_method.pot 1970-01-01 00:00:00 +0000
+++ sale_payment_method/i18n/sale_payment_method.pot 2013-10-13 16:10:00 +0000
@@ -0,0 +1,141 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * sale_payment_method
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 7.0\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2013-05-02 07:06+0000\n"
10"PO-Revision-Date: 2013-05-02 07:06+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: sale_payment_method
19#: view:sale.order:0
20msgid "Automation Information"
21msgstr ""
22
23#. module: sale_payment_method
24#: help:payment.method,journal_id:0
25msgid "If a journal a selected, when a payment is recorded on a backend, payment entries will be created in this journal. "
26msgstr ""
27
28#. module: sale_payment_method
29#: view:payment.method:0
30msgid "Even if the E-commerce backend receives a payment for a sale order,\n"
31" no payment entries will be generated."
32msgstr ""
33
34#. module: sale_payment_method
35#: view:payment.method:0
36msgid "Default Values"
37msgstr ""
38
39#. module: sale_payment_method
40#: model:ir.model,name:sale_payment_method.model_payment_method
41#: field:sale.order,payment_method_id:0
42msgid "Payment Method"
43msgstr ""
44
45#. module: sale_payment_method
46#: view:sale.order:0
47msgid "View Automatic Payment"
48msgstr ""
49
50#. module: sale_payment_method
51#: help:sale.order,payment_exists:0
52msgid "It indicates that sales order has at least one payment."
53msgstr ""
54
55#. module: sale_payment_method
56#: field:payment.method,journal_id:0
57msgid "Journal"
58msgstr ""
59
60#. module: sale_payment_method
61#: model:ir.actions.act_window,name:sale_payment_method.act_payment_method_form
62#: model:ir.ui.menu,name:sale_payment_method.menu_action_paymetn_method_form
63msgid "Payment Methods "
64msgstr ""
65
66#. module: sale_payment_method
67#: field:account.move,order_ids:0
68msgid "Sales Orders"
69msgstr ""
70
71#. module: sale_payment_method
72#: view:sale.order:0
73msgid "Other Information"
74msgstr ""
75
76#. module: sale_payment_method
77#: view:payment.method:0
78msgid "Payment Methods"
79msgstr ""
80
81#. module: sale_payment_method
82#: field:payment.method,name:0
83msgid "Name"
84msgstr ""
85
86#. module: sale_payment_method
87#: field:sale.order,payment_ids:0
88msgid "Payments Entries"
89msgstr ""
90
91#. module: sale_payment_method
92#: view:payment.method:0
93msgid "When the E-commerce backend will receive a payment for a sale order,\n"
94" payment entries will be generated in the selected journal."
95msgstr ""
96
97#. module: sale_payment_method
98#: view:payment.method:0
99msgid "Journal for payment"
100msgstr ""
101
102#. module: sale_payment_method
103#: field:sale.order,residual:0
104msgid "Balance"
105msgstr ""
106
107#. module: sale_payment_method
108#: model:ir.model,name:sale_payment_method.model_account_move
109msgid "Account Entry"
110msgstr ""
111
112#. module: sale_payment_method
113#: help:payment.method,payment_term_id:0
114msgid "Default payment term of a sale order using this method."
115msgstr ""
116
117#. module: sale_payment_method
118#: field:payment.method,payment_term_id:0
119msgid "Payment Term"
120msgstr ""
121
122#. module: sale_payment_method
123#: view:sale.order:0
124msgid "Create Invoice"
125msgstr ""
126
127#. module: sale_payment_method
128#: help:payment.method,name:0
129msgid "The name of the method on the backend"
130msgstr ""
131
132#. module: sale_payment_method
133#: model:ir.model,name:sale_payment_method.model_sale_order
134msgid "Sales Order"
135msgstr ""
136
137#. module: sale_payment_method
138#: field:sale.order,payment_exists:0
139msgid "Has automatic payment"
140msgstr ""
141
0142
=== modified file 'sale_payment_method/migrations/0.1/post-migration.py'
--- sale_quick_payment/migrations/0.1/post-migration.py 2012-12-26 13:13:25 +0000
+++ sale_payment_method/migrations/0.1/post-migration.py 2013-10-13 16:10:00 +0000
@@ -1,5 +1,5 @@
1# -*- encoding: utf-8 -*-1# -*- encoding: utf-8 -*-
2###############################################################################2##############################################################################
3#3#
4# sale_quick_payment for OpenERP4# sale_quick_payment for OpenERP
5# Copyright (C) 2012-TODAY Akretion <http://www.akretion.com>.5# Copyright (C) 2012-TODAY Akretion <http://www.akretion.com>.
@@ -18,7 +18,7 @@
18# You should have received a copy of the GNU Affero General Public License18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#20#
21###############################################################################21##############################################################################
2222
23""" r0.1: Migration 6.1 => 7.0.0.123""" r0.1: Migration 6.1 => 7.0.0.1
24 migrate the field payment_id from one2many to payment_ids many2many24 migrate the field payment_id from one2many to payment_ids many2many
2525
=== modified file 'sale_payment_method/payment_method.py'
--- sale_quick_payment/payment_method.py 2012-08-21 13:57:44 +0000
+++ sale_payment_method/payment_method.py 2013-10-13 16:10:00 +0000
@@ -1,38 +1,43 @@
1# -*- encoding: utf-8 -*-1# -*- coding: utf-8 -*-
2###############################################################################2##############################################################################
3# #3#
4# sale_quick_payment for OpenERP #4# sale_quick_payment for OpenERP
5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com> #5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>
6# #6# Copyright 2013 Camptocamp SA (Guewen Baconnier)
7# This program is free software: you can redistribute it and/or modify #7#
8# it under the terms of the GNU Affero General Public License as #8# This program is free software: you can redistribute it and/or modify
9# published by the Free Software Foundation, either version 3 of the #9# it under the terms of the GNU Affero General Public License as
10# License, or (at your option) any later version. #10# published by the Free Software Foundation, either version 3 of the
11# #11# License, or (at your option) any later version.
12# This program is distributed in the hope that it will be useful, #12#
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #13# This program is distributed in the hope that it will be useful,
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# GNU Affero General Public License for more details. #15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# #16# GNU Affero General Public License for more details.
17# You should have received a copy of the GNU Affero General Public License #17#
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #18# You should have received a copy of the GNU Affero General Public License
19# #19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20###############################################################################20#
2121##############################################################################
22from openerp.osv.orm import Model22
23from openerp.osv import fields23from openerp.osv import fields, orm
24import netsvc24
2525
2626class payment_method(orm.Model):
27class payment_method(Model):
28
29 _name = "payment.method"27 _name = "payment.method"
30 _description = "payment method"28 _description = "Payment Method"
31
3229
33 _columns = {30 _columns = {
34 'name': fields.char('Name', size=64),31 'name': fields.char('Name',
35 'journal_id': fields.many2one('account.journal', 'Journal'),32 help="The name of the method on the backend"),
36 'payment_term_id': fields.many2one('account.payment.term', 'Payment Term'),33 'journal_id': fields.many2one(
34 'account.journal',
35 'Journal',
36 help="If a journal a selected, when a payment is recorded "
37 "on a backend, payment entries will be created in this "
38 "journal. "),
39 'payment_term_id': fields.many2one(
40 'account.payment.term',
41 'Payment Term',
42 help="Default payment term of a sale order using this method."),
37 }43 }
38
3944
=== modified file 'sale_payment_method/payment_method_view.xml'
--- sale_quick_payment/payment_method_view.xml 2012-04-22 12:48:34 +0000
+++ sale_payment_method/payment_method_view.xml 2013-10-13 16:10:00 +0000
@@ -1,6 +1,6 @@
1<?xml version="1.0" encoding="utf-8"?>1<?xml version="1.0" encoding="utf-8"?>
2<!--2<!--
3 sale_quick_payment for OpenERP3 sale_payment_method for OpenERP
4 Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>4 Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>
5 The licence is in the file __openerp__.py5 The licence is in the file __openerp__.py
6-->6-->
@@ -8,28 +8,41 @@
8<openerp>8<openerp>
9 <data>9 <data>
1010
11 <!-- VIEW FOR THE OBJECT : payment_method -->
12 <record id="payment_method_view_form" model="ir.ui.view">11 <record id="payment_method_view_form" model="ir.ui.view">
13 <field name="name">sale_quick_payment.payment_method.view_form</field>12 <field name="name">sale_payment_method.payment_method.view_form</field>
14 <field name="model">payment.method</field>13 <field name="model">payment.method</field>
15 <field eval="16" name="priority"/>
16 <field name="type">form</field>
17 <field name="arch" type="xml">14 <field name="arch" type="xml">
18 <form string="payment_method">15 <form string="Payment Methods" version="7.0">
19 <field name="name" />16 <h1>
20 <field name="journal_id" />17 <field name="name" class="oe_inline"/>
21 <field name="payment_term_id" />18 </h1>
19 <group name="general">
20 <group name="config">
21 <field name="journal_id" string="Journal for payment"/>
22 </group>
23 <group name="payment_help" class="oe_grey" col="1">
24 <p attrs="{'invisible': [('journal_id', '=', False)]}">
25 When the E-commerce backend will receive a payment for a sale order,
26 payment entries will be generated in the selected journal.
27 </p>
28 <p attrs="{'invisible': [('journal_id', '!=', False)]}">
29 Even if the E-commerce backend receives a payment for a sale order,
30 no payment entries will be generated.
31 </p>
32 </group>
33 </group>
34 <group string="Default Values">
35 <field name="payment_term_id" />
36 </group>
22 </form>37 </form>
23 </field>38 </field>
24 </record>39 </record>
2540
26 <record id="payment_method_view_tree" model="ir.ui.view">41 <record id="payment_method_view_tree" model="ir.ui.view">
27 <field name="name">sale_quick_payment.payment_method.view_tree</field>42 <field name="name">sale_payment_method.payment_method.view_tree</field>
28 <field name="model">payment.method</field>43 <field name="model">payment.method</field>
29 <field eval="16" name="priority"/>
30 <field name="type">tree</field>
31 <field name="arch" type="xml">44 <field name="arch" type="xml">
32 <tree string="payment_method">45 <tree string="Payment Methods">
33 <field name="name" />46 <field name="name" />
34 <field name="journal_id" />47 <field name="journal_id" />
35 <field name="payment_term_id" />48 <field name="payment_term_id" />
@@ -37,9 +50,8 @@
37 </field>50 </field>
38 </record>51 </record>
3952
40
41 <record id="act_payment_method_form" model="ir.actions.act_window">53 <record id="act_payment_method_form" model="ir.actions.act_window">
42 <field name="name">Customer Payment Method</field>54 <field name="name">Payment Methods </field>
43 <field name="res_model">payment.method</field>55 <field name="res_model">payment.method</field>
44 <field name="view_type">form</field>56 <field name="view_type">form</field>
45 <field name="view_mode">tree,form</field>57 <field name="view_mode">tree,form</field>
4658
=== modified file 'sale_payment_method/sale.py'
--- sale_quick_payment/sale.py 2012-12-26 09:32:43 +0000
+++ sale_payment_method/sale.py 2013-10-13 16:10:00 +0000
@@ -1,165 +1,296 @@
1# -*- encoding: utf-8 -*-1# -*- coding: utf-8 -*-
2###############################################################################2##############################################################################
3# #3#
4# sale_quick_payment for OpenERP #4# Author: Guewen Baconnier, Sébastien Beau
5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com> #5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>
6# #6# Copyright 2013 Camptocamp SA (Guewen Baconnier)
7# This program is free software: you can redistribute it and/or modify #7#
8# it under the terms of the GNU Affero General Public License as #8# This program is free software: you can redistribute it and/or modify
9# published by the Free Software Foundation, either version 3 of the #9# it under the terms of the GNU Affero General Public License as
10# License, or (at your option) any later version. #10# published by the Free Software Foundation, either version 3 of the
11# #11# License, or (at your option) any later version.
12# This program is distributed in the hope that it will be useful, #12#
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #13# This program is distributed in the hope that it will be useful,
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# GNU Affero General Public License for more details. #15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# #16# GNU Affero General Public License for more details.
17# You should have received a copy of the GNU Affero General Public License #17#
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #18# You should have received a copy of the GNU Affero General Public License
19# #19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20###############################################################################20#
21##############################################################################
2122
22from openerp.osv.orm import Model23from openerp.osv import orm, fields, osv
23from openerp.osv import fields24from openerp.tools.translate import _
24from openerp.osv.osv import except_osv
25import netsvc
26from collections import Iterable25from collections import Iterable
27from openerp.tools.translate import _26import openerp.addons.decimal_precision as dp
28import decimal_precision as dp27
2928
30class sale_order(Model):29class sale_order(orm.Model):
31 _inherit = "sale.order"30 _inherit = 'sale.order'
3231
33 def _get_order_from_voucher(self, cr, uid, ids, context=None):32 def _get_order_from_move(self, cr, uid, ids, context=None):
34 result = []33 result = set()
35 for voucher in self.pool.get('account.voucher').browse(cr, uid, ids, context=context):34 move_obj = self.pool.get('account.move')
36 for order in voucher.order_ids:35 for move in move_obj.browse(cr, uid, ids, context=context):
37 result.append(order.id)36 for order in move.order_ids:
38 return list(set(result))37 result.add(order.id)
38 return list(result)
3939
40 def _get_order_from_line(self, cr, uid, ids, context=None):40 def _get_order_from_line(self, cr, uid, ids, context=None):
41 return self.pool.get('sale.order')._get_order(cr, uid, ids, context=context)41 so_obj = self.pool.get('sale.order')
42 return so_obj._get_order(cr, uid, ids, context=context)
4243
43 def _amount_residual(self, cr, uid, ids, field_name, args, context=None):44 def _get_amount(self, cr, uid, ids, fields, args, context=None):
44 res = {}45 res = {}
45 #TODO add here the support of multi-currency payment if need
46 for order in self.browse(cr, uid, ids, context=context):46 for order in self.browse(cr, uid, ids, context=context):
47 res[order.id] = order.amount_total47 #TODO add support when payment is linked to many order
48 for payment in order.payment_ids:48 paid_amount = 0
49 if payment.state == 'posted':49 for line in order.payment_ids:
50 res[order.id] -= payment.amount50 paid_amount += line.credit - line.debit
51 res[order.id] = {
52 'amount_paid': paid_amount,
53 'residual': order.amount_total - paid_amount,
54 }
55 return res
56
57 def _payment_exists(self, cursor, user, ids, name, arg, context=None):
58 res = {}
59 for sale in self.browse(cursor, user, ids, context=context):
60 res[sale.id] = bool(sale.payment_ids)
51 return res61 return res
5262
53 _columns = {63 _columns = {
54 'payment_ids': fields.many2many('account.voucher', string='Payments'),64 'payment_ids': fields.many2many('account.move.line',
55 'payment_method_id': fields.many2one('payment.method', 'Payment Method'),65 string='Payments Entries'),
56 'residual': fields.function(_amount_residual, digits_compute=dp.get_precision('Account'), string='Balance',66 'payment_method_id': fields.many2one('payment.method',
57 store = {67 'Payment Method',
58 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line', 'payment_ids'], 10),68 ondelete='restrict'),
59 'sale.order.line': (_get_order_from_line, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 20),69 'residual': fields.function(
60 'account.voucher': (_get_order_from_voucher, ['amount'], 30),70 _get_amount,
61 },71 digits_compute=dp.get_precision('Account'),
62 ),72 string='Balance',
73 store=False,
74 multi='payment'),
75 'amount_paid': fields.function(
76 _get_amount,
77 digits_compute=dp.get_precision('Account'),
78 string='Amount Paid',
79 store=False,
80 multi='payment'),
81 'payment_exists': fields.function(
82 _payment_exists,
83 string='Has automatic payment',
84 type='boolean',
85 help="It indicates that sales order has at least one payment."),
63 }86 }
6487
65 def copy(self, cr, uid, id, default=None, context=None):88 def copy(self, cr, uid, id, default=None, context=None):
66 if not default:89 if default is None:
67 default = {}90 default = {}
68 default.update({91 default['payment_ids'] = False
69 'payment_ids': False,92 return super(sale_order, self).copy(cr, uid, id,
70 })93 default, context=context)
71 return super(sale_order, self).copy(cr, uid, id, default, context=context)94
7295 def automatic_payment(self, cr, uid, ids, amount=None, context=None):
73 def pay_sale_order(self, cr, uid, sale_id, journal_id, amount, date, context=None):96 """ Create the payment entries to pay a sale order, respecting
74 """97 the payment terms.
75 Generate a voucher for the payment98 If no amount is defined, it will pay the residual amount of the sale
7699 order. """
77 It will try to match with the invoice of the order by100 if isinstance(ids, Iterable):
78 matching the payment ref and the invoice origin.101 assert len(ids) == 1, "one sale order at a time can be paid"
79102 ids = ids[0]
80 The invoice does not necessarily exists at this point, so if yes,103 sale = self.browse(cr, uid, ids, context=context)
81 it will be matched in the voucher, otherwise, the voucher won't104 method = sale.payment_method_id
82 have any invoice lines and the payment lines will be reconciled105 if not method:
83 later with "auto-reconcile" if the option is used.106 raise osv.except_osv(
84107 _('Configuration Error'),
85 """108 _("An automatic payment can not be created for the sale "
86 if isinstance(sale_id, Iterable):109 "order %s because it has no payment method.") % sale.name)
87 sale_id = sale_id[0]110
88111 if not method.journal_id:
89 voucher_obj = self.pool.get('account.voucher')112 raise osv.except_osv(
90 voucher_line_obj = self.pool.get('account.voucher.line')113 _('Configuration Error'),
91 move_line_obj = self.pool.get('account.move.line')114 _("An automatic payment should be created for the sale order %s "
92 sale = self.browse(cr, uid, sale_id, context=context)115 "but the payment method '%s' has no journal defined.") %
93116 (sale.name, method.name))
94 journal = self.pool.get('account.journal').browse(117
95 cr, uid, journal_id, context=context)118 journal = method.journal_id
96119 date = sale.date_order
97 voucher_vals = {'reference': sale.name,120 if amount is None:
98 'journal_id': journal_id,121 amount = sale.residual
99 'period_id': self.pool.get('account.period').find(cr, uid, dt=date,122 if sale.payment_term:
100 context=context)[0],123 term_obj = self.pool.get('account.payment.term')
101 'amount': amount,124 amounts = term_obj.compute(cr, uid, sale.payment_term.id,
102 'date': date,125 amount, date_ref=date,
103 'partner_id': sale.partner_id.id,126 context=context)
104 'account_id': journal.default_credit_account_id.id,127 else:
105 'currency_id': journal.company_id.currency_id.id,128 amounts = [(date, amount)]
106 'company_id': journal.company_id.id,129
107 'type': 'receipt', }130 # reversed is cosmetic, compute returns terms in the 'wrong' order
108131 for date, amount in reversed(amounts):
109 # Set the payment rate if currency are different132 self._add_payment(cr, uid, sale, journal,
110 if journal.currency.id and journal.company_id.currency_id.id != journal.currency.id:133 amount, date, context=context)
111 currency_id = journal.company_id.currency_id.id134 return True
112 payment_rate_currency_id = journal.currency.id135
113136 def add_payment(self, cr, uid, ids, journal_id, amount,
114 currency_obj = self.pool.get('res.currency')137 date=None, description=None, context=None):
115 ctx= context.copy()138 """ Generate payment move lines of a certain amount linked
116 ctx.update({'date': date})139 with the sale order. """
117 tmp = currency_obj.browse(cr, uid, payment_rate_currency_id, context=ctx).rate140 if isinstance(ids, Iterable):
118 payment_rate = tmp / currency_obj.browse(cr, uid, currency_id, context=ctx).rate141 assert len(ids) == 1, "one sale order at a time can be paid"
119 voucher_vals.update({142 ids = ids[0]
120 'payment_rate_currency_id': payment_rate_currency_id,143 journal_obj = self.pool.get('account.journal')
121 'payment_rate': payment_rate,144
122 })145 sale = self.browse(cr, uid, ids, context=context)
123146 if date is None:
124 voucher_id = voucher_obj.create(cr, uid, voucher_vals, context=context)147 date = sale.date_order
125148 journal = journal_obj.browse(cr, uid, journal_id, context=context)
126 # call on change to search the invoice lines149 self._add_payment(cr, uid, sale, journal, amount, date, description, context=context)
127 onchange_voucher = voucher_obj.onchange_partner_id(150 return True
128 cr, uid, [],151
129 partner_id=sale.partner_id.id,152 def _add_payment(self, cr, uid, sale, journal, amount, date, description, context=None):
130 journal_id=journal.id,153 """ Generate move lines entries to pay the sale order. """
131 amount=amount,154 move_obj = self.pool.get('account.move')
132 currency_id=journal.company_id.currency_id.id,155 period_obj = self.pool.get('account.period')
133 ttype='receipt',156 period_id = period_obj.find(cr, uid, dt=date, context=context)[0]
134 date=date,157 period = period_obj.browse(cr, uid, period_id, context=context)
135 context=context)['value']158 move_name = description or self._get_payment_move_name(cr, uid, journal,
136159 period, context=context)
137 # keep in the voucher only the move line of the160 move_vals = self._prepare_payment_move(cr, uid, move_name, sale,
138 # invoice (eventually) created for this order161 journal, period, date,
139 matching_line = {}162 context=context)
140 if onchange_voucher.get('line_cr_ids'):163 move_lines = self._prepare_payment_move_line(cr, uid, move_name, sale,
141 voucher_lines = onchange_voucher['line_cr_ids']164 journal, period, amount,
142 line_ids = [line['move_line_id'] for line in voucher_lines]165 date, context=context)
143 matching_ids = [line.id for line166
144 in move_line_obj.browse(167 move_vals['line_id'] = [(0, 0, line) for line in move_lines]
145 cr, uid, line_ids, context=context)168 move_obj.create(cr, uid, move_vals, context=context)
146 if line.ref == sale.name]169
147 matching_lines = [line for line170 def _get_payment_move_name(self, cr, uid, journal, period, context=None):
148 in voucher_lines171 if context is None:
149 if line['move_line_id'] in matching_ids]172 context = {}
150 if matching_lines:173 seq_obj = self.pool.get('ir.sequence')
151 matching_line = matching_lines[0]174 sequence = journal.sequence_id
152 matching_line.update({175
153 'amount': amount,176 if not sequence:
154 'voucher_id': voucher_id,177 raise osv.except_osv(
155 })178 _('Configuration Error'),
156179 _('Please define a sequence on the journal %s.') %
157 if matching_line:180 journal.name)
158 voucher_line_obj.create(cr, uid, matching_line, context=context)181 if not sequence.active:
159182 raise osv.except_osv(
160 wf_service = netsvc.LocalService("workflow")183 _('Configuration Error'),
161 wf_service.trg_validate(184 _('Please activate the sequence of the journal %s.') %
162 uid, 'account.voucher', voucher_id, 'proforma_voucher', cr)185 journal.name)
163 sale.write({'payment_ids': [(4,voucher_id)]}, context=context)186
164 return True187 ctx = context.copy()
165188 ctx['fiscalyear_id'] = period.fiscalyear_id.id
189 name = seq_obj.next_by_id(cr, uid, sequence.id, context=ctx)
190 return name
191
192 def _prepare_payment_move(self, cr, uid, move_name, sale, journal,
193 period, date, context=None):
194 return {'name': move_name,
195 'journal_id': journal.id,
196 'date': date,
197 'ref': sale.name,
198 'period_id': period.id,
199 }
200
201 def _prepare_payment_move_line(self, cr, uid, move_name, sale, journal,
202 period, amount, date, context=None):
203 """ """
204 partner_obj = self.pool.get('res.partner')
205 currency_obj = self.pool.get('res.currency')
206 partner = partner_obj._find_accounting_partner(sale.partner_id)
207
208 company = journal.company_id
209
210 currency_id = False
211 amount_currency = 0.0
212 if journal.currency and journal.currency.id != company.currency_id.id:
213 currency_id = journal.currency.id
214 amount_currency, amount = (amount,
215 currency_obj.compute(cr, uid,
216 currency_id,
217 company.currency_id.id,
218 amount,
219 context=context))
220
221 # payment line (bank / cash)
222 debit_line = {
223 'name': move_name,
224 'debit': amount,
225 'credit': 0.0,
226 'account_id': journal.default_credit_account_id.id,
227 'journal_id': journal.id,
228 'period_id': period.id,
229 'partner_id': partner.id,
230 'date': date,
231 'amount_currency': amount_currency,
232 'currency_id': currency_id,
233 }
234
235 # payment line (receivable)
236 credit_line = {
237 'name': move_name,
238 'debit': 0.0,
239 'credit': amount,
240 'account_id': partner.property_account_receivable.id,
241 'journal_id': journal.id,
242 'period_id': period.id,
243 'partner_id': partner.id,
244 'date': date,
245 'amount_currency': -amount_currency,
246 'currency_id': currency_id,
247 'sale_ids': [(4, sale.id)],
248 }
249 return debit_line, credit_line
250
251 def onchange_payment_method_id(self, cr, uid, ids, payment_method_id, context=None):
252 if not payment_method_id:
253 return {}
254 result = {}
255 method_obj = self.pool.get('payment.method')
256 method = method_obj.browse(cr, uid, payment_method_id, context=context)
257 if method.payment_term_id:
258 result['payment_term'] = method.payment_term_id.id
259 return {'value': result}
260
261 def action_view_payments(self, cr, uid, ids, context=None):
262 """ Return an action to display the payment linked
263 with the sale order """
264
265 mod_obj = self.pool.get('ir.model.data')
266 act_obj = self.pool.get('ir.actions.act_window')
267
268 payment_ids = []
269 for so in self.browse(cr, uid, ids, context=context):
270 payment_ids += [move.id for move in so.payment_ids]
271
272 ref = mod_obj.get_object_reference(cr, uid, 'account',
273 'action_move_journal_line')
274 action_id = False
275 if ref:
276 __, action_id = ref
277 action = act_obj.read(cr, uid, [action_id], context=context)[0]
278
279 # choose the view_mode accordingly
280 if len(payment_ids) > 1:
281 action['domain'] = str([('id', 'in', payment_ids)])
282 else:
283 ref = mod_obj.get_object_reference(cr, uid, 'account',
284 'view_move_form')
285 action['views'] = [(ref[1] if ref else False, 'form')]
286 action['res_id'] = payment_ids[0] if payment_ids else False
287 return action
288
289 def action_cancel(self, cr, uid, ids, context=None):
290 for sale in self.browse(cr, uid, ids, context=context):
291 if sale.payment_ids:
292 raise osv.except_osv(
293 _('Cannot cancel this sales order!'),
294 _('Automatic payment entries are linked '
295 'with the sale order.'))
296 return super(sale_order, self).action_cancel(cr, uid, ids, context=context)
166297
=== modified file 'sale_payment_method/sale_view.xml'
--- sale_quick_payment/sale_view.xml 2012-12-26 13:13:25 +0000
+++ sale_payment_method/sale_view.xml 2013-10-13 16:10:00 +0000
@@ -1,48 +1,47 @@
1<?xml version="1.0" encoding="utf-8"?>1<?xml version="1.0" encoding="utf-8"?>
2<!--2<!--
3 sale_quick_payment for OpenERP3 sale_payment_method for OpenERP
4 Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>4 Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>
5 The licence is in the file __openerp__.py5 The licence is in the file __openerp__.py
6-->6-->
77
8<openerp>8<openerp>
9 <data>9 <data>
10 10
11 <!-- INHERITED VIEW FOR THE OBJECT : sale_order -->11 <!-- INHERITED VIEW FOR THE OBJECT : sale_order -->
1212
13 <record id="sale_order_view_form" model="ir.ui.view">13 <record id="sale_order_view_form" model="ir.ui.view">
14 <field name="name">sale_quick_payment.sale_order.view_form</field>14 <field name="name">sale.order.view.form</field>
15 <field name="model">sale.order</field>15 <field name="model">sale.order</field>
16 <field name="inherit_id" ref="sale.view_order_form" />16 <field name="inherit_id" ref="sale.view_order_form" />
17 <field eval="16" name="priority"/>
18 <field name="type">form</field>
19 <field name="arch" type="xml">17 <field name="arch" type="xml">
20 <button name="print_quotation" position="after">
21 <button name="%(open_pay_sale_order)d" string="Register Payments" type="action" states="draft,sent"/>
22 </button>
23 <page string="Other Information" position="after">18 <page string="Other Information" position="after">
24 <page name="automation_information" string="Automation Information">19 <page name="automation_information" string="Automation Information">
25 <group name="payment_information" colspan="4">20 <group name="payment_information" colspan="4">
26 <field name="payment_method_id" />21 <field name="payment_method_id"
27 <group name="payments" colspan="4">22 on_change="onchange_payment_method_id(payment_method_id)"/>
28 <separator string="Payments" colspan="4"/>
29 <field name="payment_ids" nolabel="1" />
30 </group>
31 </group>23 </group>
32 </page>24 </page>
33 </page>25 </page>
34 <field name="amount_total" position="after">26 <field name="amount_total" position="after">
35 <field name="residual" invisible="1"/>27 <field name="residual" invisible="1"/>
36 </field>28 </field>
29
30 <button string="Create Invoice" position="after">
31 <field name="payment_exists" invisible="1"/>
32 <button name="action_view_payments"
33 string="View Automatic Payment"
34 type="object" class="oe_highlight"
35 attrs="{'invisible': [('payment_exists', '=', False)]}"
36 groups="base.group_user"/>
37 </button>
37 </field>38 </field>
38 </record>39 </record>
3940
40 <record id="sale_order_view_tree" model="ir.ui.view">41 <record id="sale_order_view_tree" model="ir.ui.view">
41 <field name="name">sale_quick_payment.sale_order.view_tree</field>42 <field name="name">sale.order.view.tree</field>
42 <field name="model">sale.order</field>43 <field name="model">sale.order</field>
43 <field name="inherit_id" ref="sale.view_order_tree" />44 <field name="inherit_id" ref="sale.view_order_tree" />
44 <field eval="16" name="priority"/>
45 <field name="type">tree</field>
46 <field name="arch" type="xml">45 <field name="arch" type="xml">
47 <field name="state" position="after">46 <field name="state" position="after">
48 <field name="payment_method_id" />47 <field name="payment_method_id" />
@@ -50,5 +49,30 @@
50 </field>49 </field>
51 </record>50 </record>
5251
52 <record id="view_quotation_tree" model="ir.ui.view">
53 <field name="name">sale.order.view.tree</field>
54 <field name="model">sale.order</field>
55 <field name="inherit_id" ref="sale.view_quotation_tree" />
56 <field name="arch" type="xml">
57 <field name="amount_total" position="after">
58 <field name="amount_paid"/>
59 <field name="payment_method_id"/>
60 </field>
61 </field>
62 </record>
63
64
65 <record id="view_sales_order_filter" model="ir.ui.view">
66 <field name="model">sale.order</field>
67 <field name="inherit_id" ref="sale.view_sales_order_filter"/>
68 <field name="arch" type="xml">
69 <filter name="my_sale_orders_filter" position="before">
70 <filter string="With Payment" domain="[('payment_ids','!=',False)]" help="Order With Payment" name="with_payment"/>
71 <separator/>
72 </filter>
73 </field>
74 </record>
75
76
53 </data>77 </data>
54</openerp>78</openerp>
5579
=== added directory 'sale_quick_payment'
=== added file 'sale_quick_payment/__init__.py'
--- sale_quick_payment/__init__.py 1970-01-01 00:00:00 +0000
+++ sale_quick_payment/__init__.py 2013-10-13 16:10:00 +0000
@@ -0,0 +1,22 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# sale_quick_payment for OpenERP
5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22from . import wizard
023
=== added file 'sale_quick_payment/__openerp__.py'
--- sale_quick_payment/__openerp__.py 1970-01-01 00:00:00 +0000
+++ sale_quick_payment/__openerp__.py 2013-10-13 16:10:00 +0000
@@ -0,0 +1,55 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# sale_payment_method for OpenERP
5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22
23{
24 'name': 'Sale Quick Payment',
25 'version': '0.2',
26 'category': 'Generic Modules/Others',
27 'license': 'AGPL-3',
28 'description': """
29Sale Quick Payment
30==================
31
32Sale Quick Payment gives the possibility to pay a sale order from the
33sale order itself.
34
35The payment will be linked to the sale order.
36
37If you install the module Sale Automatic Workflow, you can forbid the
38validation of an unpaid order and the invoice will be automatically
39reconciled with the payment.
40
41This module was originally designed for the e-commerce sector, but it
42does not preclude to use it in other sectors.
43 """,
44 'author': 'Akretion',
45 'website': 'http://www.akretion.com/',
46 'depends': ['sale_payment_method',
47 'sale_exceptions',
48 ],
49 'data': ['wizard/pay_sale_order.xml',
50 'sale_view.xml',
51 'settings/sale.exception.csv',
52 ],
53 'demo': [],
54 'installable': True,
55}
056
=== removed file 'sale_quick_payment/account_voucher.py'
--- sale_quick_payment/account_voucher.py 2012-12-26 09:32:43 +0000
+++ sale_quick_payment/account_voucher.py 1970-01-01 00:00:00 +0000
@@ -1,33 +0,0 @@
1# -*- encoding: utf-8 -*-
2###############################################################################
3#
4# sale_quick_payment for OpenERP
5# Copyright (C) 2012-TODAY Akretion <http://www.akretion.com>.
6# All Rights Reserved
7# @author Sébastien BEAU <sebastien.beau@akretion.com>
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Affero General Public License as
10# published by the Free Software Foundation, either version 3 of the
11# License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU Affero General Public License for more details.
17#
18# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#
21###############################################################################
22
23from openerp.osv.orm import Model
24from openerp.osv import fields
25
26class payment_method(Model):
27 _inherit = "account.voucher"
28
29 _columns = {
30 'order_ids': fields.many2many('sale.order', string='Sale Order'),
31 }
32
33
340
=== added file 'sale_quick_payment/sale_view.xml'
--- sale_quick_payment/sale_view.xml 1970-01-01 00:00:00 +0000
+++ sale_quick_payment/sale_view.xml 2013-10-13 16:10:00 +0000
@@ -0,0 +1,40 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!--
3 sale_quick_payment for OpenERP
4 Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>
5 The licence is in the file __openerp__.py
6-->
7
8<openerp>
9 <data>
10
11 <!-- INHERITED VIEW FOR THE OBJECT : sale_order -->
12
13 <record id="sale_order_view_form" model="ir.ui.view">
14 <field name="name">sale_quick_payment.sale_order.view_form</field>
15 <field name="model">sale.order</field>
16 <field name="inherit_id" ref="sale_payment_method.sale_order_view_form" />
17 <field name="arch" type="xml">
18 <button name="print_quotation" position="after">
19 <button name="%(open_pay_sale_order)d"
20 string="Register Payments"
21 type="action" states="draft,sent"/>
22 </button>
23 <field name="payment_method_id" position="after" >
24 <group name="payments" string="Generated Payments" colspan="4">
25 <field name="payment_ids" nolabel="1">
26 <tree string="Payment">
27 <field name="date"/>
28 <field name="journal_id"/>
29 <field name="partner_id"/>
30 <field name="debit"/>
31 <field name="credit"/>
32 </tree>
33 </field>
34 </group>
35 </field>
36 </field>
37 </record>
38
39 </data>
40</openerp>
041
=== renamed directory 'sale_quick_payment/settings' => 'sale_quick_payment/settings'
=== renamed directory 'sale_quick_payment/wizard' => 'sale_quick_payment/wizard'
=== modified file 'sale_quick_payment/wizard/__init__.py'
--- sale_quick_payment/wizard/__init__.py 2012-04-22 12:48:34 +0000
+++ sale_quick_payment/wizard/__init__.py 2013-10-13 16:10:00 +0000
@@ -1,1 +1,1 @@
1import pay_sale_order1from . import pay_sale_order
22
=== modified file 'sale_quick_payment/wizard/pay_sale_order.py'
--- sale_quick_payment/wizard/pay_sale_order.py 2012-12-26 09:32:43 +0000
+++ sale_quick_payment/wizard/pay_sale_order.py 2013-10-13 16:10:00 +0000
@@ -1,47 +1,47 @@
1# -*- encoding: utf-8 -*-1# -*- coding: utf-8 -*-
2#################################################################################2##############################################################################
3# #3#
4# Magentoerpconnect for OpenERP #4# sale_quick_payment for OpenERP
5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com> #5# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@akretion.com>
6# #6#
7# This program is free software: you can redistribute it and/or modify #7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as #8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the #9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version. #10# License, or (at your option) any later version.
11# #11#
12# This program is distributed in the hope that it will be useful, #12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details. #15# GNU Affero General Public License for more details.
16# #16#
17# You should have received a copy of the GNU Affero General Public License #17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19# #19#
20#################################################################################20##############################################################################
2121
2222from openerp.osv import orm, fields
23from openerp.osv.orm import TransientModel23import openerp.addons.decimal_precision as dp
24from openerp.osv import fields24
25import decimal_precision as dp25
26from datetime import datetime26class pay_sale_order(orm.TransientModel):
27
28#TODO add button on sale_form header instead of more button
29
30class pay_sale_order(TransientModel):
31 _name = 'pay.sale.order'27 _name = 'pay.sale.order'
32 _description = 'Wizard to generate a payment from the sale order'28 _description = 'Wizard to generate a payment from the sale order'
3329
34 _columns = {30 _columns = {
35 'journal_id': fields.many2one('account.journal', 'Journal'),31 'journal_id': fields.many2one('account.journal', 'Journal'),
36 'amount': fields.float('Amount', digits_compute=dp.get_precision('Sale Price')),32 'amount': fields.float('Amount',
33 digits_compute=dp.get_precision('Sale Price')),
37 'date': fields.datetime('Payment Date'),34 'date': fields.datetime('Payment Date'),
38 }35 'description': fields.char('Description', size=64),
36 }
3937
40 def _get_journal_id(self, cr, uid, context=None):38 def _get_journal_id(self, cr, uid, context=None):
41 if context is None:39 if context is None:
42 context = {}40 context = {}
43 if context.get('active_id'):41 if context.get('active_id'):
44 order = self.pool.get('sale.order').browse(cr, uid, context['active_id'], context=context)42 sale_obj = self.pool.get('sale.order')
43 order = sale_obj.browse(cr, uid, context['active_id'],
44 context=context)
45 if order.payment_method_id:45 if order.payment_method_id:
46 return order.payment_method_id.journal_id.id46 return order.payment_method_id.journal_id.id
47 return False47 return False
@@ -50,7 +50,9 @@
50 if context is None:50 if context is None:
51 context = {}51 context = {}
52 if context.get('active_id'):52 if context.get('active_id'):
53 order = self.pool.get('sale.order').browse(cr, uid, context['active_id'], context=context)53 sale_obj = self.pool.get('sale.order')
54 order = sale_obj.browse(cr, uid, context['active_id'],
55 context=context)
54 return order.residual56 return order.residual
55 return False57 return False
5658
@@ -61,25 +63,22 @@
61 }63 }
6264
63 def pay_sale_order(self, cr, uid, ids, context=None):65 def pay_sale_order(self, cr, uid, ids, context=None):
64 """66 """ Pay the sale order """
65 Pay the sale order
66 @param cr: the current row, from the database cursor,
67 @param uid: the current user’s ID for security checks,
68 @param ids: List of account chart’s IDs
69 @return: dictionary of Product list window for a given attributs set
70 """
71 wizard = self.browse(cr, uid, ids[0], context=context)67 wizard = self.browse(cr, uid, ids[0], context=context)
72 self.pool.get('sale.order').pay_sale_order(cr, uid, context['active_id'], wizard.journal_id.id, wizard.amount, wizard.date, context=context)68 sale_obj = self.pool.get('sale.order')
69 sale_obj.add_payment(cr, uid,
70 context['active_id'],
71 wizard.journal_id.id,
72 wizard.amount,
73 wizard.date,
74 description=wizard.description,
75 context=context)
73 return {'type': 'ir.actions.act_window_close'}76 return {'type': 'ir.actions.act_window_close'}
7477
75 def pay_sale_order_and_confirm(self, cr, uid, ids, context=None):78 def pay_sale_order_and_confirm(self, cr, uid, ids, context=None):
76 """79 """ Pay the sale order """
77 Pay the sale order
78 @param cr: the current row, from the database cursor,
79 @param uid: the current user’s ID for security checks,
80 @param ids: List of account chart’s IDs
81 @return: dictionary of Product list window for a given attributs set
82 """
83 self.pay_sale_order(cr, uid, ids, context=context)80 self.pay_sale_order(cr, uid, ids, context=context)
84 return self.pool.get('sale.order').action_button_confirm(cr, uid, [context['active_id']], context=context)81 sale_obj = self.pool.get('sale.order')
85 82 return sale_obj.action_button_confirm(cr, uid,
83 [context['active_id']],
84 context=context)
8685
=== modified file 'sale_quick_payment/wizard/pay_sale_order.xml'
--- sale_quick_payment/wizard/pay_sale_order.xml 2012-12-26 09:32:43 +0000
+++ sale_quick_payment/wizard/pay_sale_order.xml 2013-10-13 16:10:00 +0000
@@ -4,10 +4,10 @@
4 <record model="ir.ui.view" id="pay_sale_order_view">4 <record model="ir.ui.view" id="pay_sale_order_view">
5 <field name="name">pay.sale.order.view</field>5 <field name="name">pay.sale.order.view</field>
6 <field name="model">pay.sale.order</field>6 <field name="model">pay.sale.order</field>
7 <field name="type">form</field>
8 <field name="arch" type="xml">7 <field name="arch" type="xml">
9 <form string="Pay Sale Order" version="7.0">8 <form string="Pay Sale Order" version="7.0">
10 <group>9 <group>
10 <field name="description" string="Description"/>
11 <field name="journal_id" string="Journal"/>11 <field name="journal_id" string="Journal"/>
12 <field name="amount" string="Paid Amount"/>12 <field name="amount" string="Paid Amount"/>
13 <field name="date" string="Date"/>13 <field name="date" string="Date"/>

Subscribers

People subscribed via source and target branches