From e00021e4e3d7d20baf274e84c348a2e1e4b48055 Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Tue, 2 Jun 2020 18:03:20 +0200 Subject: [PATCH 01/10] [REF] emca: api returns share product template --- .../services/subscription_request_service.py | 31 ++++++++++++++++--- easy_my_coop_api/tests/common.py | 4 ++- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/easy_my_coop_api/services/subscription_request_service.py b/easy_my_coop_api/services/subscription_request_service.py index a64de5d..4013739 100644 --- a/easy_my_coop_api/services/subscription_request_service.py +++ b/easy_my_coop_api/services/subscription_request_service.py @@ -81,8 +81,8 @@ class SubscriptionRequestService(Component): "date": Date.to_string(sr.date), "ordered_parts": sr.ordered_parts, "share_product": { - "id": sr.share_product_id.id, - "name": sr.share_product_id.name, + "id": sr.share_product_id.product_tmpl_id.id, + "name": sr.share_product_id.product_tmpl_id.name, }, "address": { "street": sr.address, @@ -102,15 +102,29 @@ class SubscriptionRequestService(Component): BadRequest(_("No country for isocode %s") % code) ) + def _get_share_product(self, template_id): + product = self.env["product.product"].search( + [("product_tmpl_id", "=", template_id)] + ) + if product: + return product + else: + raise wrapJsonException( + BadRequest(_("No share for id %s") % template_id) + ) + def _prepare_create(self, params): + """Prepare a writable dictionary of values""" address = params["address"] country = self._get_country(address["country"]) + share_product_id = self._get_share_product(params["share_product"]) + return { "name": params["name"], "email": params["email"], "ordered_parts": params["ordered_parts"], - "share_product_id": params["share_product"], + "share_product_id": share_product_id.id, "address": address["street"], "zip_code": address["zip_code"], "city": address["city"], @@ -123,16 +137,23 @@ class SubscriptionRequestService(Component): address = params["address"] if "country" in address: country = self._get_country(address["country"]).id - address["country"] = country + address["country"] = country.id else: address = {} + if "share_product" in params: + share_product_id = self._get_share_product( + params["share_product"] + ).id + else: + share_product_id = None + params = { "name": params.get("name"), "email": params.get("email"), "state": params.get("state"), "ordered_parts": params.get("ordered_parts"), - "share_product_id": params.get("share_product"), + "share_product_id": share_product_id, "address": address.get("street"), "zip_code": address.get("zip_code"), "city": address.get("city"), diff --git a/easy_my_coop_api/tests/common.py b/easy_my_coop_api/tests/common.py index 1e15a7f..b44d54d 100644 --- a/easy_my_coop_api/tests/common.py +++ b/easy_my_coop_api/tests/common.py @@ -42,7 +42,9 @@ class BaseEMCRestCase(BaseRestCase): self.demo_request_1 = self.browse_ref( "easy_my_coop.subscription_request_1_demo" ) - self.demo_share_product = self.demo_request_1.share_product_id + self.demo_share_product = ( + self.demo_request_1.share_product_id.product_tmpl_id + ) date = Date.to_string(self.demo_request_1.date) self.demo_request_1_dict = { From b9b9d16745c1b14f49f65b19d0ce36e919dc991c Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Tue, 2 Jun 2020 18:03:56 +0200 Subject: [PATCH 02/10] [IMP] emca: generate and export external id [ADD] emca: external_id on invoice --- easy_my_coop_api/__manifest__.py | 4 ++-- easy_my_coop_api/data/sequences.xml | 19 +++++++++++++++ easy_my_coop_api/demo/demo.xml | 10 ++++++++ easy_my_coop_api/models/__init__.py | 2 ++ easy_my_coop_api/models/account_invoice.py | 22 +++++++++++++++++ .../models/subscription_request.py | 24 +++++++++++++++++++ .../services/subscription_request_service.py | 11 ++++++--- 7 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 easy_my_coop_api/data/sequences.xml create mode 100644 easy_my_coop_api/demo/demo.xml create mode 100644 easy_my_coop_api/models/account_invoice.py create mode 100644 easy_my_coop_api/models/subscription_request.py diff --git a/easy_my_coop_api/__manifest__.py b/easy_my_coop_api/__manifest__.py index f42c066..a7f8cd9 100644 --- a/easy_my_coop_api/__manifest__.py +++ b/easy_my_coop_api/__manifest__.py @@ -17,8 +17,8 @@ "summary": """ Open Easy My Coop to the world: RESTful API. """, - "data": [], - "demo": [], + "data": ["data/sequences.xml"], + "demo": ["demo/demo.xml"], "installable": True, "application": False, } diff --git a/easy_my_coop_api/data/sequences.xml b/easy_my_coop_api/data/sequences.xml new file mode 100644 index 0000000..4d03a8a --- /dev/null +++ b/easy_my_coop_api/data/sequences.xml @@ -0,0 +1,19 @@ + + + + + + Subscritpion Request External ID sequence + subscription.request.external.id + 3 + + + Subscritpion Request External ID sequence + account.invoice.external.id + 3 + + + diff --git a/easy_my_coop_api/demo/demo.xml b/easy_my_coop_api/demo/demo.xml new file mode 100644 index 0000000..a88981a --- /dev/null +++ b/easy_my_coop_api/demo/demo.xml @@ -0,0 +1,10 @@ + + + + + 1 + + diff --git a/easy_my_coop_api/models/__init__.py b/easy_my_coop_api/models/__init__.py index 6dfe3f7..b951867 100644 --- a/easy_my_coop_api/models/__init__.py +++ b/easy_my_coop_api/models/__init__.py @@ -1 +1,3 @@ from . import auth_api_key +from . import subscription_request +from . import account_invoice diff --git a/easy_my_coop_api/models/account_invoice.py b/easy_my_coop_api/models/account_invoice.py new file mode 100644 index 0000000..ae3c520 --- /dev/null +++ b/easy_my_coop_api/models/account_invoice.py @@ -0,0 +1,22 @@ +# Copyright 2020 Coop IT Easy SCRL fs +# Robin Keunen +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class AccountInvoice(models.Model): + _inherit = "account.invoice" + + external_id = fields.Integer( + string="External ID", index=True, required=False + ) + + @api.multi + def get_external_id(self): + self.ensure_one() + if not self.external_id: + self.external_id = self.env["ir.sequence"].next_by_code( + "account.invoice.external.id" + ) + return self.external_id diff --git a/easy_my_coop_api/models/subscription_request.py b/easy_my_coop_api/models/subscription_request.py new file mode 100644 index 0000000..717c072 --- /dev/null +++ b/easy_my_coop_api/models/subscription_request.py @@ -0,0 +1,24 @@ +# Copyright 2020 Coop IT Easy SCRL fs +# Robin Keunen +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from os.path import join + +from odoo import api, fields, models + + +class SubscriptionRequest(models.Model): + _inherit = "subscription.request" + + external_id = fields.Integer( + string="External ID", index=True, required=False + ) + + @api.multi + def get_external_id(self): + self.ensure_one() + if not self.external_id: + self.external_id = self.env["ir.sequence"].next_by_code( + "subscription.request.external.id" + ) + return self.external_id diff --git a/easy_my_coop_api/services/subscription_request_service.py b/easy_my_coop_api/services/subscription_request_service.py index 4013739..b120a82 100644 --- a/easy_my_coop_api/services/subscription_request_service.py +++ b/easy_my_coop_api/services/subscription_request_service.py @@ -28,7 +28,9 @@ class SubscriptionRequestService(Component): """ def get(self, _id): - sr = self.env["subscription.request"].browse(_id) + sr = self.env["subscription.request"].search( + [("external_id", "=", _id)] + ) if sr: return self._to_dict(sr) else: @@ -63,7 +65,9 @@ class SubscriptionRequestService(Component): def update(self, _id, **params): params = self._prepare_update(params) - sr = self.env["subscription.request"].browse(_id) + sr = self.env["subscription.request"].search( + [("external_id", "=", _id)] + ) if not sr: raise wrapJsonException( NotFound(_("No subscription request for id %s") % _id) @@ -73,8 +77,9 @@ class SubscriptionRequestService(Component): def _to_dict(self, sr): sr.ensure_one() + return { - "id": sr.id, + "id": sr.get_external_id(), "name": sr.name, "email": sr.email, "state": sr.state, From b0c06835ea4dd5d649fdcbee28d828e563872906 Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Thu, 4 Jun 2020 17:41:41 +0200 Subject: [PATCH 03/10] [ADD] emca: subscription-request/id_/validate route --- easy_my_coop/demo/coop.xml | 42 ++++++++++++++++++- easy_my_coop_api/demo/demo.xml | 8 ++++ .../services/account_invoice_service.py | 0 easy_my_coop_api/services/schemas.py | 8 ++++ .../services/subscription_request_service.py | 32 ++++++++++++++ easy_my_coop_api/tests/common.py | 30 ++++++------- .../tests/test_subscription_requests.py | 38 ++++++++++++++--- 7 files changed, 137 insertions(+), 21 deletions(-) create mode 100644 easy_my_coop_api/services/account_invoice_service.py diff --git a/easy_my_coop/demo/coop.xml b/easy_my_coop/demo/coop.xml index 6538115..c8cce44 100644 --- a/easy_my_coop/demo/coop.xml +++ b/easy_my_coop/demo/coop.xml @@ -76,8 +76,16 @@ + + 100910 + Variable Capital + + + + - + @@ -127,6 +135,38 @@ + + + Catherine des Champs + catherine@demo.net + Chemin des bois fleuris + 1000 + Brussels + + + manual + 4 + + en_US + + waiting + + + + Catherine des Champs + + + catherine@demo.net + Chemin des bois fleuris, 2 + Brussels + 1000 + + + + + + diff --git a/easy_my_coop_api/demo/demo.xml b/easy_my_coop_api/demo/demo.xml index a88981a..4caccc9 100644 --- a/easy_my_coop_api/demo/demo.xml +++ b/easy_my_coop_api/demo/demo.xml @@ -4,7 +4,15 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> + + + cbd07f57-c903-43b4-b668-436b3bec5f15 + + 1 + + 2 + diff --git a/easy_my_coop_api/services/account_invoice_service.py b/easy_my_coop_api/services/account_invoice_service.py new file mode 100644 index 0000000..e69de29 diff --git a/easy_my_coop_api/services/schemas.py b/easy_my_coop_api/services/schemas.py index f20dab7..2b374f4 100644 --- a/easy_my_coop_api/services/schemas.py +++ b/easy_my_coop_api/services/schemas.py @@ -41,6 +41,12 @@ S_SUBSCRIPTION_REQUEST_RETURN_GET = { }, }, "lang": {"type": "string", "required": True, "empty": False}, + "capital_release_request": { + "type": "list", + "schema": {"type": "integer"}, + "required": True, + "empty": True, + }, } S_SUBSCRIPTION_REQUEST_SEARCH = { @@ -93,3 +99,5 @@ S_SUBSCRIPTION_REQUEST_UPDATE = { "lang": {"type": "string"}, "share_product": {"type": "integer"}, } + +S_SUBSCRIPTION_REQUEST_VALIDATE = {"_id": {"type": "integer"}} diff --git a/easy_my_coop_api/services/subscription_request_service.py b/easy_my_coop_api/services/subscription_request_service.py index b120a82..c962690 100644 --- a/easy_my_coop_api/services/subscription_request_service.py +++ b/easy_my_coop_api/services/subscription_request_service.py @@ -75,9 +75,34 @@ class SubscriptionRequestService(Component): sr.write(params) return self._to_dict(sr) + def validate(self, _id, **params): + sr = self.env["subscription.request"].search( + [("external_id", "=", _id)] + ) + if not sr: + raise wrapJsonException( + NotFound(_("No subscription request for id %s") % _id) + ) + if sr.state != "draft": + raise wrapJsonException( + BadRequest( + _("Subscription request %s is not in draft state") % _id + ) + ) + sr.validate_subscription_request() + return self._to_dict(sr) + def _to_dict(self, sr): sr.ensure_one() + if sr.capital_release_request: + invoice_ids = [ + invoice.get_external_id() + for invoice in sr.capital_release_request + ] + else: + invoice_ids = [] + return { "id": sr.get_external_id(), "name": sr.name, @@ -96,6 +121,7 @@ class SubscriptionRequestService(Component): "country": sr.country_id.code, }, "lang": sr.lang, + "capital_release_request": invoice_ids, } def _get_country(self, code): @@ -191,3 +217,9 @@ class SubscriptionRequestService(Component): def _validator_return_update(self): return schemas.S_SUBSCRIPTION_REQUEST_RETURN_GET + + def _validator_validate(self): + return schemas.S_SUBSCRIPTION_REQUEST_VALIDATE + + def _validator_return_validate(self): + return schemas.S_SUBSCRIPTION_REQUEST_RETURN_GET diff --git a/easy_my_coop_api/tests/common.py b/easy_my_coop_api/tests/common.py index b44d54d..5c91962 100644 --- a/easy_my_coop_api/tests/common.py +++ b/easy_my_coop_api/tests/common.py @@ -17,31 +17,32 @@ HOST = "127.0.0.1" PORT = odoo.tools.config["http_port"] -def _add_api_key(headers): - key_dict = {"API-KEY": "api-key"} - if headers: - headers.update(key_dict) - else: - headers = key_dict - return headers - - class BaseEMCRestCase(BaseRestCase): @classmethod def setUpClass(cls, *args, **kwargs): super().setUpClass(*args, **kwargs) cls.AuthApiKey = cls.env["auth.api.key"] - emc_manager = cls.env.ref("easy_my_coop.res_users_manager_emc_demo") - cls.api_key_test = cls.AuthApiKey.create( - {"name": "test-key", "key": "api-key", "user_id": emc_manager.id} + cls.api_key_test = cls.env.ref( + "easy_my_coop_api.auth_api_key_manager_emc_demo" ) + def _add_api_key(self, headers): + key_dict = {"API-KEY": self.api_key_test.key} + if headers: + headers.update(key_dict) + else: + headers = key_dict + return headers + def setUp(self): super().setUp() self.session = requests.Session() self.demo_request_1 = self.browse_ref( "easy_my_coop.subscription_request_1_demo" ) + self.demo_request_2 = self.browse_ref( + "easy_my_coop.subscription_request_2_demo" + ) self.demo_share_product = ( self.demo_request_1.share_product_id.product_tmpl_id ) @@ -65,10 +66,11 @@ class BaseEMCRestCase(BaseRestCase): "country": "BE", }, "lang": "en_US", + "capital_release_request": [], } def http_get(self, url, headers=None): - headers = _add_api_key(headers) + headers = self._add_api_key(headers) if url.startswith("/"): url = "http://{}:{}{}".format(HOST, PORT, url) @@ -81,7 +83,7 @@ class BaseEMCRestCase(BaseRestCase): return json.loads(content) def http_post(self, url, data, headers=None): - headers = _add_api_key(headers) + headers = self._add_api_key(headers) if url.startswith("/"): url = "http://{}:{}{}".format(HOST, PORT, url) diff --git a/easy_my_coop_api/tests/test_subscription_requests.py b/easy_my_coop_api/tests/test_subscription_requests.py index 405205b..36764da 100644 --- a/easy_my_coop_api/tests/test_subscription_requests.py +++ b/easy_my_coop_api/tests/test_subscription_requests.py @@ -5,6 +5,8 @@ import json from datetime import timedelta +from werkzeug.exceptions import BadRequest + import odoo from odoo.fields import Date @@ -22,27 +24,29 @@ class TestSRController(BaseEMCRestCase): model_name="rest.service.registration", collection=collection ) - self.service = emc_services_env.component(usage="subscription-request") + self.sr_service = emc_services_env.component( + usage="subscription-request" + ) def test_service(self): # kept as example # useful if you need to change data in database and check db type - result = self.service.get(self.demo_request_1.id) + result = self.sr_service.get(self.demo_request_1.external_id) self.assertEquals(self.demo_request_1_dict, result) - all_sr = self.service.search() + all_sr = self.sr_service.search() self.assertTrue(all_sr) sr_date = self.demo_request_1.date date_from = Date.to_string(sr_date - timedelta(days=1)) date_to = Date.to_string(sr_date + timedelta(days=1)) - date_sr = self.service.search(date_from=date_from, date_to=date_to) + date_sr = self.sr_service.search(date_from=date_from, date_to=date_to) self.assertTrue(date_sr) def test_route_get(self): - id_ = self.demo_request_1.id + id_ = self.demo_request_1.external_id route = "/api/subscription-request/%s" % id_ content = self.http_get_content(route) self.assertEquals(self.demo_request_1_dict, content) @@ -126,12 +130,13 @@ class TestSRController(BaseEMCRestCase): "id": self.demo_share_product.id, "name": self.demo_share_product.name, }, + "capital_release_request": [], }, } self.assertEquals(expected, content) def test_route_update(self): - url = "/api/subscription-request/%s" % self.demo_request_1.id + url = "/api/subscription-request/%s" % self.demo_request_1.external_id data = {"state": "done"} response = self.http_post(url, data=data) @@ -141,3 +146,24 @@ class TestSRController(BaseEMCRestCase): expected = self.demo_request_1_dict expected["state"] = "done" self.assertEquals(expected, content) + + def test_route_validate(self): + url = ( + "/api/subscription-request/%s/validate" + % self.demo_request_1.external_id + ) + response = self.http_post(url, data={}) + self.assertEquals(response.status_code, 200) + content = json.loads(response.content.decode("utf-8")) + + state = content.get("state") + self.assertEquals(state, "done") + + def test_service_validate_draft_request(self): + self.sr_service.validate(self.demo_request_1.external_id) + self.assertEquals(self.demo_request_1.state, "done") + self.assertTrue(len(self.demo_request_1.capital_release_request) > 0) + + def test_service_validate_done_request(self): + with self.assertRaises(BadRequest): + self.sr_service.validate(self.demo_request_2.external_id) From 251eea133af7f5dd14bd335088682ff5d6b42341 Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Tue, 9 Jun 2020 14:50:13 +0200 Subject: [PATCH 04/10] =?UTF-8?q?[FIX]=C2=A0emca:=20add=20subscription=20d?= =?UTF-8?q?emo=20journal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- easy_my_coop/demo/coop.xml | 8 ++++---- easy_my_coop/tests/test_base.py | 4 ---- easy_my_coop_api/demo/demo.xml | 12 ++++++------ 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/easy_my_coop/demo/coop.xml b/easy_my_coop/demo/coop.xml index c8cce44..7573fb7 100644 --- a/easy_my_coop/demo/coop.xml +++ b/easy_my_coop/demo/coop.xml @@ -77,8 +77,8 @@ + Equity 100910 - Variable Capital @@ -88,9 +88,9 @@ ref="account_cooperator_demo"/> - - + + + diff --git a/easy_my_coop/tests/test_base.py b/easy_my_coop/tests/test_base.py index b4c4472..cc4c023 100644 --- a/easy_my_coop/tests/test_base.py +++ b/easy_my_coop/tests/test_base.py @@ -8,10 +8,6 @@ import odoo.tests.common as common class EMCBaseCase(common.TransactionCase): def setUp(self): super(EMCBaseCase, self).setUp() - # todo set from demo data - user = self.env["res.users"].browse(self.uid) - cooperator_account = self.ref("easy_my_coop.account_cooperator_demo") - user.company_id.property_cooperator_account = cooperator_account def as_user(self): self.uid = self.ref("base.user_demo") diff --git a/easy_my_coop_api/demo/demo.xml b/easy_my_coop_api/demo/demo.xml index 4caccc9..57f3a58 100644 --- a/easy_my_coop_api/demo/demo.xml +++ b/easy_my_coop_api/demo/demo.xml @@ -9,10 +9,10 @@ cbd07f57-c903-43b4-b668-436b3bec5f15 - - 1 - - - 2 - + + + + + + From d3dd9d0e037542428e17f20de4510c1e5eec2b5b Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Tue, 9 Jun 2020 15:46:57 +0200 Subject: [PATCH 05/10] [ADD] emca: external_id_mixin [IMP] emca: use external_id for product_template --- easy_my_coop/demo/coop.xml | 16 +--- easy_my_coop_api/__manifest__.py | 2 +- easy_my_coop_api/data/sequences.xml | 19 ----- easy_my_coop_api/demo/demo.xml | 13 +-- easy_my_coop_api/models/__init__.py | 3 +- easy_my_coop_api/models/account_invoice.py | 22 ----- easy_my_coop_api/models/external_id_mixin.py | 76 +++++++++++++++++ .../models/subscription_request.py | 24 ------ .../services/subscription_request_service.py | 17 ++-- easy_my_coop_api/tests/__init__.py | 1 + easy_my_coop_api/tests/common.py | 32 ------- .../tests/test_external_id_mixin.py | 83 +++++++++++++++++++ easy_my_coop_api/tests/test_registry.py | 3 - .../tests/test_subscription_requests.py | 51 ++++++++++-- 14 files changed, 222 insertions(+), 140 deletions(-) delete mode 100644 easy_my_coop_api/data/sequences.xml delete mode 100644 easy_my_coop_api/models/account_invoice.py create mode 100644 easy_my_coop_api/models/external_id_mixin.py delete mode 100644 easy_my_coop_api/models/subscription_request.py create mode 100644 easy_my_coop_api/tests/test_external_id_mixin.py diff --git a/easy_my_coop/demo/coop.xml b/easy_my_coop/demo/coop.xml index 7573fb7..9179c16 100644 --- a/easy_my_coop/demo/coop.xml +++ b/easy_my_coop/demo/coop.xml @@ -135,7 +135,6 @@ - Catherine des Champs catherine@demo.net @@ -153,20 +152,6 @@ waiting - - Catherine des Champs - - - catherine@demo.net - Chemin des bois fleuris, 2 - Brussels - 1000 - - - - - - @@ -186,4 +171,5 @@ + diff --git a/easy_my_coop_api/__manifest__.py b/easy_my_coop_api/__manifest__.py index a7f8cd9..7aa896a 100644 --- a/easy_my_coop_api/__manifest__.py +++ b/easy_my_coop_api/__manifest__.py @@ -17,7 +17,7 @@ "summary": """ Open Easy My Coop to the world: RESTful API. """, - "data": ["data/sequences.xml"], + "data": [], "demo": ["demo/demo.xml"], "installable": True, "application": False, diff --git a/easy_my_coop_api/data/sequences.xml b/easy_my_coop_api/data/sequences.xml deleted file mode 100644 index 4d03a8a..0000000 --- a/easy_my_coop_api/data/sequences.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - Subscritpion Request External ID sequence - subscription.request.external.id - 3 - - - Subscritpion Request External ID sequence - account.invoice.external.id - 3 - - - diff --git a/easy_my_coop_api/demo/demo.xml b/easy_my_coop_api/demo/demo.xml index 57f3a58..72d2102 100644 --- a/easy_my_coop_api/demo/demo.xml +++ b/easy_my_coop_api/demo/demo.xml @@ -9,10 +9,11 @@ cbd07f57-c903-43b4-b668-436b3bec5f15 - - - - - - + + 1 + + + + 2 + diff --git a/easy_my_coop_api/models/__init__.py b/easy_my_coop_api/models/__init__.py index b951867..6740752 100644 --- a/easy_my_coop_api/models/__init__.py +++ b/easy_my_coop_api/models/__init__.py @@ -1,3 +1,2 @@ from . import auth_api_key -from . import subscription_request -from . import account_invoice +from . import external_id_mixin diff --git a/easy_my_coop_api/models/account_invoice.py b/easy_my_coop_api/models/account_invoice.py deleted file mode 100644 index ae3c520..0000000 --- a/easy_my_coop_api/models/account_invoice.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2020 Coop IT Easy SCRL fs -# Robin Keunen -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). - -from odoo import api, fields, models - - -class AccountInvoice(models.Model): - _inherit = "account.invoice" - - external_id = fields.Integer( - string="External ID", index=True, required=False - ) - - @api.multi - def get_external_id(self): - self.ensure_one() - if not self.external_id: - self.external_id = self.env["ir.sequence"].next_by_code( - "account.invoice.external.id" - ) - return self.external_id diff --git a/easy_my_coop_api/models/external_id_mixin.py b/easy_my_coop_api/models/external_id_mixin.py new file mode 100644 index 0000000..c2ebbc3 --- /dev/null +++ b/easy_my_coop_api/models/external_id_mixin.py @@ -0,0 +1,76 @@ +# Copyright 2020 Coop IT Easy SCRL fs +# Robin Keunen +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class ExternalIdMixin(models.AbstractModel): + _name = "external.id.mixin" + _description = "External ID Mixin" + + # do not access directly, always use get_api_external_id method + _api_external_id = fields.Integer( + string="External ID", index=True, required=False + ) + external_id_sequence_id = fields.Many2one( + comodel_name="ir.sequence", + string="External ID Sequence", + required=False, + ) + + @api.multi + def set_external_sequence(self): + self.ensure_one() + code = "%s.external.id" % self._name + Sequence = self.env["ir.sequence"] + # check if code was created for that model + sequence = Sequence.search([("code", "=", code)]) + if not sequence: + sequence = Sequence.sudo().create( + {"name": code, "code": code, "number_next": 1} + ) + + self.sudo().write({"external_id_sequence_id": sequence.id}) + return True + + @api.multi + def get_api_external_id(self): + self.ensure_one() + if not self.external_id_sequence_id: + self.set_external_sequence() + if not self._api_external_id: + self.sudo().write( + {"_api_external_id": self.external_id_sequence_id._next()} + ) + return self._api_external_id + + +class ResPartner(models.Model): + _name = "res.partner" + _inherit = ["res.partner", "external.id.mixin"] + + +class SubscriptionRequest(models.Model): + _name = "subscription.request" + _inherit = ["subscription.request", "external.id.mixin"] + + +class AccountAccount(models.Model): + _name = "account.account" + _inherit = ["account.account", "external.id.mixin"] + + +class AccountJournal(models.Model): + _name = "account.journal" + _inherit = ["account.journal", "external.id.mixin"] + + +class AccountInvoice(models.Model): + _name = "account.invoice" + _inherit = ["account.invoice", "external.id.mixin"] + + +class ProductTemplate(models.Model): + _name = "product.template" + _inherit = ["product.template", "external.id.mixin"] diff --git a/easy_my_coop_api/models/subscription_request.py b/easy_my_coop_api/models/subscription_request.py deleted file mode 100644 index 717c072..0000000 --- a/easy_my_coop_api/models/subscription_request.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2020 Coop IT Easy SCRL fs -# Robin Keunen -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). - -from os.path import join - -from odoo import api, fields, models - - -class SubscriptionRequest(models.Model): - _inherit = "subscription.request" - - external_id = fields.Integer( - string="External ID", index=True, required=False - ) - - @api.multi - def get_external_id(self): - self.ensure_one() - if not self.external_id: - self.external_id = self.env["ir.sequence"].next_by_code( - "subscription.request.external.id" - ) - return self.external_id diff --git a/easy_my_coop_api/services/subscription_request_service.py b/easy_my_coop_api/services/subscription_request_service.py index c962690..a56d68a 100644 --- a/easy_my_coop_api/services/subscription_request_service.py +++ b/easy_my_coop_api/services/subscription_request_service.py @@ -24,12 +24,12 @@ class SubscriptionRequestService(Component): _usage = "subscription-request" _collection = "emc.services" _description = """ - Subscription requests + Subscription Request Services """ def get(self, _id): sr = self.env["subscription.request"].search( - [("external_id", "=", _id)] + [("_api_external_id", "=", _id)] ) if sr: return self._to_dict(sr) @@ -66,7 +66,7 @@ class SubscriptionRequestService(Component): def update(self, _id, **params): params = self._prepare_update(params) sr = self.env["subscription.request"].search( - [("external_id", "=", _id)] + [("_api_external_id", "=", _id)] ) if not sr: raise wrapJsonException( @@ -77,7 +77,7 @@ class SubscriptionRequestService(Component): def validate(self, _id, **params): sr = self.env["subscription.request"].search( - [("external_id", "=", _id)] + [("_api_external_id", "=", _id)] ) if not sr: raise wrapJsonException( @@ -97,22 +97,23 @@ class SubscriptionRequestService(Component): if sr.capital_release_request: invoice_ids = [ - invoice.get_external_id() + invoice.get_api_external_id() for invoice in sr.capital_release_request ] else: invoice_ids = [] + share_product = sr.share_product_id.product_tmpl_id return { - "id": sr.get_external_id(), + "id": sr.get_api_external_id(), "name": sr.name, "email": sr.email, "state": sr.state, "date": Date.to_string(sr.date), "ordered_parts": sr.ordered_parts, "share_product": { - "id": sr.share_product_id.product_tmpl_id.id, - "name": sr.share_product_id.product_tmpl_id.name, + "id": share_product.get_api_external_id(), + "name": share_product.name, }, "address": { "street": sr.address, diff --git a/easy_my_coop_api/tests/__init__.py b/easy_my_coop_api/tests/__init__.py index f831997..a7be43d 100644 --- a/easy_my_coop_api/tests/__init__.py +++ b/easy_my_coop_api/tests/__init__.py @@ -1,3 +1,4 @@ from . import test_ping from . import test_registry +from . import test_external_id_mixin from . import test_subscription_requests diff --git a/easy_my_coop_api/tests/common.py b/easy_my_coop_api/tests/common.py index 5c91962..d959400 100644 --- a/easy_my_coop_api/tests/common.py +++ b/easy_my_coop_api/tests/common.py @@ -9,7 +9,6 @@ import requests from lxml import html import odoo -from odoo.fields import Date from odoo.addons.base_rest.tests.common import BaseRestCase @@ -37,37 +36,6 @@ class BaseEMCRestCase(BaseRestCase): def setUp(self): super().setUp() self.session = requests.Session() - self.demo_request_1 = self.browse_ref( - "easy_my_coop.subscription_request_1_demo" - ) - self.demo_request_2 = self.browse_ref( - "easy_my_coop.subscription_request_2_demo" - ) - self.demo_share_product = ( - self.demo_request_1.share_product_id.product_tmpl_id - ) - - date = Date.to_string(self.demo_request_1.date) - self.demo_request_1_dict = { - "id": self.demo_request_1.id, - "name": "Manuel Dublues", - "email": "manuel@demo.net", - "date": date, - "state": "draft", - "ordered_parts": 3, - "share_product": { - "id": self.demo_share_product.id, - "name": self.demo_share_product.name, - }, - "address": { - "street": "schaerbeekstraat", - "zip_code": "1111", - "city": "Brussels", - "country": "BE", - }, - "lang": "en_US", - "capital_release_request": [], - } def http_get(self, url, headers=None): headers = self._add_api_key(headers) diff --git a/easy_my_coop_api/tests/test_external_id_mixin.py b/easy_my_coop_api/tests/test_external_id_mixin.py new file mode 100644 index 0000000..0f7f0a3 --- /dev/null +++ b/easy_my_coop_api/tests/test_external_id_mixin.py @@ -0,0 +1,83 @@ +# Copyright 2020 Coop IT Easy SCRL fs +# Robin Keunen +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo.fields import Date +from odoo.tests import TransactionCase + + +class TestExternalIdMixin(TransactionCase): + def test_res_partner_api_external_id(self): + partner = self.env["res.partner"].create({"name": "Test Partner"}) + self.assertFalse(partner._api_external_id) + self.assertFalse(partner.external_id_sequence_id) + + external_id = partner.get_api_external_id() + self.assertTrue(bool(partner._api_external_id)) + self.assertTrue(bool(partner.external_id_sequence_id)) + + self.assertEquals(external_id, partner.get_api_external_id()) + + def test_subscription_request_api_external_id(self): + share_type = self.browse_ref( + "easy_my_coop.product_template_share_type_2_demo" + ).product_variant_id + sr = self.env["subscription.request"].create( + { + "name": "test create request", + "email": "test@demo.net", + "address": "schaerbeekstraat", + "zip_code": "1111", + "city": "Brussels", + "country_id": self.ref("base.be"), + "date": Date.today(), + "source": "manual", + "ordered_parts": 3, + "share_product_id": share_type.id, + "lang": "en_US", + } + ) + self.assertFalse(sr._api_external_id) + self.assertFalse(sr.external_id_sequence_id) + + external_id = sr.get_api_external_id() + self.assertTrue(bool(sr._api_external_id)) + self.assertTrue(bool(sr.external_id_sequence_id)) + + self.assertEquals(external_id, sr.get_api_external_id()) + + def test_account_journal_api_external_id(self): + bank = self.env["res.partner.bank"].create( + { + "acc_number": "test", + "partner_id": self.env.user.company_id.partner_id.id, + } + ) + journal = self.env["account.journal"].create( + { + "name": "test journal", + "code": "123", + "type": "bank", + "company_id": self.env.ref("base.main_company").id, + "bank_account_id": bank.id, + } + ) + self.assertFalse(journal._api_external_id) + self.assertFalse(journal.external_id_sequence_id) + + external_id = journal.get_api_external_id() + self.assertTrue(bool(journal._api_external_id)) + self.assertTrue(bool(journal.external_id_sequence_id)) + + self.assertEquals(external_id, journal.get_api_external_id()) + + def test_account_invoice_api_external_id(self): + invoice = self.env["account.invoice"].create({"name": "create passes"}) + self.assertFalse(invoice._api_external_id) + self.assertFalse(invoice.external_id_sequence_id) + + external_id = invoice.get_api_external_id() + self.assertTrue(bool(invoice._api_external_id)) + self.assertTrue(bool(invoice.external_id_sequence_id)) + + self.assertEquals(external_id, invoice.get_api_external_id()) diff --git a/easy_my_coop_api/tests/test_registry.py b/easy_my_coop_api/tests/test_registry.py index b420eff..adef8e3 100644 --- a/easy_my_coop_api/tests/test_registry.py +++ b/easy_my_coop_api/tests/test_registry.py @@ -10,9 +10,6 @@ from odoo.addons.base_rest.tests.common import BaseRestCase from ..controllers.controllers import UserController -HOST = "127.0.0.1" -PORT = odoo.tools.config["http_port"] - class TestControllerRegistry(BaseRestCase): def test_controller_registry(self): diff --git a/easy_my_coop_api/tests/test_subscription_requests.py b/easy_my_coop_api/tests/test_subscription_requests.py index 36764da..73e66e2 100644 --- a/easy_my_coop_api/tests/test_subscription_requests.py +++ b/easy_my_coop_api/tests/test_subscription_requests.py @@ -28,11 +28,43 @@ class TestSRController(BaseEMCRestCase): usage="subscription-request" ) + self.demo_request_1 = self.browse_ref( + "easy_my_coop.subscription_request_1_demo" + ) + self.demo_request_2 = self.browse_ref( + "easy_my_coop.subscription_request_waiting_demo" + ) + self.demo_share_product = ( + self.demo_request_1.share_product_id.product_tmpl_id + ) + + date = Date.to_string(self.demo_request_1.date) + self.demo_request_1_dict = { + "id": self.demo_request_1.get_api_external_id(), + "name": "Manuel Dublues", + "email": "manuel@demo.net", + "date": date, + "state": "draft", + "ordered_parts": 3, + "share_product": { + "id": self.demo_share_product.get_api_external_id(), + "name": self.demo_share_product.name, + }, + "address": { + "street": "schaerbeekstraat", + "zip_code": "1111", + "city": "Brussels", + "country": "BE", + }, + "lang": "en_US", + "capital_release_request": [], + } + def test_service(self): # kept as example # useful if you need to change data in database and check db type - result = self.sr_service.get(self.demo_request_1.external_id) + result = self.sr_service.get(self.demo_request_1.get_api_external_id()) self.assertEquals(self.demo_request_1_dict, result) all_sr = self.sr_service.search() @@ -46,8 +78,8 @@ class TestSRController(BaseEMCRestCase): self.assertTrue(date_sr) def test_route_get(self): - id_ = self.demo_request_1.external_id - route = "/api/subscription-request/%s" % id_ + external_id = self.demo_request_1.get_api_external_id() + route = "/api/subscription-request/%s" % external_id content = self.http_get_content(route) self.assertEquals(self.demo_request_1_dict, content) @@ -127,7 +159,7 @@ class TestSRController(BaseEMCRestCase): "date": Date.to_string(Date.today()), "state": "draft", "share_product": { - "id": self.demo_share_product.id, + "id": self.demo_share_product.get_api_external_id(), "name": self.demo_share_product.name, }, "capital_release_request": [], @@ -136,7 +168,10 @@ class TestSRController(BaseEMCRestCase): self.assertEquals(expected, content) def test_route_update(self): - url = "/api/subscription-request/%s" % self.demo_request_1.external_id + url = ( + "/api/subscription-request/%s" + % self.demo_request_1.get_api_external_id() + ) data = {"state": "done"} response = self.http_post(url, data=data) @@ -150,7 +185,7 @@ class TestSRController(BaseEMCRestCase): def test_route_validate(self): url = ( "/api/subscription-request/%s/validate" - % self.demo_request_1.external_id + % self.demo_request_1.get_api_external_id() ) response = self.http_post(url, data={}) self.assertEquals(response.status_code, 200) @@ -160,10 +195,10 @@ class TestSRController(BaseEMCRestCase): self.assertEquals(state, "done") def test_service_validate_draft_request(self): - self.sr_service.validate(self.demo_request_1.external_id) + self.sr_service.validate(self.demo_request_1.get_api_external_id()) self.assertEquals(self.demo_request_1.state, "done") self.assertTrue(len(self.demo_request_1.capital_release_request) > 0) def test_service_validate_done_request(self): with self.assertRaises(BadRequest): - self.sr_service.validate(self.demo_request_2.external_id) + self.sr_service.validate(self.demo_request_2.get_api_external_id()) From 4071aab54e1cb574e24032d605664e2ca7ec72dd Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Thu, 11 Jun 2020 16:40:14 +0200 Subject: [PATCH 06/10] [ADD] emca: invoice service --- easy_my_coop_api/services/__init__.py | 1 + .../services/account_invoice_service.py | 81 +++++++++ easy_my_coop_api/services/schemas.py | 35 +++- easy_my_coop_api/tests/__init__.py | 1 + easy_my_coop_api/tests/common.py | 161 +++++++++++++++++- .../tests/test_account_invoice.py | 101 +++++++++++ 6 files changed, 375 insertions(+), 5 deletions(-) create mode 100644 easy_my_coop_api/tests/test_account_invoice.py diff --git a/easy_my_coop_api/services/__init__.py b/easy_my_coop_api/services/__init__.py index d657c40..546abd6 100644 --- a/easy_my_coop_api/services/__init__.py +++ b/easy_my_coop_api/services/__init__.py @@ -1,2 +1,3 @@ from . import ping_service from . import subscription_request_service +from . import account_invoice_service diff --git a/easy_my_coop_api/services/account_invoice_service.py b/easy_my_coop_api/services/account_invoice_service.py index e69de29..1eda236 100644 --- a/easy_my_coop_api/services/account_invoice_service.py +++ b/easy_my_coop_api/services/account_invoice_service.py @@ -0,0 +1,81 @@ +# Copyright 2019 Coop IT Easy SCRL fs +# Robin Keunen +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +# pylint: disable=consider-merging-classes-inherited + +import logging + +from werkzeug.exceptions import NotFound + +from odoo import _ +from odoo.fields import Date + +from odoo.addons.base_rest.http import wrapJsonException +from odoo.addons.component.core import Component + +from . import schemas + +_logger = logging.getLogger(__name__) + + +class AccountInvoiceService(Component): + _inherit = "base.rest.service" + _name = "account.invoice.services" + _usage = "invoice" + _collection = "emc.services" + _description = """ + Account Invoice Services + """ + + def get(self, _id): + sr = self.env["account.invoice"].search( + [("_api_external_id", "=", _id)] + ) + if sr: + return self._to_dict(sr) + else: + raise wrapJsonException( + NotFound(_("No invoice found for id %s") % _id) + ) + + def _to_dict(self, invoice): + invoice.ensure_one() + + if invoice.subscription_request: + sr_external_id = invoice.subscription_request.get_api_external_id() + else: + sr_external_id = None + + # todo return dictionaries for Many2one fields + data = { + "id": invoice.get_api_external_id(), + "name": invoice.name, + "state": invoice.state, + "type": invoice.type, + "date": Date.to_string(invoice.date), + "date_due": Date.to_string(invoice.date_due), + "date_invoice": Date.to_string(invoice.date_invoice), + "partner": invoice.partner_id.get_api_external_id(), + "journal": invoice.journal_id.get_api_external_id(), + "account": invoice.account_id.get_api_external_id(), + "subscription_request": sr_external_id, + "invoice_lines": [ + self._line_to_dict(line) for line in invoice.invoice_line_ids + ], + } + return data + + def _line_to_dict(self, line): + return { + "name": line.name, + "account": line.account_id.get_api_external_id(), + "product": line.product_id.product_tmpl_id.get_api_external_id(), + "quantity": line.quantity, + "price_unit": line.price_unit, + } + + def _validator_get(self): + return schemas.S_INVOICE_GET + + def _validator_return_get(self): + return schemas.S_INVOICE_RETURN_GET diff --git a/easy_my_coop_api/services/schemas.py b/easy_my_coop_api/services/schemas.py index 2b374f4..a1886fc 100644 --- a/easy_my_coop_api/services/schemas.py +++ b/easy_my_coop_api/services/schemas.py @@ -9,7 +9,7 @@ from odoo.fields import Date def date_validator(field, value, error): try: Date.from_string(value) - except ValueError as e: + except ValueError: return error( field, _("{} does not match format '%Y-%m-%d'".format(value)) ) @@ -101,3 +101,36 @@ S_SUBSCRIPTION_REQUEST_UPDATE = { } S_SUBSCRIPTION_REQUEST_VALIDATE = {"_id": {"type": "integer"}} + +S_INVOICE_GET = {"_id": {"type": "integer"}} + +S_INVOICE_LINE_RETURN_GET = { + "type": "list", + "schema": { + "type": "dict", + "schema": { + "name": {"type": "string", "required": True}, + "account": {"type": "integer", "required": True}, + "product": {"type": "integer", "required": True}, + "quantity": {"type": "float", "required": True}, + "price_unit": {"type": "float", "required": True}, + }, + }, + "required": True, + "empty": True, +} + +S_INVOICE_RETURN_GET = { + "id": {"type": "integer", "required": True}, + "name": {"type": "string", "required": True, "empty": False}, + "state": {"type": "string", "required": True, "empty": False}, + "type": {"type": "string", "required": True, "empty": False}, + "date": {"type": "string", "required": True, "empty": False}, + "date_due": {"type": "string", "required": True, "empty": False}, + "date_invoice": {"type": "string", "required": True, "empty": False}, + "partner": {"type": "integer", "required": True}, + "journal": {"type": "integer", "required": True}, + "account": {"type": "integer", "required": True}, + "subscription_request": {"type": "integer", "nullable": True}, + "invoice_lines": S_INVOICE_LINE_RETURN_GET, +} diff --git a/easy_my_coop_api/tests/__init__.py b/easy_my_coop_api/tests/__init__.py index a7be43d..b3a4cd1 100644 --- a/easy_my_coop_api/tests/__init__.py +++ b/easy_my_coop_api/tests/__init__.py @@ -2,3 +2,4 @@ from . import test_ping from . import test_registry from . import test_external_id_mixin from . import test_subscription_requests +from . import test_account_invoice diff --git a/easy_my_coop_api/tests/common.py b/easy_my_coop_api/tests/common.py index d959400..763b66b 100644 --- a/easy_my_coop_api/tests/common.py +++ b/easy_my_coop_api/tests/common.py @@ -24,6 +24,163 @@ class BaseEMCRestCase(BaseRestCase): cls.api_key_test = cls.env.ref( "easy_my_coop_api.auth_api_key_manager_emc_demo" ) + cls._chart_template_create() + cls._add_chart_of_accounts() + cls._journals_setup() + + def setUp(self): + super().setUp() + self.session = requests.Session() + + @classmethod + def _chart_template_create(cls): + transfer_account_id = cls.env["account.account.template"].create( + { + "code": "000", + "name": "Liquidity Transfers", + "reconcile": True, + "user_type_id": cls.env.ref( + "account.data_account_type_current_assets" + ).id, + } + ) + cls.chart = cls.env["account.chart.template"].create( + { + "name": "Test COA", + "code_digits": 4, + "bank_account_code_prefix": 1014, + "cash_account_code_prefix": 1014, + "currency_id": cls.env.ref("base.USD").id, + "transfer_account_code_prefix": "000", + } + ) + transfer_account_id.update({"chart_template_id": cls.chart.id}) + cls.env["ir.model.data"].create( + { + "res_id": transfer_account_id.id, + "model": transfer_account_id._name, + "name": "Liquidity Transfers", + } + ) + act = cls.env["account.account.template"].create( + { + "code": "001", + "name": "Expenses", + "user_type_id": cls.env.ref( + "account.data_account_type_expenses" + ).id, + "chart_template_id": cls.chart.id, + "reconcile": True, + } + ) + cls.env["ir.model.data"].create( + {"res_id": act.id, "model": act._name, "name": "expenses"} + ) + act = cls.env["account.account.template"].create( + { + "code": "002", + "name": "Product Sales", + "user_type_id": cls.env.ref( + "account.data_account_type_revenue" + ).id, + "chart_template_id": cls.chart.id, + "reconcile": True, + } + ) + cls.env["ir.model.data"].create( + {"res_id": act.id, "model": act._name, "name": "sales"} + ) + act = cls.env["account.account.template"].create( + { + "code": "003", + "name": "Account Receivable", + "user_type_id": cls.env.ref( + "account.data_account_type_receivable" + ).id, + "chart_template_id": cls.chart.id, + "reconcile": True, + } + ) + cls.env["ir.model.data"].create( + {"res_id": act.id, "model": act._name, "name": "receivable"} + ) + act = cls.env["account.account.template"].create( + { + "code": "004", + "name": "Account Payable", + "user_type_id": cls.env.ref( + "account.data_account_type_payable" + ).id, + "chart_template_id": cls.chart.id, + "reconcile": True, + } + ) + cls.env["ir.model.data"].create( + {"res_id": act.id, "model": act._name, "name": "payable"} + ) + + @classmethod + def _add_chart_of_accounts(cls): + cls.company = cls.env.user.company_id + cls.chart.try_loading_for_current_company() + cls.revenue = cls.env["account.account"].search( + [ + ( + "user_type_id", + "=", + cls.env.ref("account.data_account_type_revenue").id, + ) + ], + limit=1, + ) + cls.expense = cls.env["account.account"].search( + [ + ( + "user_type_id", + "=", + cls.env.ref("account.data_account_type_expenses").id, + ) + ], + limit=1, + ) + cls.receivable = cls.env["account.account"].search( + [ + ( + "user_type_id", + "=", + cls.env.ref("account.data_account_type_receivable").id, + ) + ], + limit=1, + ) + cls.payable = cls.env["account.account"].search( + [ + ( + "user_type_id", + "=", + cls.env.ref("account.data_account_type_payable").id, + ) + ], + limit=1, + ) + cls.equity_account = cls.env.ref("easy_my_coop.account_equity_demo") + cls.cooperator_account = cls.env.ref( + "easy_my_coop.account_cooperator_demo" + ) + return True + + @classmethod + def _journals_setup(cls): + cls.subscription_journal = cls.env.ref( + "easy_my_coop.subscription_journal" + ) + cls.subscription_journal.write( + { + "default_debit_account_id": cls.equity_account.id, + "default_credit_account_id": cls.equity_account.id, + } + ) + return True def _add_api_key(self, headers): key_dict = {"API-KEY": self.api_key_test.key} @@ -33,10 +190,6 @@ class BaseEMCRestCase(BaseRestCase): headers = key_dict return headers - def setUp(self): - super().setUp() - self.session = requests.Session() - def http_get(self, url, headers=None): headers = self._add_api_key(headers) if url.startswith("/"): diff --git a/easy_my_coop_api/tests/test_account_invoice.py b/easy_my_coop_api/tests/test_account_invoice.py new file mode 100644 index 0000000..3fdf07a --- /dev/null +++ b/easy_my_coop_api/tests/test_account_invoice.py @@ -0,0 +1,101 @@ +# Copyright 2020 Coop IT Easy SCRL fs +# Robin Keunen +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo.fields import Date + +from odoo.addons.base_rest.controllers.main import _PseudoCollection +from odoo.addons.component.core import WorkContext + +from .common import BaseEMCRestCase + + +class TestAccountInvoiceController(BaseEMCRestCase): + @classmethod + def setUpClass(cls, *args, **kwargs): + super().setUpClass(*args, **kwargs) + + def setUp(self): + res = super().setUp() + collection = _PseudoCollection("emc.services", self.env) + emc_services_env = WorkContext( + model_name="rest.service.registration", collection=collection + ) + self.ai_service = emc_services_env.component(usage="invoice") + + self.share_type_A = self.browse_ref( + "easy_my_coop.product_template_share_type_1_demo" + ) + self._capital_release_create() + + today = Date.to_string(Date.today()) + self.demo_invoice_dict = { + "id": 1, + "name": "Capital Release Example", + "partner": 1, + "account": 1, + "journal": 1, + "subscription_request": None, + "state": "open", + "date": today, + "date_invoice": today, + "date_due": today, + "type": "out_invoice", + "invoice_lines": [ + { + "account": 2, + "name": "Share Type A", + "price_unit": 100.0, + "product": 1, + "quantity": 2.0, + } + ], + } + return res + + def _capital_release_create(self): + self.coop_candidate = self.env["res.partner"].create( + { + "name": "Catherine des Champs", + "company_id": self.company.id, + "property_account_receivable_id": self.receivable.id, + "property_account_payable_id": self.payable.id, + } + ) + + capital_release_line = [ + ( + 0, + False, + { + "name": "Share Type A", + "account_id": self.equity_account.id, + "quantity": 2.0, + "price_unit": 100.0, + "product_id": self.share_type_A.product_variant_id.id, + }, + ) + ] + + self.capital_release = self.env["account.invoice"].create( + { + "name": "Capital Release Example", + "partner_id": self.coop_candidate.id, + "type": "out_invoice", + "invoice_line_ids": capital_release_line, + "account_id": self.cooperator_account.id, + "journal_id": self.subscription_journal.id, + } + ) + self.capital_release.action_invoice_open() + + def test_service_get(self): + external_id = self.capital_release.get_api_external_id() + result = self.ai_service.get(external_id) + self.assertEquals(self.demo_invoice_dict, result) + + def test_route_get(self): + external_id = self.capital_release.get_api_external_id() + route = "/api/invoice/%s" % external_id + content = self.http_get_content(route) + self.assertEquals(self.demo_invoice_dict, content) From b033b3195aff25371796d221c9cd6e2b18412f25 Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Thu, 11 Jun 2020 17:36:55 +0200 Subject: [PATCH 07/10] [IMP] emca: return dictionary for one2many fields --- .../services/account_invoice_service.py | 22 ++++++------- easy_my_coop_api/services/schemas.py | 31 +++++++++++-------- .../services/subscription_request_service.py | 11 ++++--- .../tests/test_account_invoice.py | 12 +++---- 4 files changed, 41 insertions(+), 35 deletions(-) diff --git a/easy_my_coop_api/services/account_invoice_service.py b/easy_my_coop_api/services/account_invoice_service.py index 1eda236..54f5d50 100644 --- a/easy_my_coop_api/services/account_invoice_service.py +++ b/easy_my_coop_api/services/account_invoice_service.py @@ -41,12 +41,6 @@ class AccountInvoiceService(Component): def _to_dict(self, invoice): invoice.ensure_one() - if invoice.subscription_request: - sr_external_id = invoice.subscription_request.get_api_external_id() - else: - sr_external_id = None - - # todo return dictionaries for Many2one fields data = { "id": invoice.get_api_external_id(), "name": invoice.name, @@ -55,10 +49,12 @@ class AccountInvoiceService(Component): "date": Date.to_string(invoice.date), "date_due": Date.to_string(invoice.date_due), "date_invoice": Date.to_string(invoice.date_invoice), - "partner": invoice.partner_id.get_api_external_id(), - "journal": invoice.journal_id.get_api_external_id(), - "account": invoice.account_id.get_api_external_id(), - "subscription_request": sr_external_id, + "partner": self._one_to_many_to_dict(invoice.partner_id), + "journal": self._one_to_many_to_dict(invoice.journal_id), + "account": self._one_to_many_to_dict(invoice.account_id), + "subscription_request": self._one_to_many_to_dict( + invoice.subscription_request + ), "invoice_lines": [ self._line_to_dict(line) for line in invoice.invoice_line_ids ], @@ -68,8 +64,10 @@ class AccountInvoiceService(Component): def _line_to_dict(self, line): return { "name": line.name, - "account": line.account_id.get_api_external_id(), - "product": line.product_id.product_tmpl_id.get_api_external_id(), + "account": self._one_to_many_to_dict(line.account_id), + "product": self._one_to_many_to_dict( + line.product_id.product_tmpl_id + ), "quantity": line.quantity, "price_unit": line.price_unit, } diff --git a/easy_my_coop_api/services/schemas.py b/easy_my_coop_api/services/schemas.py index a1886fc..4f19bb8 100644 --- a/easy_my_coop_api/services/schemas.py +++ b/easy_my_coop_api/services/schemas.py @@ -15,6 +15,14 @@ def date_validator(field, value, error): ) +S_MANY_2_ONE = { + "type": "dict", + "schema": { + "id": {"type": "integer", "required": True}, + "name": {"type": "string", "required": True, "empty": False}, + }, +} + S_SUBSCRIPTION_REQUEST_GET = {"_id": {"type": "integer"}} S_SUBSCRIPTION_REQUEST_RETURN_GET = { @@ -24,13 +32,7 @@ S_SUBSCRIPTION_REQUEST_RETURN_GET = { "date": {"type": "string", "required": True, "empty": False}, "state": {"type": "string", "required": True, "empty": False}, "ordered_parts": {"type": "integer", "required": True}, - "share_product": { - "type": "dict", - "schema": { - "id": {"type": "integer", "required": True}, - "name": {"type": "string", "required": True, "empty": False}, - }, - }, + "share_product": S_MANY_2_ONE, "address": { "type": "dict", "schema": { @@ -110,8 +112,8 @@ S_INVOICE_LINE_RETURN_GET = { "type": "dict", "schema": { "name": {"type": "string", "required": True}, - "account": {"type": "integer", "required": True}, - "product": {"type": "integer", "required": True}, + "account": S_MANY_2_ONE, + "product": S_MANY_2_ONE, "quantity": {"type": "float", "required": True}, "price_unit": {"type": "float", "required": True}, }, @@ -128,9 +130,12 @@ S_INVOICE_RETURN_GET = { "date": {"type": "string", "required": True, "empty": False}, "date_due": {"type": "string", "required": True, "empty": False}, "date_invoice": {"type": "string", "required": True, "empty": False}, - "partner": {"type": "integer", "required": True}, - "journal": {"type": "integer", "required": True}, - "account": {"type": "integer", "required": True}, - "subscription_request": {"type": "integer", "nullable": True}, + "partner": S_MANY_2_ONE, + "journal": S_MANY_2_ONE, + "account": S_MANY_2_ONE, + "subscription_request": { + "type": "dict", + "schema": {"id": {"type": "integer"}, "name": {"type": "string"}}, + }, "invoice_lines": S_INVOICE_LINE_RETURN_GET, } diff --git a/easy_my_coop_api/services/subscription_request_service.py b/easy_my_coop_api/services/subscription_request_service.py index a56d68a..76f824d 100644 --- a/easy_my_coop_api/services/subscription_request_service.py +++ b/easy_my_coop_api/services/subscription_request_service.py @@ -111,10 +111,7 @@ class SubscriptionRequestService(Component): "state": sr.state, "date": Date.to_string(sr.date), "ordered_parts": sr.ordered_parts, - "share_product": { - "id": share_product.get_api_external_id(), - "name": share_product.name, - }, + "share_product": self._one_to_many_to_dict(share_product), "address": { "street": sr.address, "zip_code": sr.zip_code, @@ -125,6 +122,12 @@ class SubscriptionRequestService(Component): "capital_release_request": invoice_ids, } + def _one_to_many_to_dict(self, record): + if record: + return {"id": record.get_api_external_id(), "name": record.name} + else: + return {} + def _get_country(self, code): country = self.env["res.country"].search([("code", "=", code)]) if country: diff --git a/easy_my_coop_api/tests/test_account_invoice.py b/easy_my_coop_api/tests/test_account_invoice.py index 3fdf07a..2eaf902 100644 --- a/easy_my_coop_api/tests/test_account_invoice.py +++ b/easy_my_coop_api/tests/test_account_invoice.py @@ -32,10 +32,10 @@ class TestAccountInvoiceController(BaseEMCRestCase): self.demo_invoice_dict = { "id": 1, "name": "Capital Release Example", - "partner": 1, - "account": 1, - "journal": 1, - "subscription_request": None, + "partner": {"id": 1, "name": "Catherine des Champs"}, + "account": {"id": 1, "name": "Cooperators"}, + "journal": {"id": 1, "name": "Subscription Journal"}, + "subscription_request": {}, "state": "open", "date": today, "date_invoice": today, @@ -43,11 +43,11 @@ class TestAccountInvoiceController(BaseEMCRestCase): "type": "out_invoice", "invoice_lines": [ { - "account": 2, "name": "Share Type A", + "product": {"id": 1, "name": "Part A - Founder"}, "price_unit": 100.0, - "product": 1, "quantity": 2.0, + "account": {"id": 2, "name": "Equity"}, } ], } From a2bdcb43c63959473b96d9951e68ec4086e293ef Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Thu, 11 Jun 2020 17:54:29 +0200 Subject: [PATCH 08/10] [REF] emca: add AbsctractComponent for services --- easy_my_coop_api/services/__init__.py | 1 + .../services/abstract_emc_service.py | 21 +++++++++++++++++++ .../services/account_invoice_service.py | 5 ++--- easy_my_coop_api/services/ping_service.py | 3 +-- .../services/subscription_request_service.py | 9 +------- 5 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 easy_my_coop_api/services/abstract_emc_service.py diff --git a/easy_my_coop_api/services/__init__.py b/easy_my_coop_api/services/__init__.py index 546abd6..c9cf30f 100644 --- a/easy_my_coop_api/services/__init__.py +++ b/easy_my_coop_api/services/__init__.py @@ -1,3 +1,4 @@ +from . import abstract_emc_service from . import ping_service from . import subscription_request_service from . import account_invoice_service diff --git a/easy_my_coop_api/services/abstract_emc_service.py b/easy_my_coop_api/services/abstract_emc_service.py new file mode 100644 index 0000000..3911b67 --- /dev/null +++ b/easy_my_coop_api/services/abstract_emc_service.py @@ -0,0 +1,21 @@ +# Copyright 2019 Coop IT Easy SCRL fs +# Robin Keunen +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +# pylint: disable=consider-merging-classes-inherited + +from odoo.addons.component.core import AbstractComponent + + +class BaseRestService(AbstractComponent): + _name = "emc.rest.service" + _inherit = "base.rest.service" + _collection = "emc.services" + _description = """ + Base Rest Services + """ + + def _one_to_many_to_dict(self, record): + if record: + return {"id": record.get_api_external_id(), "name": record.name} + else: + return {} diff --git a/easy_my_coop_api/services/account_invoice_service.py b/easy_my_coop_api/services/account_invoice_service.py index 54f5d50..29216e5 100644 --- a/easy_my_coop_api/services/account_invoice_service.py +++ b/easy_my_coop_api/services/account_invoice_service.py @@ -19,10 +19,9 @@ _logger = logging.getLogger(__name__) class AccountInvoiceService(Component): - _inherit = "base.rest.service" - _name = "account.invoice.services" + _name = "account.invoice.service" + _inherit = "emc.rest.service" _usage = "invoice" - _collection = "emc.services" _description = """ Account Invoice Services """ diff --git a/easy_my_coop_api/services/ping_service.py b/easy_my_coop_api/services/ping_service.py index 49b37d1..f3b48fd 100644 --- a/easy_my_coop_api/services/ping_service.py +++ b/easy_my_coop_api/services/ping_service.py @@ -10,10 +10,9 @@ from odoo.addons.component.core import Component class PingService(Component): - _inherit = "base.rest.service" + _inherit = "emc.rest.service" _name = "emc.services" _usage = "ping" # service_name - _collection = "emc.services" _description = """ Ping services (test the api) """ diff --git a/easy_my_coop_api/services/subscription_request_service.py b/easy_my_coop_api/services/subscription_request_service.py index 76f824d..66e3a2e 100644 --- a/easy_my_coop_api/services/subscription_request_service.py +++ b/easy_my_coop_api/services/subscription_request_service.py @@ -19,10 +19,9 @@ _logger = logging.getLogger(__name__) class SubscriptionRequestService(Component): - _inherit = "base.rest.service" + _inherit = "emc.rest.service" _name = "subscription.request.services" _usage = "subscription-request" - _collection = "emc.services" _description = """ Subscription Request Services """ @@ -122,12 +121,6 @@ class SubscriptionRequestService(Component): "capital_release_request": invoice_ids, } - def _one_to_many_to_dict(self, record): - if record: - return {"id": record.get_api_external_id(), "name": record.name} - else: - return {} - def _get_country(self, code): country = self.env["res.country"].search([("code", "=", code)]) if country: From 19c7ee35ec4ddab2d79f4628373d9397a0a4c298 Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Wed, 12 Aug 2020 09:34:12 +0200 Subject: [PATCH 09/10] [ADD] emca: mark invoice as paid (account_payment service) --- easy_my_coop_api/models/external_id_mixin.py | 5 + easy_my_coop_api/services/__init__.py | 1 + .../services/account_payment_service.py | 92 +++++++++++++++++++ easy_my_coop_api/services/schemas.py | 19 ++++ easy_my_coop_api/tests/__init__.py | 1 + easy_my_coop_api/tests/common.py | 3 + .../tests/test_account_payment.py | 69 ++++++++++++++ 7 files changed, 190 insertions(+) create mode 100644 easy_my_coop_api/services/account_payment_service.py create mode 100644 easy_my_coop_api/tests/test_account_payment.py diff --git a/easy_my_coop_api/models/external_id_mixin.py b/easy_my_coop_api/models/external_id_mixin.py index c2ebbc3..cd9193e 100644 --- a/easy_my_coop_api/models/external_id_mixin.py +++ b/easy_my_coop_api/models/external_id_mixin.py @@ -71,6 +71,11 @@ class AccountInvoice(models.Model): _inherit = ["account.invoice", "external.id.mixin"] +class AccountPayment(models.Model): + _name = "account.payment" + _inherit = ["account.payment", "external.id.mixin"] + + class ProductTemplate(models.Model): _name = "product.template" _inherit = ["product.template", "external.id.mixin"] diff --git a/easy_my_coop_api/services/__init__.py b/easy_my_coop_api/services/__init__.py index c9cf30f..6ab9a93 100644 --- a/easy_my_coop_api/services/__init__.py +++ b/easy_my_coop_api/services/__init__.py @@ -2,3 +2,4 @@ from . import abstract_emc_service from . import ping_service from . import subscription_request_service from . import account_invoice_service +from . import account_payment_service diff --git a/easy_my_coop_api/services/account_payment_service.py b/easy_my_coop_api/services/account_payment_service.py new file mode 100644 index 0000000..d8094e3 --- /dev/null +++ b/easy_my_coop_api/services/account_payment_service.py @@ -0,0 +1,92 @@ +# Copyright 2019 Coop IT Easy SCRL fs +# Robin Keunen +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +# pylint: disable=consider-merging-classes-inherited + +import logging + +from werkzeug.exceptions import NotFound + +from odoo import _ +from odoo.fields import Date + +from odoo.addons.base_rest.http import wrapJsonException +from odoo.addons.component.core import Component + +from . import schemas + +_logger = logging.getLogger(__name__) + + +class AccountPaymentService(Component): + _name = "account.payment.service" + _inherit = "emc.rest.service" + _usage = "payment" + _description = """ + Account Payment Services + """ + + def create(self, **params): # pylint: disable=method-required-super + params = self._prepare_create(params) + payment = self.env["account.payment"].create(params) + payment.post() + return self._to_dict(payment) + + def _prepare_create(self, params): + """Prepare a writable dictionary of values""" + journal = self.env["account.journal"].search( + [("_api_external_id", "=", params["journal"])] + ) + if not journal: + raise wrapJsonException( + NotFound(_("No journal %s on platform") % params["journal"]) + ) + + invoice = self.env["account.invoice"].search( + [("_api_external_id", "=", params["invoice"])] + ) + if not invoice: + raise wrapJsonException( + NotFound(_("No invoice %s on platform") % params["invoice"]) + ) + + payment_method_id = self.env["account.payment.method"].search( + [ + ("code", "=", params["payment_method"]), + ("payment_type", "=", params["payment_type"]), + ] + ) + if not payment_method_id: + codes = ( + self.env["account.payment.method"].search([]).mapped("code") + ) + raise wrapJsonException( + NotFound(_("Payment method must be one of %s") % codes) + ) + + return { + "payment_date": params["payment_date"], + "amount": params["amount"], + "payment_type": params["payment_type"], + "communication": params["communication"], + "invoice_ids": [(4, invoice.id, False)], + "payment_method_id": payment_method_id.id, + "journal_id": journal.id, + "partner_type": "customer", + } + + def _to_dict(self, payment): + return { + "id": payment.get_api_external_id(), + "journal": self._one_to_many_to_dict(payment.journal_id), + "invoice": self._one_to_many_to_dict(payment.invoice_ids), + "payment_date": Date.to_string(payment.payment_date), + "amount": payment.amount, + "communication": payment.communication, + } + + def _validator_create(self): + return schemas.S_PAYMENT_CREATE + + def _validator_return_create(self): + return schemas.S_PAYMENT_RETURN_GET diff --git a/easy_my_coop_api/services/schemas.py b/easy_my_coop_api/services/schemas.py index 4f19bb8..542c9f0 100644 --- a/easy_my_coop_api/services/schemas.py +++ b/easy_my_coop_api/services/schemas.py @@ -139,3 +139,22 @@ S_INVOICE_RETURN_GET = { }, "invoice_lines": S_INVOICE_LINE_RETURN_GET, } + +S_PAYMENT_RETURN_GET = { + "id": {"type": "integer", "required": True}, + "journal": S_MANY_2_ONE, + "invoice": S_MANY_2_ONE, + "payment_date": {"type": "string", "check_with": date_validator}, + "amount": {"type": "float", "required": True}, + "communication": {"type": "string", "required": True}, +} + +S_PAYMENT_CREATE = { + "journal": {"type": "integer", "required": True}, + "invoice": {"type": "integer", "required": True}, + "payment_date": {"type": "string", "check_with": date_validator}, + "amount": {"type": "float", "required": True}, + "communication": {"type": "string", "required": True}, + "payment_type": {"type": "string", "required": True}, + "payment_method": {"type": "string", "required": True}, +} diff --git a/easy_my_coop_api/tests/__init__.py b/easy_my_coop_api/tests/__init__.py index b3a4cd1..e4b1767 100644 --- a/easy_my_coop_api/tests/__init__.py +++ b/easy_my_coop_api/tests/__init__.py @@ -3,3 +3,4 @@ from . import test_registry from . import test_external_id_mixin from . import test_subscription_requests from . import test_account_invoice +from . import test_account_payment diff --git a/easy_my_coop_api/tests/common.py b/easy_my_coop_api/tests/common.py index 763b66b..a08afe0 100644 --- a/easy_my_coop_api/tests/common.py +++ b/easy_my_coop_api/tests/common.py @@ -180,6 +180,9 @@ class BaseEMCRestCase(BaseRestCase): "default_credit_account_id": cls.equity_account.id, } ) + cls.bank_journal = cls.env["account.journal"].search( + [("type", "=", "bank")], limit=1 + ) return True def _add_api_key(self, headers): diff --git a/easy_my_coop_api/tests/test_account_payment.py b/easy_my_coop_api/tests/test_account_payment.py new file mode 100644 index 0000000..d428a75 --- /dev/null +++ b/easy_my_coop_api/tests/test_account_payment.py @@ -0,0 +1,69 @@ +# Copyright 2020 Coop IT Easy SCRL fs +# Robin Keunen +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo.fields import Date + +from odoo.addons.base_rest.controllers.main import _PseudoCollection +from odoo.addons.component.core import WorkContext + +from .common import BaseEMCRestCase + + +class TestAccountPaymentController(BaseEMCRestCase): + @classmethod + def setUpClass(cls, *args, **kwargs): + super().setUpClass(*args, **kwargs) + + def setUp(self): + res = super().setUp() + collection = _PseudoCollection("emc.services", self.env) + emc_services_env = WorkContext( + model_name="rest.service.registration", collection=collection + ) + self.ap_service = emc_services_env.component(usage="payment") + self.ai_service = emc_services_env.component(usage="invoice") + self.demo_request_1 = self.browse_ref( + "easy_my_coop.subscription_request_1_demo" + ) + return res + + def test_service_create(self): + self.demo_request_1.validate_subscription_request() + invoice = self.demo_request_1.capital_release_request + journal = self.bank_journal + + result = self.ap_service.create( + payment_date=Date.to_string(Date.today()), + amount=self.demo_request_1.subscription_amount, + payment_type="inbound", + payment_method="manual", + communication=invoice.reference, + invoice=invoice.get_api_external_id(), + journal=journal.get_api_external_id(), + ) + + demo_payment_dict = { + "id": result["id"], + "communication": invoice.reference, + "invoice": { + "id": invoice.get_api_external_id(), + "name": invoice.name, + }, + "amount": self.demo_request_1.subscription_amount, + "payment_date": Date.to_string(Date.today()), + "journal": { + "id": self.bank_journal.get_api_external_id(), + "name": self.bank_journal.name, + }, + } + self.assertEquals(demo_payment_dict, result) + + invoice = self.ai_service.get(invoice.get_api_external_id()) + self.assertEquals("paid", invoice["state"]) + + # def test_route_create(self): # todo + # external_id = self.capital_release.get_api_external_id() + # route = "/api/payment/%s" % external_id + # content = self.http_get_content(route) + # self.assertEquals(self.demo_payment_dict, content) From bf0faf3d58068976778601bc5bbbb4ec366d0ea6 Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Wed, 12 Aug 2020 10:25:31 +0200 Subject: [PATCH 10/10] make travis green again --- .pre-commit-config.yaml | 2 +- README.md | 4 +- easy_my_coop/README.rst | 20 +++ easy_my_coop/__manifest__.py | 4 - .../{description.rst => readme/INSTALL.rst} | 1 - easy_my_coop/static/description/icon.svg | 24 +-- easy_my_coop/static/description/index.html | 37 +++-- easy_my_coop/tests/test_base.py | 157 ++++++++++++++++++ easy_my_coop/views/menus.xml | 4 +- easy_my_coop_api/tests/test_registry.py | 1 - .../tests/test_subscription_requests.py | 11 +- easy_my_coop_be/README.rst | 1 - easy_my_coop_ch/README.rst | 11 +- easy_my_coop_ch/__manifest__.py | 3 - easy_my_coop_ch/static/description/index.html | 5 +- easy_my_coop_dividend/__manifest__.py | 5 - easy_my_coop_dividend/readme/DESCRIPTION.rst | 6 +- easy_my_coop_es/__manifest__.py | 21 +-- easy_my_coop_es/models/coop.py | 12 +- easy_my_coop_fr/README.rst | 3 +- easy_my_coop_fr/static/description/index.html | 2 +- easy_my_coop_loan/README.rst | 1 - easy_my_coop_loan_website/README.rst | 1 - easy_my_coop_taxshelter_report/README.rst | 4 +- .../static/description/index.html | 2 +- easy_my_coop_website/README.rst | 1 - easy_my_coop_website/controllers/main.py | 6 +- easy_my_coop_website/models/company.py | 12 +- .../views/res_company_view.xml | 1 - easy_my_coop_website_portal/README.rst | 1 - .../controllers/main.py | 2 + partner_age/README.rst | 3 +- partner_age/__manifest__.py | 2 +- partner_age/static/description/index.html | 2 +- theme_light/README.rst | 8 +- theme_light/static/description/index.html | 2 +- website_recaptcha_reloaded/README.rst | 2 +- website_recaptcha_reloaded/__manifest__.py | 10 -- 38 files changed, 283 insertions(+), 111 deletions(-) rename easy_my_coop/{description.rst => readme/INSTALL.rst} (99%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8156129..9fea8a4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,7 +33,7 @@ repos: - id: check-executables-have-shebangs - id: check-merge-conflict - id: check-symlinks -# - id: check-xml + - id: check-xml - id: mixed-line-ending args: ["--fix=lf"] - repo: https://github.com/pre-commit/mirrors-pylint diff --git a/README.md b/README.md index b131c49..a6a0372 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,15 @@ Available addons addon | version | summary --- | --- | --- [easy_my_coop](easy_my_coop/) | 12.0.3.0.1 | Manage your cooperative shares +[easy_my_coop_api](easy_my_coop_api/) | 12.0.0.0.1 | Open Easy My Coop to the world: RESTful API. [easy_my_coop_be](easy_my_coop_be/) | 12.0.1.2.0 | Easy My Coop Belgium Localization [easy_my_coop_ch](easy_my_coop_ch/) | 12.0.1.0.2 | Easy My Coop Switzerland localization +[easy_my_coop_es](easy_my_coop_es/) | 12.0.0.0.13 | Easy My Coop Spain [easy_my_coop_fr](easy_my_coop_fr/) | 12.0.1.0.1 | This is the french localization for the easy my coop module [easy_my_coop_loan](easy_my_coop_loan/) | 12.0.1.0.1 | This module allows to manage the bonds and subordinated loans subscription life cycle. [easy_my_coop_loan_website](easy_my_coop_loan_website/) | 12.0.1.0.1 | This module implements the subscription page for bonds and subordinated loans. [easy_my_coop_taxshelter_report](easy_my_coop_taxshelter_report/) | 12.0.1.0.1 | This module allows you to create a fiscal declaration year and to print tax shelter declaration for each cooperator. -[easy_my_coop_website](easy_my_coop_website/) | 12.0.1.0.0 | This module adds the cooperator subscription form allowing to subscribe for shares online. +[easy_my_coop_website](easy_my_coop_website/) | 12.0.1.0.3 | This module adds the cooperator subscription form allowing to subscribe for shares online. [easy_my_coop_website_portal](easy_my_coop_website_portal/) | 12.0.1.0.0 | Show cooperator information in the website portal. [partner_age](partner_age/) | 12.0.2.0.0 | This module computes the age of the partner. [theme_light](theme_light/) | 12.0.1.0.0 | extract of the theme zen diff --git a/easy_my_coop/README.rst b/easy_my_coop/README.rst index 1cfbefa..4cca8dc 100644 --- a/easy_my_coop/README.rst +++ b/easy_my_coop/README.rst @@ -32,6 +32,26 @@ Please don't hesitate to suggest one of your modules to this project. .. contents:: :local: +Installation +============ + +## Deploying with pip + +We used [odoo setup tools](https://pypi.org/project/setuptools-odoo/#packaging-a-single-addon) to generate the pypi files from the odoo manifests. To deploy any packaged module, so that odoo can later install them, +you can create a venv with this name (it's git-ignored) +```shell +python -m venv venv +``` +And then pip-install them [from pypi](https://pypi.org/user/coopdevs/). + +### Example + +For instance, for the addon `easy_my_coop_website_portal` +```shell +pip install odoo12-addon-easy-my-coop-website-portal==12.0.1.0.0.99.dev9 +``` +Beware that for word separation, pypi uses dashes `-` and odoo underscores `_`. + Bug Tracker =========== diff --git a/easy_my_coop/__manifest__.py b/easy_my_coop/__manifest__.py index f53712b..2a91490 100644 --- a/easy_my_coop/__manifest__.py +++ b/easy_my_coop/__manifest__.py @@ -25,10 +25,6 @@ "category": "Cooperative management", "website": "https://www.coopiteasy.be", "license": "AGPL-3", - "description": """ - This module allows to manage the cooperator subscription and all the - cooperative business processes. - """, "data": [ "data/easy_my_coop_data.xml", "data/paperformat.xml", diff --git a/easy_my_coop/description.rst b/easy_my_coop/readme/INSTALL.rst similarity index 99% rename from easy_my_coop/description.rst rename to easy_my_coop/readme/INSTALL.rst index 33db7e8..5482873 100644 --- a/easy_my_coop/description.rst +++ b/easy_my_coop/readme/INSTALL.rst @@ -14,4 +14,3 @@ For instance, for the addon `easy_my_coop_website_portal` pip install odoo12-addon-easy-my-coop-website-portal==12.0.1.0.0.99.dev9 ``` Beware that for word separation, pypi uses dashes `-` and odoo underscores `_`. - diff --git a/easy_my_coop/static/description/icon.svg b/easy_my_coop/static/description/icon.svg index 2c59dc5..9cb20ae 100644 --- a/easy_my_coop/static/description/icon.svg +++ b/easy_my_coop/static/description/icon.svg @@ -11,23 +11,23 @@ - - + + - - - - - - - - - + + + + + + + + +