diff --git a/account_statement_import_online_gocardless/models/online_bank_statement_provider.py b/account_statement_import_online_gocardless/models/online_bank_statement_provider.py index dfdb9724f2..a3fc2559d6 100644 --- a/account_statement_import_online_gocardless/models/online_bank_statement_provider.py +++ b/account_statement_import_online_gocardless/models/online_bank_statement_provider.py @@ -190,6 +190,36 @@ def action_check_gocardless_agreement(self): # JS code expects here to return a plain link or nothing return requisition_data["link"] + def _gocardless_request_requisition(self): + response = requests.get( + f"{GOCARDLESS_ENDPOINT}/requisitions/{self.gocardless_requisition_id}/", + headers=self._gocardless_get_headers(), + timeout=REQUESTS_TIMEOUT, + ) + if response.status_code == 200: + return json.loads(response.text) + return {} + + def _gocardless_request_account(self, account_id): + response = requests.get( + f"{GOCARDLESS_ENDPOINT}/accounts/{account_id}/", + headers=self._gocardless_get_headers(), + timeout=REQUESTS_TIMEOUT, + ) + if response.status_code == 200: + return json.loads(response.text) + return {} + + def _gocardless_request_agreement(self, agreement_id): + response = requests.get( + f"{GOCARDLESS_ENDPOINT}/agreements/enduser/" f"{agreement_id}/", + headers=self._gocardless_get_headers(), + timeout=REQUESTS_TIMEOUT, + ) + if response.status_code == 200: + return json.loads(response.text) + return {} + def _gocardless_finish_requisition(self, dry=False): """Once the requisiton to the bank institution has been made, and this is called from the controller assigned to the redirect URL, we check that the IBAN account @@ -203,39 +233,25 @@ def _gocardless_finish_requisition(self, dry=False): process, so no fail message is logged in chatter in this case. """ self.ensure_one() - requisition_response = requests.get( - f"{GOCARDLESS_ENDPOINT}/requisitions/{self.gocardless_requisition_id}/", - headers=self._gocardless_get_headers(), - timeout=REQUESTS_TIMEOUT, - ) - requisition_data = json.loads(requisition_response.text) + requisition_data = self._gocardless_request_requisition() accounts = requisition_data.get("accounts", []) found_account = False accounts_iban = [] for account_id in accounts: - account_response = requests.get( - f"{GOCARDLESS_ENDPOINT}/accounts/{account_id}/", - headers=self._gocardless_get_headers(), - timeout=REQUESTS_TIMEOUT, - ) - if account_response.status_code == 200: - account_data = json.loads(account_response.text) + account_data = self._gocardless_request_account(account_id) + if account_data: accounts_iban.append(account_data["iban"]) if ( self.journal_id.bank_account_id.sanitized_acc_number - == account_data["iban"] + == account_data["iban"].upper() ): found_account = True self.gocardless_account_id = account_data["id"] break if found_account: - agreement_response = requests.get( - f"{GOCARDLESS_ENDPOINT}/agreements/enduser/" - f"{requisition_data['agreement']}/", - headers=self._gocardless_get_headers(), - timeout=REQUESTS_TIMEOUT, + agreement_data = self._gocardless_request_agreement( + requisition_data["agreement"] ) - agreement_data = json.loads(agreement_response.text) self.gocardless_requisition_expiration = datetime.strptime( agreement_data["accepted"], "%Y-%m-%dT%H:%M:%S.%fZ" ) + relativedelta(days=agreement_data["access_valid_for_days"]) diff --git a/account_statement_import_online_gocardless/tests/test_account_statement_import_online_gocardless.py b/account_statement_import_online_gocardless/tests/test_account_statement_import_online_gocardless.py index 6e6f504050..2b51424118 100644 --- a/account_statement_import_online_gocardless/tests/test_account_statement_import_online_gocardless.py +++ b/account_statement_import_online_gocardless/tests/test_account_statement_import_online_gocardless.py @@ -21,6 +21,14 @@ def setUpClass(cls): cls.now = fields.Datetime.now() cls.currency_eur = cls.env.ref("base.EUR") cls.currency_eur.write({"active": True}) + bank_account = cls.env["res.partner.bank"].create( + { + "acc_number": "NL77ABNA0574908765", + "partner_id": cls.env.ref("base.main_partner").id, + "company_id": cls.env.ref("base.main_company").id, + "bank_id": cls.env.ref("base.res_bank_1").id, + } + ) cls.journal = cls.env["account.journal"].create( { "name": "GoCardless Bank Test", @@ -29,6 +37,7 @@ def setUpClass(cls): "currency_id": cls.currency_eur.id, "bank_statements_source": "online", "online_bank_statement_provider": "gocardless", + "bank_account_id": bank_account.id, } ) cls.provider = cls.journal.online_bank_statement_provider_id @@ -77,6 +86,31 @@ def setUpClass(cls): _provider_class + "._gocardless_request_transactions", return_value=cls.return_value, ) + cls.request_requisition_value = { + "accounts": ["ACCOUNT-ID-1"], + "agreement": "TEST-AGREEMENT-ID", + } + cls.mock_requisition = lambda cls: mock.patch( + _provider_class + "._gocardless_request_requisition", + return_value=cls.request_requisition_value, + ) + cls.request_account_value = { + "id": "ACCOUNT-ID-1", + "iban": "nl77abna0574908765", + } + cls.mock_account = lambda cls: mock.patch( + _provider_class + "._gocardless_request_account", + return_value=cls.request_account_value, + ) + cls.request_agreement_value = { + "id": "TEST-AGREEMENT-ID", + "accepted": cls.now.strftime("%Y-%m-%dT%H:%M:%S.%fZ"), + "access_valid_for_days": 30, + } + cls.mock_agreement = lambda cls: mock.patch( + _provider_class + "._gocardless_request_agreement", + return_value=cls.request_agreement_value, + ) def test_mocked_gocardless(self): vals = { @@ -100,3 +134,8 @@ def test_mocked_gocardless(self): lines = statements.line_ids.sorted(lambda x: x.date) self.assertEqual(len(lines), 2) self.assertEqual(lines.mapped("amount"), [45.0, -15.0]) + + def test_provider_gocardless_finish_requisition(self): + with self.mock_requisition(), self.mock_account(), self.mock_agreement(): + res = self.provider._gocardless_finish_requisition(dry=True) + self.assertTrue(res, "Bank account not found!")