From 19c7ee35ec4ddab2d79f4628373d9397a0a4c298 Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Wed, 12 Aug 2020 09:34:12 +0200 Subject: [PATCH] [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)