From 48b535f2542ee5cc61c887bd402b6275112d2b11 Mon Sep 17 00:00:00 2001 From: Patrik Dufresne Date: Wed, 9 May 2018 14:49:20 -0400 Subject: [PATCH] Revert "Remove membership_variable_period." This reverts commit 3bc974813e32e5105184c1b9f4db7f8fa539e9b2. --- membership_variable_period/README.rst | 72 ++ membership_variable_period/__init__.py | 5 + membership_variable_period/__openerp__.py | 22 + .../data/membership_data.xml | 18 + membership_variable_period/i18n/de.po | 107 +++ membership_variable_period/i18n/es.po | 106 +++ .../i18n/membership_variable_period.pot | 97 +++ membership_variable_period/i18n/pt_BR.po | 106 +++ membership_variable_period/i18n/sl.po | 107 +++ membership_variable_period/models/__init__.py | 6 + .../models/account_invoice.py | 91 +++ .../models/product_template.py | 63 ++ .../models/res_partner.py | 19 + .../static/description/icon.png | Bin 0 -> 7979 bytes .../static/description/icon.svg | 455 +++++++++++ .../static/description/icon_main.svg | 735 ++++++++++++++++++ membership_variable_period/tests/__init__.py | 5 + .../tests/test_membership_variable_period.py | 156 ++++ .../views/product_template_views.xml | 74 ++ .../views/res_partner_views.xml | 17 + 20 files changed, 2261 insertions(+) create mode 100644 membership_variable_period/README.rst create mode 100644 membership_variable_period/__init__.py create mode 100644 membership_variable_period/__openerp__.py create mode 100644 membership_variable_period/data/membership_data.xml create mode 100644 membership_variable_period/i18n/de.po create mode 100644 membership_variable_period/i18n/es.po create mode 100644 membership_variable_period/i18n/membership_variable_period.pot create mode 100644 membership_variable_period/i18n/pt_BR.po create mode 100644 membership_variable_period/i18n/sl.po create mode 100644 membership_variable_period/models/__init__.py create mode 100644 membership_variable_period/models/account_invoice.py create mode 100644 membership_variable_period/models/product_template.py create mode 100644 membership_variable_period/models/res_partner.py create mode 100644 membership_variable_period/static/description/icon.png create mode 100644 membership_variable_period/static/description/icon.svg create mode 100644 membership_variable_period/static/description/icon_main.svg create mode 100644 membership_variable_period/tests/__init__.py create mode 100644 membership_variable_period/tests/test_membership_variable_period.py create mode 100644 membership_variable_period/views/product_template_views.xml create mode 100644 membership_variable_period/views/res_partner_views.xml diff --git a/membership_variable_period/README.rst b/membership_variable_period/README.rst new file mode 100644 index 0000000..a61b25d --- /dev/null +++ b/membership_variable_period/README.rst @@ -0,0 +1,72 @@ +=============================== +Variable period for memberships +=============================== + +Current membership module allows to set products that define a fixed period +for a membership. This is good when the quotas are defined periodically, and +when you become a member, you are until the end of that quota cycle. + +But a lot of times, membership quotas express an amount of time that you +gain the membership. For example, one year since the subscription. + + +This module allows to make it in Odoo, using current membership features, +and adapting them for this purpose. As now the quota is not attached to a fixed +period, you can also invoice more than one quantity for being a member for +the corresponding number of periods. + +Finally, a cron has been included that triggers the recalculation of the +membership state, allowing to have "old members", which doesn't work well +on standard. + +Usage +===== + +Define a member product, and select 'Variable periods' in the field +*Membership type*. You will be able to select them the period for the +membership in quantity and interval. + + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/208/8.0 + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed feedback +`here `_. + +Credits +======= + +Contributors +------------ + +* Pedro M. Baeza + +Icon +---- + +Original clipart from: + +* http://pixabay.com/es/en-contacto-con-tarjeta-de-cr%C3%A9dito-97574/ +* https://openclipart.org/detail/23920/sandglass + +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/membership_variable_period/__init__.py b/membership_variable_period/__init__.py new file mode 100644 index 0000000..9674e40 --- /dev/null +++ b/membership_variable_period/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Antiun Ingeniería S.L. - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import models diff --git a/membership_variable_period/__openerp__.py b/membership_variable_period/__openerp__.py new file mode 100644 index 0000000..561ca56 --- /dev/null +++ b/membership_variable_period/__openerp__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Antiun Ingeniería S.L. - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +{ + 'name': 'Variable period for memberships', + 'version': '8.0.1.0.0', + 'license': 'AGPL-3', + 'category': 'Association', + 'author': 'Antiun Ingeniería S.L., ' + 'Serv. Tecnol. Avanzados - Pedro M. Baeza, ' + 'Odoo Community Association (OCA)', + 'website': 'http://www.antiun.com', + 'depends': [ + 'membership', + ], + 'data': [ + 'views/product_template_views.xml', + 'views/res_partner_views.xml', + 'data/membership_data.xml', + ], + "installable": True, +} diff --git a/membership_variable_period/data/membership_data.xml b/membership_variable_period/data/membership_data.xml new file mode 100644 index 0000000..47ca1a9 --- /dev/null +++ b/membership_variable_period/data/membership_data.xml @@ -0,0 +1,18 @@ + + + + + + Check membership expiry + 1 + 10 + days + -1 + + + + + + + + diff --git a/membership_variable_period/i18n/de.po b/membership_variable_period/i18n/de.po new file mode 100644 index 0000000..2fb6537 --- /dev/null +++ b/membership_variable_period/i18n/de.po @@ -0,0 +1,107 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * membership_variable_period +# +# Translators: +# Rudolf Schnapka , 2016 +msgid "" +msgstr "" +"Project-Id-Version: vertical-association (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-01-19 12:02+0000\n" +"PO-Revision-Date: 2016-01-18 20:04+0000\n" +"Last-Translator: Rudolf Schnapka \n" +"Language-Team: German (http://www.transifex.com/oca/OCA-vertical-association-8-0/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: membership_variable_period +#: selection:product.template,membership_type:0 +msgid "Fixed dates" +msgstr "Feste Termine" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "Interval" +msgstr "Intervall" + +#. module: membership_variable_period +#: field:product.template,membership_interval_qty:0 +msgid "Interval quantity" +msgstr "Intervallanzahl" + +#. module: membership_variable_period +#: field:product.template,membership_interval_unit:0 +msgid "Interval unit" +msgstr "Intervalleinheit" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_account_invoice_line +msgid "Invoice Line" +msgstr "Rechnungsposition" + +#. module: membership_variable_period +#: field:account.invoice.line,membership_lines:0 +msgid "Membership lines" +msgstr "Mitgliedschafts-Positionen" + +#. module: membership_variable_period +#: field:product.template,membership_type:0 +msgid "Membership type" +msgstr "Art der Mitgliedschaft" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_res_partner +msgid "Partner" +msgstr "Partner" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_product_template +msgid "Product Template" +msgstr "Produktvorlage" + +#. module: membership_variable_period +#: selection:product.template,membership_type:0 +msgid "Variable periods" +msgstr "Variable Perioden" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "days" +msgstr "Tage" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "months" +msgstr "Monate" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "weeks" +msgstr "Wochen" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "years" +msgstr "Jahre" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "{'invisible': [('membership_type', '!=', 'fixed')]}" +msgstr "" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.product_template_form_view_membership_period +msgid "" +"{'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)]," +" 'invisible': [('membership_type', '!=', 'fixed')]}" +msgstr "" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "" +"{'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)]}" +msgstr "" diff --git a/membership_variable_period/i18n/es.po b/membership_variable_period/i18n/es.po new file mode 100644 index 0000000..3cea35b --- /dev/null +++ b/membership_variable_period/i18n/es.po @@ -0,0 +1,106 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * membership_variable_period +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: vertical-association (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-09-07 20:26+0000\n" +"PO-Revision-Date: 2015-09-07 20:27+0000\n" +"Last-Translator: OCA Transbot \n" +"Language-Team: Spanish (http://www.transifex.com/oca/OCA-vertical-association-8-0/language/es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: membership_variable_period +#: selection:product.template,membership_type:0 +msgid "Fixed dates" +msgstr "Fechas fijas" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "Interval" +msgstr "Intervalo" + +#. module: membership_variable_period +#: field:product.template,membership_interval_qty:0 +msgid "Interval quantity" +msgstr "Cantidad del intervalo" + +#. module: membership_variable_period +#: field:product.template,membership_interval_unit:0 +msgid "Interval unit" +msgstr "Unidad del intervalo" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_account_invoice_line +msgid "Invoice Line" +msgstr "Línea de factura" + +#. module: membership_variable_period +#: field:account.invoice.line,membership_lines:0 +msgid "Membership lines" +msgstr "Líneas de afiliación" + +#. module: membership_variable_period +#: field:product.template,membership_type:0 +msgid "Membership type" +msgstr "Tipo de afiliación" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_res_partner +msgid "Partner" +msgstr "" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_product_template +msgid "Product Template" +msgstr "Plantilla de producto" + +#. module: membership_variable_period +#: selection:product.template,membership_type:0 +msgid "Variable periods" +msgstr "Periodos variables" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "days" +msgstr "días" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "months" +msgstr "meses" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "weeks" +msgstr "semanas" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "years" +msgstr "años" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "{'invisible': [('membership_type', '!=', 'fixed')]}" +msgstr "" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.product_template_form_view_membership_period +msgid "" +"{'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)]," +" 'invisible': [('membership_type', '!=', 'fixed')]}" +msgstr "" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "" +"{'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)]}" +msgstr "" diff --git a/membership_variable_period/i18n/membership_variable_period.pot b/membership_variable_period/i18n/membership_variable_period.pot new file mode 100644 index 0000000..9e4e1bd --- /dev/null +++ b/membership_variable_period/i18n/membership_variable_period.pot @@ -0,0 +1,97 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * membership_variable_period +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-21 00:25+0000\n" +"PO-Revision-Date: 2015-08-21 00:25+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: membership_variable_period +#: selection:product.template,membership_type:0 +msgid "Fixed dates" +msgstr "" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "Interval" +msgstr "" + +#. module: membership_variable_period +#: field:product.template,membership_interval_qty:0 +msgid "Interval quantity" +msgstr "" + +#. module: membership_variable_period +#: field:product.template,membership_interval_unit:0 +msgid "Interval unit" +msgstr "" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_account_invoice_line +msgid "Invoice Line" +msgstr "" + +#. module: membership_variable_period +#: field:account.invoice.line,membership_lines:0 +msgid "Membership lines" +msgstr "" + +#. module: membership_variable_period +#: field:product.template,membership_type:0 +msgid "Membership type" +msgstr "" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_res_partner +msgid "Partner" +msgstr "" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_product_template +msgid "Product Template" +msgstr "" + +#. module: membership_variable_period +#: selection:product.template,membership_type:0 +msgid "Variable periods" +msgstr "" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "days" +msgstr "" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "months" +msgstr "" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "weeks" +msgstr "" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "years" +msgstr "" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "{'invisible': [('membership_type', '!=', 'fixed')]}" +msgstr "" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "{'required': [('membership_type', '=', 'fixed')]}" +msgstr "" + diff --git a/membership_variable_period/i18n/pt_BR.po b/membership_variable_period/i18n/pt_BR.po new file mode 100644 index 0000000..36c58d7 --- /dev/null +++ b/membership_variable_period/i18n/pt_BR.po @@ -0,0 +1,106 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * membership_variable_period +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: vertical-association (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-14 07:14+0000\n" +"PO-Revision-Date: 2015-09-07 20:26+0000\n" +"Last-Translator: <>\n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/oca/OCA-vertical-association-8-0/language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: membership_variable_period +#: selection:product.template,membership_type:0 +msgid "Fixed dates" +msgstr "" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "Interval" +msgstr "" + +#. module: membership_variable_period +#: field:product.template,membership_interval_qty:0 +msgid "Interval quantity" +msgstr "" + +#. module: membership_variable_period +#: field:product.template,membership_interval_unit:0 +msgid "Interval unit" +msgstr "" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_account_invoice_line +msgid "Invoice Line" +msgstr "Linha de faturamento" + +#. module: membership_variable_period +#: field:account.invoice.line,membership_lines:0 +msgid "Membership lines" +msgstr "" + +#. module: membership_variable_period +#: field:product.template,membership_type:0 +msgid "Membership type" +msgstr "" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_res_partner +msgid "Partner" +msgstr "" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_product_template +msgid "Product Template" +msgstr "Modelo do Produto" + +#. module: membership_variable_period +#: selection:product.template,membership_type:0 +msgid "Variable periods" +msgstr "" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "days" +msgstr "" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "months" +msgstr "" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "weeks" +msgstr "" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "years" +msgstr "" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "{'invisible': [('membership_type', '!=', 'fixed')]}" +msgstr "" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.product_template_form_view_membership_period +msgid "" +"{'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)]," +" 'invisible': [('membership_type', '!=', 'fixed')]}" +msgstr "" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "" +"{'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)]}" +msgstr "" diff --git a/membership_variable_period/i18n/sl.po b/membership_variable_period/i18n/sl.po new file mode 100644 index 0000000..a44848b --- /dev/null +++ b/membership_variable_period/i18n/sl.po @@ -0,0 +1,107 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * membership_variable_period +# +# Translators: +# Matjaž Mozetič , 2015 +msgid "" +msgstr "" +"Project-Id-Version: vertical-association (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-09-23 19:13+0000\n" +"PO-Revision-Date: 2015-09-20 19:07+0000\n" +"Last-Translator: Matjaž Mozetič \n" +"Language-Team: Slovenian (http://www.transifex.com/oca/OCA-vertical-association-8-0/language/sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" + +#. module: membership_variable_period +#: selection:product.template,membership_type:0 +msgid "Fixed dates" +msgstr "Fiksni datumi" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "Interval" +msgstr "Interval" + +#. module: membership_variable_period +#: field:product.template,membership_interval_qty:0 +msgid "Interval quantity" +msgstr "Količina intervala" + +#. module: membership_variable_period +#: field:product.template,membership_interval_unit:0 +msgid "Interval unit" +msgstr "Enota intervala" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_account_invoice_line +msgid "Invoice Line" +msgstr "Postavka računa" + +#. module: membership_variable_period +#: field:account.invoice.line,membership_lines:0 +msgid "Membership lines" +msgstr "Postavke članarin" + +#. module: membership_variable_period +#: field:product.template,membership_type:0 +msgid "Membership type" +msgstr "Tip članarine" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_res_partner +msgid "Partner" +msgstr "Partner" + +#. module: membership_variable_period +#: model:ir.model,name:membership_variable_period.model_product_template +msgid "Product Template" +msgstr "Predloga proizvoda" + +#. module: membership_variable_period +#: selection:product.template,membership_type:0 +msgid "Variable periods" +msgstr "Variabilna obdobja" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "days" +msgstr "dni" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "months" +msgstr "mesecev" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "weeks" +msgstr "tednov" + +#. module: membership_variable_period +#: selection:product.template,membership_interval_unit:0 +msgid "years" +msgstr "let" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "{'invisible': [('membership_type', '!=', 'fixed')]}" +msgstr "{'invisible': [('membership_type', '!=', 'fixed')]}" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.product_template_form_view_membership_period +msgid "" +"{'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)]," +" 'invisible': [('membership_type', '!=', 'fixed')]}" +msgstr "{'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)], 'invisible': [('membership_type', '!=', 'fixed')]}" + +#. module: membership_variable_period +#: view:product.template:membership_variable_period.membership_products_form_period +msgid "" +"{'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)]}" +msgstr "{'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)]}" diff --git a/membership_variable_period/models/__init__.py b/membership_variable_period/models/__init__.py new file mode 100644 index 0000000..d92d15d --- /dev/null +++ b/membership_variable_period/models/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Antiun Ingeniería S.L. - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from . import product_template +from . import account_invoice +from . import res_partner diff --git a/membership_variable_period/models/account_invoice.py b/membership_variable_period/models/account_invoice.py new file mode 100644 index 0000000..88186cc --- /dev/null +++ b/membership_variable_period/models/account_invoice.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Antiun Ingeniería S.L. - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from openerp import models, api, fields +from datetime import timedelta +import math + + +class AccountInvoiceLine(models.Model): + _inherit = "account.invoice.line" + + membership_lines = fields.One2many( + comodel_name='membership.membership_line', + inverse_name='account_invoice_line') + + def _prepare_membership_line(self, invoice, product, price_unit, line_id): + memb_line_model = self.env['membership.membership_line'] + memb_lines = memb_line_model.search( + [('partner', '=', invoice.partner_id.id), + ('state', 'not in', ['none', 'canceled'])], + order="date_to desc") + if memb_lines and memb_lines[0].date_to: + date_from = (fields.Date.from_string(memb_lines[0].date_to) + + timedelta(days=1)) + else: + date_from = fields.Date.from_string( + invoice.date_invoice or fields.Date.today()) + date_to = (product.product_tmpl_id._get_next_date(date_from) - + timedelta(days=1)) + return { + 'partner': invoice.partner_id.id, + 'membership_id': product.id, + 'member_price': price_unit, + 'date': fields.Date.today(), + 'date_from': fields.Date.to_string(date_from), + 'date_to': fields.Date.to_string(date_to), + 'state': 'waiting', + 'account_invoice_line': line_id, + } + + @api.multi + def write(self, vals): + """Create before the lines of membership with variable period.""" + memb_line_model = self.env['membership.membership_line'] + if any(x in vals for x in ['product_id', 'quantity', 'invoice_id']): + for line in self: + product = ( + self.env['product.product'].browse(vals['product_id']) if + vals.get('product_id') else line.product_id) + invoice = ( + self.env['account.invoice'].browse(vals['invoice_id']) if + vals.get('invoice_id') else line.invoice_id) + if (invoice.type == 'out_invoice' and + product.membership and + product.membership_type == 'variable'): + quantity = vals.get('quantity', line.quantity) + memb_lines = memb_line_model.search( + [('account_invoice_line', '=', line.id), + ('state', 'not in', ['none', 'canceled'])], + order="date desc, id desc") + price_unit = vals.get('price_unit', line.price_unit) + membership_vals = self._prepare_membership_line( + invoice, product, price_unit, line.id) + if len(memb_lines) < quantity: + # Add missing membership lines + missing_number = quantity - len(memb_lines) + for i in range(int(missing_number)): + memb_line_model.create(membership_vals) + elif len(memb_lines) > quantity: + # Remove extra membership lines + extra_number = ( + len(memb_lines) - int(math.ceil(quantity))) + memb_lines[:extra_number].unlink() + else: + # Update data of current membership line + memb_lines[0].write(membership_vals) + return super(AccountInvoiceLine, self).write(vals) + + @api.model + def create(self, vals): + price_unit = vals.get('price_unit', 0.0) + line = super(AccountInvoiceLine, self).create(vals) + if (line.invoice_id.type == 'out_invoice' and + line.product_id.membership and + line.product_id.membership_type == 'variable'): + for i in range(int(line.quantity)): + membership_vals = self._prepare_membership_line( + line.invoice_id, line.product_id, price_unit, line.id) + # There's already the super line + line.membership_lines[0].write(membership_vals) + return line diff --git a/membership_variable_period/models/product_template.py b/membership_variable_period/models/product_template.py new file mode 100644 index 0000000..8840a6e --- /dev/null +++ b/membership_variable_period/models/product_template.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Antiun Ingeniería S.L. - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from openerp import models, fields, api +from datetime import timedelta +from dateutil.relativedelta import relativedelta + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + @api.multi + def _get_next_date(self, date): + """Get the date that results on incrementing given date an interval of + time in time unit. + @param date: Original date. + @param unit: Interval time unit. + @param interval: Quantity of the time unit. + @rtype: date + @return: The date incremented in 'interval' units of 'unit'. + """ + self.ensure_one() + if isinstance(date, str): + date = fields.Date.from_string(date) + if self.membership_interval_unit == 'days': + return date + timedelta(days=self.membership_interval_qty) + elif self.membership_interval_unit == 'weeks': + return date + timedelta(weeks=self.membership_interval_qty) + elif self.membership_interval_unit == 'months': + return date + relativedelta(months=self.membership_interval_qty) + elif self.membership_interval_unit == 'years': + return date + relativedelta(years=self.membership_interval_qty) + + membership_type = fields.Selection( + selection=[('fixed', 'Fixed dates'), + ('variable', 'Variable periods')], + default='fixed', string="Membership type", required=True) + membership_interval_qty = fields.Integer( + string="Interval quantity", default=1) + membership_interval_unit = fields.Selection( + selection=[('days', 'days'), + ('weeks', 'weeks'), + ('months', 'months'), + ('years', 'years')], + string="Interval unit", default='years') + + def _correct_vals_membership_type(self, vals, membership_type): + if membership_type == 'variable': + vals['membership_date_from'] = False + vals['membership_date_to'] = False + return vals + + @api.model + def create(self, vals): + self._correct_vals_membership_type( + vals, vals.get('membership_type', 'fixed')) + return super(ProductTemplate, self).create(vals) + + @api.multi + def write(self, vals): + self._correct_vals_membership_type( + vals, vals.get('membership_type', self.membership_type)) + return super(ProductTemplate, self).write(vals) diff --git a/membership_variable_period/models/res_partner.py b/membership_variable_period/models/res_partner.py new file mode 100644 index 0000000..5e757e4 --- /dev/null +++ b/membership_variable_period/models/res_partner.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Antiun Ingeniería S.L. - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from openerp import models, api + + +class ResPartner(models.Model): + _inherit = "res.partner" + + @api.model + def check_membership_expiry(self): + """Force a recalculation on each partner that is member.""" + partners = self.search( + [('membership_state', 'not in', ['old', 'none', 'free']), + ('associate_member', '=', False)]) + # It has to be triggered one by one to avoid an error + for partner in partners: + partner.write({'membership_state': 'none'}) + return True diff --git a/membership_variable_period/static/description/icon.png b/membership_variable_period/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6c6662f1522dc0aca1c2b6dfa44f7a64bbbe55ca GIT binary patch literal 7979 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 literal 0 HcmV?d00001 diff --git a/membership_variable_period/static/description/icon.svg b/membership_variable_period/static/description/icon.svg new file mode 100644 index 0000000..6fb22c9 --- /dev/null +++ b/membership_variable_period/static/description/icon.svg @@ -0,0 +1,455 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/membership_variable_period/static/description/icon_main.svg b/membership_variable_period/static/description/icon_main.svg new file mode 100644 index 0000000..c7f5f0a --- /dev/null +++ b/membership_variable_period/static/description/icon_main.svg @@ -0,0 +1,735 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/membership_variable_period/tests/__init__.py b/membership_variable_period/tests/__init__.py new file mode 100644 index 0000000..4a1e59e --- /dev/null +++ b/membership_variable_period/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Antiun Ingeniería S.L. - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from . import test_membership_variable_period diff --git a/membership_variable_period/tests/test_membership_variable_period.py b/membership_variable_period/tests/test_membership_variable_period.py new file mode 100644 index 0000000..691603c --- /dev/null +++ b/membership_variable_period/tests/test_membership_variable_period.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# (c) 2015 Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +import openerp.tests.common as common +from datetime import date + + +class TestMembershipVariablePeriod(common.TransactionCase): + + def setUp(self): + super(TestMembershipVariablePeriod, self).setUp() + self.product = self.env['product.product'].create( + { + 'name': 'Membership product with variable period', + 'membership': True, + 'membership_date_from': '2015-01-01', + 'membership_date_to': '2015-12-31', + 'membership_type': 'variable', + 'membership_interval_qty': 1, + 'membership_interval_unit': 'weeks', + }) + self.partner = self.env['res.partner'].create({'name': 'Test'}) + + def test_create_invoice_membership_product_days(self): + self.product.membership_interval_qty = 20 + self.product.membership_interval_unit = 'days' + invoice = self.env['account.invoice'].create( + {'partner_id': self.partner.id, + 'date_invoice': '2015-07-01', + 'account_id': self.partner.property_account_receivable.id, + 'invoice_line': [(0, 0, {'product_id': self.product.id, + 'name': 'Membership w/o prorrate'})]} + ) + membership_line = invoice.invoice_line[0].membership_lines[0] + self.assertEqual(membership_line.date_from, '2015-07-01') + self.assertEqual(membership_line.date_to, '2015-07-20') + self.assertEqual(self.partner.membership_start, '2015-07-01') + self.assertEqual(self.partner.membership_stop, '2015-07-20') + + def test_create_invoice_membership_product_week(self): + invoice = self.env['account.invoice'].create( + {'partner_id': self.partner.id, + 'date_invoice': '2015-07-01', + 'account_id': self.partner.property_account_receivable.id, + 'invoice_line': [(0, 0, {'product_id': self.product.id, + 'name': 'Membership w/o prorrate'})]} + ) + membership_line = invoice.invoice_line[0].membership_lines[0] + self.assertEqual(membership_line.date_from, '2015-07-01') + self.assertEqual(membership_line.date_to, '2015-07-07') + self.assertEqual(self.partner.membership_start, '2015-07-01') + self.assertEqual(self.partner.membership_stop, '2015-07-07') + + def test_create_invoice_membership_product_month(self): + self.product.membership_interval_unit = 'months' + invoice = self.env['account.invoice'].create( + {'partner_id': self.partner.id, + 'date_invoice': '2015-04-15', + 'account_id': self.partner.property_account_receivable.id, + 'invoice_line': [(0, 0, {'product_id': self.product.id, + 'name': 'Membership with prorrate'})]} + ) + membership_line = invoice.invoice_line[0].membership_lines[0] + self.assertEqual(membership_line.date_from, '2015-04-15') + self.assertEqual(membership_line.date_to, '2015-05-14') + self.assertEqual(self.partner.membership_start, '2015-04-15') + self.assertEqual(self.partner.membership_stop, '2015-05-14') + + def test_create_invoice_membership_product_year(self): + self.product.membership_interval_unit = 'years' + invoice = self.env['account.invoice'].create( + {'partner_id': self.partner.id, + 'date_invoice': '2016-07-01', # It's leap year + 'account_id': self.partner.property_account_receivable.id, + 'invoice_line': [(0, 0, {'product_id': self.product.id, + 'name': 'Membership with prorrate'})]} + ) + membership_line = invoice.invoice_line[0].membership_lines[0] + self.assertEqual(membership_line.date_from, '2016-07-01') + self.assertEqual(membership_line.date_to, '2017-06-30') + self.assertEqual(self.partner.membership_start, '2016-07-01') + self.assertEqual(self.partner.membership_stop, '2017-06-30') + + def test_modify_invoice_membership_product(self): + self.product.membership_interval_unit = 'years' + invoice = self.env['account.invoice'].create( + {'partner_id': self.partner.id, + 'date_invoice': '2015-07-01', + 'account_id': self.partner.property_account_receivable.id, + 'invoice_line': [(0, 0, {'product_id': self.product.id, + 'name': 'Membership w/o prorrate'})]} + ) + # Add quantity + invoice.invoice_line[0].quantity = 2.0 + membership_lines = invoice.invoice_line[0].membership_lines + self.assertEqual(len(membership_lines), 2) + self.assertEqual(membership_lines[1].date_from, '2015-07-01') + self.assertEqual(membership_lines[1].date_to, '2016-06-30') + self.assertEqual(membership_lines[0].date_from, '2016-07-01') + self.assertEqual(membership_lines[0].date_to, '2017-06-30') + self.assertEqual(self.partner.membership_start, '2015-07-01') + self.assertEqual(self.partner.membership_stop, '2017-06-30') + # Remove quantity + invoice.invoice_line[0].quantity = 1.0 + membership_lines = invoice.invoice_line[0].membership_lines + self.assertEqual(len(membership_lines), 1) + self.assertEqual(membership_lines[0].date_from, '2015-07-01') + self.assertEqual(membership_lines[0].date_to, '2016-06-30') + + def test_create_and_modify_invoice_line_membership_product(self): + self.product.membership_interval_qty = 20 + self.product.membership_interval_unit = 'days' + invoice_line = self.env['account.invoice.line'].create( + {'product_id': self.product.id, + 'name': 'Membership w/o prorrate'}) + invoice = self.env['account.invoice'].create( + {'partner_id': self.partner.id, + 'date_invoice': '2015-07-01', + 'account_id': self.partner.property_account_receivable.id}) + invoice_line.invoice_id = invoice.id + membership_line = invoice.invoice_line[0].membership_lines[0] + self.assertEqual(membership_line.date_from, '2015-07-01') + self.assertEqual(membership_line.date_to, '2015-07-20') + self.assertEqual(self.partner.membership_start, '2015-07-01') + self.assertEqual(self.partner.membership_stop, '2015-07-20') + + def test_check_membership_expiry(self): + self.env['membership.membership_line'].create( + {'partner': self.partner.id, + 'membership_id': self.product.id, + 'member_price': 1.0, + 'date': '2014-01-01', + 'date_from': '2014-01-01', + 'date_to': '2014-12-31', + 'state': 'paid', + 'account_invoice_line': self.env['account.invoice.line'].search( + [], limit=1).id}) + # Force state to let the calculation return to the computed one + self.partner.membership_stop = '2014-12-31' + self.env['res.partner'].check_membership_expiry() + self.assertEqual(self.partner.membership_state, 'none') + + def test_get_next_date(self): + test_suite = [ + # Add here more border cases that can be detected in the future + ('2015-01-01', "days", 25, date(day=26, month=1, year=2015)), + ('2015-01-01', "weeks", 1, date(day=8, month=1, year=2015)), + ('2015-01-01', "months", 3, date(day=1, month=4, year=2015)), + ('2015-01-01', "years", 1, date(day=1, month=1, year=2016)), + ] + template_model = self.env['product.template'] + for old_date, interval, qty, next_date in test_suite: + template = template_model.new() + template.membership_interval_unit = interval + template.membership_interval_qty = qty + self.assertEqual(template._get_next_date(old_date), next_date) diff --git a/membership_variable_period/views/product_template_views.xml b/membership_variable_period/views/product_template_views.xml new file mode 100644 index 0000000..cb15846 --- /dev/null +++ b/membership_variable_period/views/product_template_views.xml @@ -0,0 +1,74 @@ + + + + + + Membership Products (variable period) + product.template + + + + + + Membership Products (regular - variable period) + product.template + + + + + + + + + {'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)], 'invisible': [('membership_type', '!=', 'fixed')]} + 0 + + + {'required': [('membership_type', '=', 'fixed'), ('membership', '=', True)], 'invisible': [('membership_type', '!=', 'fixed')]} + 0 + + + + + + diff --git a/membership_variable_period/views/res_partner_views.xml b/membership_variable_period/views/res_partner_views.xml new file mode 100644 index 0000000..67b0bc2 --- /dev/null +++ b/membership_variable_period/views/res_partner_views.xml @@ -0,0 +1,17 @@ + + + + + + res.partner.form.membership.period + res.partner + + + + + + + + + + -- GitLab