diff --git a/sale_payment_method/README.rst b/sale_payment_method/README.rst new file mode 100644 index 00000000000..516fce7cad3 --- /dev/null +++ b/sale_payment_method/README.rst @@ -0,0 +1,61 @@ +Sale Payment Method +=================== + +It adds a payment method on the sales orders and allow to register +payments entries on sales orders. + +This module is low level and works well with the following modules: +* **Sale Automatic Worflow** and **Sale Payment Method - Automatic Workflow** + the payments created with this module will be automatically reconciled + with the invoices of the sales orders. +* Sale Quick Payment: allows to create the payments with a button on the + sales orders. + +Also, the e-commerce connectors such as the **Magento Connector** or +**Prestashop Connector** use it to create the external payments. + +Installation +============ + +Nothing special is required. + +Configuration +============= + +The payment methods can be configured in **Sales > Configuration > +Sales > Payment Methods**. + +Usage +===== + +A new field on sales orders allow to select the payment method used on +this sales order. + +Known issues / Roadmap +====================== + + * It accepts only one method per sale order. + +Credits +======= + +Contributors +------------ + +* Guewen Baconnier +* Sébastien Beau +* Arthur Vuillard +* Jan-Philipp Fischer + +Maintainer +---------- + +.. image:: http://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: http://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. + +To contribute to this module, please visit http://odoo-community.org. diff --git a/sale_payment_method/__init__.py b/sale_payment_method/__init__.py new file mode 100644 index 00000000000..6f10dd35c1b --- /dev/null +++ b/sale_payment_method/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# sale_payment_method for OpenERP +# Copyright (C) 2011 Akretion Sébastien BEAU +# +# 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 . import sale +from . import payment_method +from . import account_move diff --git a/sale_payment_method/__openerp__.py b/sale_payment_method/__openerp__.py new file mode 100644 index 00000000000..d450a48cd6f --- /dev/null +++ b/sale_payment_method/__openerp__.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# sale_payment_method for OpenERP +# Copyright (C) 2011 Akretion Sébastien BEAU +# +# 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': 'Sale Payment Method', + 'version': '0.2.1', + 'category': 'Generic Modules/Others', + 'license': 'AGPL-3', + 'author': "Akretion,Odoo Community Association (OCA)", + 'website': 'http://www.akretion.com/', + 'depends': ['sale', + ], + 'data': ['sale_view.xml', + 'payment_method_view.xml', + 'security/ir.model.access.csv', + 'security/rules.xml', + ], + 'demo': [], + 'installable': True, + } diff --git a/sale_payment_method/account_move.py b/sale_payment_method/account_move.py new file mode 100644 index 00000000000..291bc309211 --- /dev/null +++ b/sale_payment_method/account_move.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: Guewen Baconnier +# Copyright 2013 Camptocamp SA +# +# 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 openerp import models, fields + + +class AccountMoveLine(models.Model): + _inherit = 'account.move.line' + + sale_ids = fields.Many2many(comodel_name='sale.order', + string='Sales Orders') diff --git a/sale_payment_method/i18n/es.po b/sale_payment_method/i18n/es.po new file mode 100644 index 00000000000..a6f6fff34c2 --- /dev/null +++ b/sale_payment_method/i18n/es.po @@ -0,0 +1,138 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * sale_payment_method +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-05-02 07:06+0000\n" +"PO-Revision-Date: 2014-06-24 11:55+0100\n" +"Last-Translator: Alberto Garcia \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" + +#. module: sale_payment_method +#: view:sale.order:0 +msgid "Automation Information" +msgstr "Información Automática" + +#. module: sale_payment_method +#: help:payment.method,journal_id:0 +msgid "If a journal is selected, when a payment is recorded on a backend, payment entries will be created in this journal. " +msgstr "Si un diario es sleccionado, cuando un pago es registrado en el backend, las entradas de los pagos serán creadas en ese diario" + +#. module: sale_payment_method +#: view:payment.method:0 +msgid "" +"Even if the E-commerce backend receives a payment for a sale order,\n" +" no payment entries will be generated." +msgstr "Incluso si el E-commerce backend recibe un pago de un pedido de venta," + +#. module: sale_payment_method +#: view:payment.method:0 +msgid "Default Values" +msgstr "Valores por defecto" + +#. module: sale_payment_method +#: model:ir.model,name:sale_payment_method.model_payment_method +#: field:sale.order,payment_method_id:0 +msgid "Payment Method" +msgstr "Método de pago" + +#. module: sale_payment_method +#: view:sale.order:0 +msgid "View Automatic Payment" +msgstr "Ver Pago Automático" + +#. module: sale_payment_method +#: field:payment.method,journal_id:0 +msgid "Journal" +msgstr "Diario" + +#. module: sale_payment_method +#: model:ir.actions.act_window,name:sale_payment_method.act_payment_method_form +#: model:ir.ui.menu,name:sale_payment_method.menu_action_paymetn_method_form +msgid "Payment Methods " +msgstr "Métodos de Pago" + +#. module: sale_payment_method +#: field:account.move,order_ids:0 +msgid "Sales Orders" +msgstr "Pedidos de venta" + +#. module: sale_payment_method +#: view:sale.order:0 +msgid "Other Information" +msgstr "Otra información" + +#. module: sale_payment_method +#: view:payment.method:0 +msgid "Payment Methods" +msgstr "Métodos de pago" + +#. module: sale_payment_method +#: field:payment.method,name:0 +msgid "Name" +msgstr "Nombre" + +#. module: sale_payment_method +#: field:sale.order,payment_ids:0 +msgid "Payments Entries" +msgstr "Entradas de pagos" + +#. module: sale_payment_method +#: view:payment.method:0 +msgid "" +"When the E-commerce backend will receive a payment for a sale order,\n" +" payment entries will be generated in the selected journal." +msgstr "Cuando el E-commerce backend recibe un pago para un pedido de venta," + +#. module: sale_payment_method +#: view:payment.method:0 +msgid "Journal for payment" +msgstr "Diario de pago" + +#. module: sale_payment_method +#: field:sale.order,residual:0 +msgid "Balance" +msgstr "Balance" + +#. module: sale_payment_method +#: model:ir.model,name:sale_payment_method.model_account_move +msgid "Account Entry" +msgstr "Apunte Contable" + +#. module: sale_payment_method +#: help:payment.method,payment_term_id:0 +msgid "Default payment term of a sale order using this method." +msgstr "Forma de pago por defecto de un pedido de venta usado por este método." + +#. module: sale_payment_method +#: field:payment.method,payment_term_id:0 +msgid "Payment Term" +msgstr "Modo de pago" + +#. module: sale_payment_method +#: view:sale.order:0 +msgid "Create Invoice" +msgstr "Crear Factura" + +#. module: sale_payment_method +#: help:payment.method,name:0 +msgid "The name of the method on the backend" +msgstr "El nombre del método en el backend" + +#. module: sale_payment_method +#: model:ir.model,name:sale_payment_method.model_sale_order +msgid "Sales Order" +msgstr "Pediso de Ventas" + +#. module: sale_payment_method +#: field:sale.order,payment_exists:0 +msgid "Has automatic payment" +msgstr "Tiene pago automático" + diff --git a/sale_payment_method/i18n/fr.po b/sale_payment_method/i18n/fr.po new file mode 100644 index 00000000000..a554e06574b --- /dev/null +++ b/sale_payment_method/i18n/fr.po @@ -0,0 +1,210 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * sale_payment_method +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-02-13 13:51+0000\n" +"PO-Revision-Date: 2013-05-02 07:06+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sale_payment_method +#: code:addons/sale_payment_method/sale.py:99 +#, python-format +msgid "" +"An automatic payment can not be created for the sale order %s because it has " +"no payment method." +msgstr "Aucun paiement automatique ne peut être créé pour la commande %s parce " +"qu'elle n'a pas de méthode de paiement." + +#. module: sale_payment_method +#: code:addons/sale_payment_method/sale.py:105 +#, python-format +msgid "" +"An automatic payment should be created for the sale order %s but the payment " +"method '%s' has no journal defined." +msgstr "Un paiement automatique doit être généré pour la commande %s mais la " +"méthode de paiement '%s' n'a aucun journal séléctionné." + +#. module: sale_payment_method +#: code:addons/sale_payment_method/sale.py:75 +#, python-format +msgid "" +"Cannot cancel this sales order because automatic payment entries are linked " +"with it." +msgstr "Impossible d'annuler cette commande parce que des paiement automatiques " +"y sont liés." + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +#: field:payment.method,company_id:0 +msgid "Company" +msgstr "Société" + +#. module: sale_payment_method +#: view:sale.order:sale_payment_method.sale_order_view_form +msgid "Create Invoice" +msgstr "Créer la facture" + +#. module: sale_payment_method +#: field:payment.method,create_uid:0 +msgid "Created by" +msgstr "" + +#. module: sale_payment_method +#: field:payment.method,create_date:0 +msgid "Created on" +msgstr "" + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +msgid "Default Values" +msgstr "Valeurs par défaut" + +#. module: sale_payment_method +#: help:payment.method,payment_term_id:0 +msgid "Default payment term of a sale order using this method." +msgstr "" +"Condition de règlement par défaut pour les commandes utilisant cette méthode." + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +msgid "" +"Even if the E-commerce backend receives a payment for a sale order,\n" +" no payment entries will be generated." +msgstr "" +"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." + +#. module: sale_payment_method +#: field:payment.method,id:0 +msgid "ID" +msgstr "" + +#. module: sale_payment_method +#: help:payment.method,journal_id:0 +msgid "" +"If a journal is selected, when a payment is recorded on a backend, payment " +"entries will be created in this journal." +msgstr "" +"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." + +#. module: sale_payment_method +#: field:payment.method,journal_id:0 +msgid "Journal" +msgstr "Journal" + +#. module: sale_payment_method +#: model:ir.model,name:sale_payment_method.model_account_move_line +msgid "Journal Items" +msgstr "Pièces comptables" + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +msgid "Journal for payment" +msgstr "Journal pour le paiement" + +#. module: sale_payment_method +#: field:payment.method,write_uid:0 +msgid "Last Updated by" +msgstr "" + +#. module: sale_payment_method +#: field:payment.method,write_date:0 +msgid "Last Updated on" +msgstr "" + +#. module: sale_payment_method +#: field:payment.method,name:0 +msgid "Name" +msgstr "Nom" + +#. module: sale_payment_method +#: view:sale.order:sale_payment_method.view_sales_order_filter +msgid "Order With Payment" +msgstr "Commande avec paiement" + +#. module: sale_payment_method +#: model:ir.model,name:sale_payment_method.model_payment_method +#: field:sale.order,payment_method_id:0 +msgid "Payment Method" +msgstr "Méthode de paiement" + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +#: view:payment.method:sale_payment_method.payment_method_view_tree +msgid "Payment Methods" +msgstr "Méthodes de paiement" + +#. module: sale_payment_method +#: model:ir.actions.act_window,name:sale_payment_method.act_payment_method_form +#: model:ir.ui.menu,name:sale_payment_method.menu_action_paymetn_method_form +msgid "Payment Methods " +msgstr "Méthodes de paiement" + +#. module: sale_payment_method +#: field:payment.method,payment_term_id:0 +msgid "Payment Term" +msgstr "Condition de règlement" + +#. module: sale_payment_method +#: field:sale.order,payment_ids:0 +msgid "Payments Entries" +msgstr "Écritures de paiement" + +#. module: sale_payment_method +#: code:addons/sale_payment_method/sale.py:159 +#, python-format +msgid "Please activate the sequence of the journal %s." +msgstr "Veuillez activer la séquence sur le journal %s." + +#. module: sale_payment_method +#: code:addons/sale_payment_method/sale.py:156 +#, python-format +msgid "Please define a sequence on the journal %s." +msgstr "Veuillez définir une séquence sur le journal %s." + +#. module: sale_payment_method +#: model:ir.model,name:sale_payment_method.model_sale_order +msgid "Sales Order" +msgstr "Bon de commande" + +#. module: sale_payment_method +#: field:account.move.line,sale_ids:0 +msgid "Sales Orders" +msgstr "Bons de commande" + +#. module: sale_payment_method +#: help:payment.method,name:0 +msgid "The name of the method on the backend" +msgstr "Nom de la méthode sur le backend" + +#. module: sale_payment_method +#: view:sale.order:sale_payment_method.sale_order_view_form +msgid "View Automatic Payment" +msgstr "Voir les paiements automatiques" + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +msgid "" +"When the E-commerce backend will receive a payment for a sale order,\n" +" payment entries will be generated in the " +"selected journal." +msgstr "" +"Lorsque le backend e-commerce reçoit un paiement pour la commande,\n" +" des écritures de paiement sont générées dans " +"le journal sélectionné." + +#. module: sale_payment_method +#: view:sale.order:sale_payment_method.view_sales_order_filter +msgid "With Payment" +msgstr "Avec paiement" diff --git a/sale_payment_method/i18n/sale_payment_method.pot b/sale_payment_method/i18n/sale_payment_method.pot new file mode 100644 index 00000000000..71ea66b516c --- /dev/null +++ b/sale_payment_method/i18n/sale_payment_method.pot @@ -0,0 +1,188 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_payment_method +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-02-13 13:51+0000\n" +"PO-Revision-Date: 2015-02-13 13:51+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: sale_payment_method +#: code:addons/sale_payment_method/sale.py:99 +#, python-format +msgid "An automatic payment can not be created for the sale order %s because it has no payment method." +msgstr "" + +#. module: sale_payment_method +#: code:addons/sale_payment_method/sale.py:105 +#, python-format +msgid "An automatic payment should be created for the sale order %s but the payment method '%s' has no journal defined." +msgstr "" + +#. module: sale_payment_method +#: code:addons/sale_payment_method/sale.py:75 +#, python-format +msgid "Cannot cancel this sales order because automatic payment entries are linked with it." +msgstr "" + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +#: field:payment.method,company_id:0 +msgid "Company" +msgstr "" + +#. module: sale_payment_method +#: view:sale.order:sale_payment_method.sale_order_view_form +msgid "Create Invoice" +msgstr "" + +#. module: sale_payment_method +#: field:payment.method,create_uid:0 +msgid "Created by" +msgstr "" + +#. module: sale_payment_method +#: field:payment.method,create_date:0 +msgid "Created on" +msgstr "" + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +msgid "Default Values" +msgstr "" + +#. module: sale_payment_method +#: help:payment.method,payment_term_id:0 +msgid "Default payment term of a sale order using this method." +msgstr "" + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +msgid "Even if the E-commerce backend receives a payment for a sale order,\n" +" no payment entries will be generated." +msgstr "" + +#. module: sale_payment_method +#: field:payment.method,id:0 +msgid "ID" +msgstr "" + +#. module: sale_payment_method +#: help:payment.method,journal_id:0 +msgid "If a journal is selected, when a payment is recorded on a backend, payment entries will be created in this journal." +msgstr "" + +#. module: sale_payment_method +#: field:payment.method,journal_id:0 +msgid "Journal" +msgstr "" + +#. module: sale_payment_method +#: model:ir.model,name:sale_payment_method.model_account_move_line +msgid "Journal Items" +msgstr "" + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +msgid "Journal for payment" +msgstr "" + +#. module: sale_payment_method +#: field:payment.method,write_uid:0 +msgid "Last Updated by" +msgstr "" + +#. module: sale_payment_method +#: field:payment.method,write_date:0 +msgid "Last Updated on" +msgstr "" + +#. module: sale_payment_method +#: field:payment.method,name:0 +msgid "Name" +msgstr "" + +#. module: sale_payment_method +#: view:sale.order:sale_payment_method.view_sales_order_filter +msgid "Order With Payment" +msgstr "" + +#. module: sale_payment_method +#: model:ir.model,name:sale_payment_method.model_payment_method +#: field:sale.order,payment_method_id:0 +msgid "Payment Method" +msgstr "" + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +#: view:payment.method:sale_payment_method.payment_method_view_tree +msgid "Payment Methods" +msgstr "" + +#. module: sale_payment_method +#: model:ir.actions.act_window,name:sale_payment_method.act_payment_method_form +#: model:ir.ui.menu,name:sale_payment_method.menu_action_paymetn_method_form +msgid "Payment Methods " +msgstr "" + +#. module: sale_payment_method +#: field:payment.method,payment_term_id:0 +msgid "Payment Term" +msgstr "" + +#. module: sale_payment_method +#: field:sale.order,payment_ids:0 +msgid "Payments Entries" +msgstr "" + +#. module: sale_payment_method +#: code:addons/sale_payment_method/sale.py:159 +#, python-format +msgid "Please activate the sequence of the journal %s." +msgstr "" + +#. module: sale_payment_method +#: code:addons/sale_payment_method/sale.py:156 +#, python-format +msgid "Please define a sequence on the journal %s." +msgstr "" + +#. module: sale_payment_method +#: model:ir.model,name:sale_payment_method.model_sale_order +msgid "Sales Order" +msgstr "" + +#. module: sale_payment_method +#: field:account.move.line,sale_ids:0 +msgid "Sales Orders" +msgstr "" + +#. module: sale_payment_method +#: help:payment.method,name:0 +msgid "The name of the method on the backend" +msgstr "" + +#. module: sale_payment_method +#: view:sale.order:sale_payment_method.sale_order_view_form +msgid "View Automatic Payment" +msgstr "" + +#. module: sale_payment_method +#: view:payment.method:sale_payment_method.payment_method_view_form +msgid "When the E-commerce backend will receive a payment for a sale order,\n" +" payment entries will be generated in the selected journal." +msgstr "" + +#. module: sale_payment_method +#: view:sale.order:sale_payment_method.view_sales_order_filter +msgid "With Payment" +msgstr "" + diff --git a/sale_payment_method/migrations/0.1/post-migration.py b/sale_payment_method/migrations/0.1/post-migration.py new file mode 100644 index 00000000000..3e243cf6077 --- /dev/null +++ b/sale_payment_method/migrations/0.1/post-migration.py @@ -0,0 +1,36 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# sale_quick_payment for OpenERP +# Copyright (C) 2012-TODAY Akretion . +# All Rights Reserved +# @author Sébastien BEAU +# 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 . +# +############################################################################## + +""" r0.1: Migration 6.1 => 7.0.0.1 + migrate the field payment_id from one2many to payment_ids many2many +""" +__name__ = ("sale.order:: V7 change/rename the field payment_id into a" + "many2many with the name payment_ids") + + +def migrate(cr, version): + if version: + cr.execute("INSERT INTO account_voucher_sale_order_rel" + "(sale_order_id, account_voucher_id) " + "(SELECT id, payment_id FROM " + " sale_order " + "WHERE payment_id IS NOT NULL )") diff --git a/sale_payment_method/payment_method.py b/sale_payment_method/payment_method.py new file mode 100644 index 00000000000..e58e0ff0fdd --- /dev/null +++ b/sale_payment_method/payment_method.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# sale_quick_payment for OpenERP +# Copyright (C) 2011 Akretion Sébastien BEAU +# Copyright 2013 Camptocamp SA (Guewen Baconnier) +# +# 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 openerp import models, api, fields + + +class PaymentMethod(models.Model): + _name = "payment.method" + _description = "Payment Method" + + @api.model + @api.returns('res.company') + def _default_company_id(self): + company_model = self.env['res.company'] + return company_model.browse( + company_model._company_default_get('payment.method')) + + name = fields.Char(required=True, + help="The name of the method on the backend") + journal_id = fields.Many2one( + comodel_name='account.journal', + string='Journal', + help="If a journal is selected, when a payment is recorded " + "on a backend, payment entries will be created in this " + "journal.", + ) + payment_term_id = fields.Many2one( + comodel_name='account.payment.term', + string='Payment Term', + help="Default payment term of a sale order using this method.", + ) + company_id = fields.Many2one( + comodel_name='res.company', + string='Company', + default=_default_company_id, + ) diff --git a/sale_payment_method/payment_method_view.xml b/sale_payment_method/payment_method_view.xml new file mode 100644 index 00000000000..8d9d2557d54 --- /dev/null +++ b/sale_payment_method/payment_method_view.xml @@ -0,0 +1,57 @@ + + + + + sale_payment_method.payment_method.view_form + payment.method + +
+

+ +

+ + + + + + +

+ When the E-commerce backend will receive a payment for a sale order, + payment entries will be generated in the selected journal. +

+

+ Even if the E-commerce backend receives a payment for a sale order, + no payment entries will be generated. +

+
+
+ + + +
+
+
+ + + sale_payment_method.payment_method.view_tree + payment.method + + + + + + + + + + + Payment Methods + payment.method + form + tree,form + + + + +
+
diff --git a/sale_payment_method/sale.py b/sale_payment_method/sale.py new file mode 100644 index 00000000000..1e0f88ff30a --- /dev/null +++ b/sale_payment_method/sale.py @@ -0,0 +1,246 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: Guewen Baconnier, Sébastien Beau +# Copyright (C) 2011 Akretion Sébastien BEAU +# Copyright 2013 Camptocamp SA (Guewen Baconnier) +# +# 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 logging +from openerp import api, models, fields, exceptions, _ +import openerp.addons.decimal_precision as dp + +_logger = logging.getLogger(__name__) + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + @api.one + @api.depends('amount_total', 'payment_ids.credit', 'payment_ids.debit') + def _compute_amount(self): + paid_amount = sum(line.credit - line.debit + for line in self.payment_ids) + self.amount_paid = paid_amount + self.residual = self.amount_total - paid_amount + + payment_ids = fields.Many2many( + comodel_name='account.move.line', + string='Payments Entries', + domain=[('account_id.type', '=', 'receivable')], + copy=False, + ) + payment_method_id = fields.Many2one( + comodel_name='payment.method', + string='Payment Method', + ondelete='restrict', + ) + residual = fields.Float( + compute='_compute_amount', + digits_compute=dp.get_precision('Account'), + string='Balance', + store=False, + ) + amount_paid = fields.Float( + compute='_compute_amount', + digits_compute=dp.get_precision('Account'), + string='Amount Paid', + store=False, + ) + + @api.multi + def action_cancel(self): + for sale in self: + if sale.payment_ids: + raise exceptions.Warning(_('Cannot cancel this sales order ' + 'because automatic payment entries ' + 'are linked with it.')) + return super(SaleOrder, self).action_cancel() + + @api.multi + def automatic_payment(self, amount=None): + """ Create the payment entries to pay a sale order, respecting + the payment terms. + If no amount is defined, it will pay the residual amount of the sale + order. + """ + self.ensure_one() + method = self.payment_method_id + if not method: + raise exceptions.Warning( + _("An automatic payment can not be created for the sale " + "order %s because it has no payment method.") % self.name + ) + + if not method.journal_id: + raise exceptions.Warning( + _("An automatic payment should be created for the sale order" + " %s but the payment method '%s' has no journal defined.") % + (self.name, method.name) + ) + + journal = method.journal_id + date = self.date_order[:10] + if amount is None: + amount = self.residual + if self.payment_term: + amounts = self.payment_term.compute(amount, date_ref=date)[0] + else: + amounts = [(date, amount)] + + # reversed is cosmetic, compute returns terms in the 'wrong' order + for date, amount in reversed(amounts): + self._add_payment(journal, amount, date) + return True + + @api.multi + def add_payment(self, journal_id, amount, date=None, description=None): + """ Generate payment move lines of a certain amount linked + with the sale order. + """ + self.ensure_one() + journal_model = self.env['account.journal'] + if date is None: + date = self.date_order + journal = journal_model.browse(journal_id) + self._add_payment(journal, amount, date, description) + return True + + @api.multi + def _add_payment(self, journal, amount, date, description=None): + """ Generate move lines entries to pay the sale order. """ + move_model = self.env['account.move'] + period_model = self.env['account.period'] + period = period_model.find(dt=date) + move_name = description or self._get_payment_move_name(journal, period) + move_vals = self._prepare_payment_move(move_name, journal, + period, date) + move_lines = self._prepare_payment_move_lines(move_name, journal, + period, amount, date) + + move_vals['line_id'] = [(0, 0, line) for line in move_lines] + move_model.create(move_vals) + + @api.model + def _get_payment_move_name(self, journal, period): + sequence = journal.sequence_id + if not sequence: + raise exceptions.Warning(_('Please define a sequence on the ' + 'journal %s.') % journal.name) + if not sequence.active: + raise exceptions.Warning(_('Please activate the sequence of the ' + 'journal %s.') % journal.name) + + sequence = sequence.with_context(fiscalyear_id=period.fiscalyear_id.id) + # next_by_id not compatible with new api + sequence_model = self.pool['ir.sequence'] + name = sequence_model.next_by_id(self.env.cr, self.env.uid, + sequence.id, + context=self.env.context) + return name + + @api.multi + def _prepare_payment_move(self, move_name, journal, period, date): + return {'name': move_name, + 'journal_id': journal.id, + 'date': date, + 'ref': self.name, + 'period_id': period.id, + } + + @api.multi + def _prepare_payment_move_line(self, move_name, journal, period, + amount, date): + # to remove in v9 + _logger.warning('Deprecated: _prepare_payment_move_line has been ' + 'deprecated in favor of _prepare_payment_move_lines') + return self._prepare_payment_move_lines(move_name, journal, period, + amount, date) + + @api.multi + def _prepare_payment_move_lines(self, move_name, journal, period, + amount, date): + partner = self.partner_id.commercial_partner_id + company = journal.company_id + + currency = self.env['res.currency'].browse() + # if the lines are not in a different currency, + # the amount_currency stays at 0.0 + amount_currency = 0.0 + if journal.currency and journal.currency != company.currency_id: + # when the journal have a currency, we have to convert + # the amount to the currency of the company and set + # the journal's currency on the lines + currency = journal.currency + company_amount = currency.compute(amount, company.currency_id) + amount_currency, amount = amount, company_amount + + # payment line (bank / cash) + debit_line = { + 'name': move_name, + 'debit': amount, + 'credit': 0.0, + 'account_id': journal.default_credit_account_id.id, + 'journal_id': journal.id, + 'period_id': period.id, + 'partner_id': partner.id, + 'date': date, + 'amount_currency': amount_currency, + 'currency_id': currency.id, + } + + # payment line (receivable) + credit_line = { + 'name': move_name, + 'debit': 0.0, + 'credit': amount, + 'account_id': partner.property_account_receivable.id, + 'journal_id': journal.id, + 'period_id': period.id, + 'partner_id': partner.id, + 'date': date, + 'amount_currency': -amount_currency, + 'currency_id': currency.id, + 'sale_ids': [(4, self.id)], + } + return debit_line, credit_line + + @api.onchange('payment_method_id') + def onchange_payment_method_id_set_payment_term(self): + if not self.payment_method_id: + return + method = self.payment_method_id + if method.payment_term_id: + self.payment_term = method.payment_term_id.id + + @api.multi + def action_view_payments(self): + """ Return an action to display the payment linked + with the sale order """ + self.ensure_one() + + moves = self.mapped('payment_ids.move_id') + + xmlid = ('account', 'action_move_journal_line') + action = self.env['ir.actions.act_window'].for_xml_id(*xmlid) + if len(moves) > 1: + action['domain'] = [('id', 'in', moves.ids)] + else: + ref = self.env.ref('account.view_move_form') + action['views'] = [(ref.id, 'form')] + action['res_id'] = moves.id if moves else False + return action diff --git a/sale_payment_method/sale_view.xml b/sale_payment_method/sale_view.xml new file mode 100644 index 00000000000..59e37da70ed --- /dev/null +++ b/sale_payment_method/sale_view.xml @@ -0,0 +1,63 @@ + + + + + sale.order.view.form + sale.order + + + + + + + + + + + + + + + + sale.order.view.tree + sale.order + + + + + + + + + + sale.order.view.tree + sale.order + + + + + + + + + + + + sale.order + + + + + + + + + + diff --git a/sale_payment_method/security/ir.model.access.csv b/sale_payment_method/security/ir.model.access.csv new file mode 100644 index 00000000000..13bf2263dcc --- /dev/null +++ b/sale_payment_method/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_payment_method_user,sale_quick_payment_payment_method_user,model_payment_method,base.group_user,1,0,0,0 +access_payment_method_manager,sale_quick_payment_payment_method_manager,model_payment_method,base.group_sale_manager,1,1,1,1 diff --git a/sale_payment_method/security/rules.xml b/sale_payment_method/security/rules.xml new file mode 100644 index 00000000000..b66174aa14b --- /dev/null +++ b/sale_payment_method/security/rules.xml @@ -0,0 +1,13 @@ + + + + + + Payment method multi-company + + + ['|','|',('company_id.child_ids','child_of',[user.company_id.id]),('company_id','child_of',[user.company_id.id]),('company_id','=',False)] + + + +