From 58fc98a4c60d8760f2e1b2a78a392ce4754f5b63 Mon Sep 17 00:00:00 2001 From: Avery Kushner Date: Wed, 24 Jul 2024 09:46:07 -0400 Subject: [PATCH 1/3] Pass theme to create application form request --- unit/api/applicationForm_resource.py | 2 +- unit/models/applicationForm.py | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/unit/api/applicationForm_resource.py b/unit/api/applicationForm_resource.py index 1a54f1c0..d22cbdc5 100644 --- a/unit/api/applicationForm_resource.py +++ b/unit/api/applicationForm_resource.py @@ -12,7 +12,7 @@ def create(self, request: CreateApplicationFormRequest) -> Union[UnitResponse[Ap payload = request.to_json_api() response = super().post( self.resource, - payload, + data=payload, headers={ "X-Accept-Version": "V2024_06" } diff --git a/unit/models/applicationForm.py b/unit/models/applicationForm.py index 99708e7a..2eb75407 100644 --- a/unit/models/applicationForm.py +++ b/unit/models/applicationForm.py @@ -55,18 +55,24 @@ def from_json_api(_id, _type, attributes, relationships): class CreateApplicationFormRequest(UnitRequest): - def __init__(self, tags: Optional[Dict[str, str]] = None, - application_details: Optional[ApplicationFormPrefill] = None, - allowed_application_types: [AllowedApplicationTypes] = None): + def __init__( + self, + relationships: [Dict[str, Relationship]], + tags: Optional[Dict[str, str]] = None, + application_details: Optional[ApplicationFormPrefill] = None, + allowed_application_types: [AllowedApplicationTypes] = None + ): self.tags = tags self.application_details = application_details self.allowed_application_types = allowed_application_types + self.relationships = relationships def to_json_api(self) -> Dict: payload = { "data": { "type": "applicationForm", - "attributes": {} + "attributes": {}, + "relationships": self.relationships, } } From 6ae05cd687e566958667105a96ecdd0ded530cef Mon Sep 17 00:00:00 2001 From: Avery Kushner Date: Wed, 24 Jul 2024 16:49:37 -0400 Subject: [PATCH 2/3] Adds support for v2 application form --- unit/api/applicationForm_resource.py | 4 +- unit/api/base_resource.py | 3 +- unit/models/applicationForm.py | 58 +++++++++++++++++++++++++++- unit/models/codecs.py | 27 +++++++------ 4 files changed, 75 insertions(+), 17 deletions(-) diff --git a/unit/api/applicationForm_resource.py b/unit/api/applicationForm_resource.py index d22cbdc5..7ab0b893 100644 --- a/unit/api/applicationForm_resource.py +++ b/unit/api/applicationForm_resource.py @@ -8,7 +8,7 @@ def __init__(self, api_url, token): super().__init__(api_url, token) self.resource = "application-forms" - def create(self, request: CreateApplicationFormRequest) -> Union[UnitResponse[ApplicationFormDTO], UnitError]: + def create(self, request: CreateApplicationFormRequest) -> Union[UnitResponse[ApplicationFormV2DTO], UnitError]: payload = request.to_json_api() response = super().post( self.resource, @@ -19,7 +19,7 @@ def create(self, request: CreateApplicationFormRequest) -> Union[UnitResponse[Ap ) if super().is_20x(response.status_code): data = response.json().get("data") - return UnitResponse[ApplicationFormDTO](DtoDecoder.decode(data), None) + return UnitResponse[ApplicationFormV2DTO](DtoDecoder.decode(data), None) else: return UnitError.from_json_api(response.json()) diff --git a/unit/api/base_resource.py b/unit/api/base_resource.py index 2cab48ef..08a98b64 100644 --- a/unit/api/base_resource.py +++ b/unit/api/base_resource.py @@ -40,5 +40,4 @@ def __merge_headers(self, headers: Optional[Dict[str, str]] = None): return merged def is_20x(self, status: int): - return status == 200 or status == 201 or status == 204 - + return status == 200 or status == 201 or status == 204 \ No newline at end of file diff --git a/unit/models/applicationForm.py b/unit/models/applicationForm.py index 2eb75407..049ec032 100644 --- a/unit/models/applicationForm.py +++ b/unit/models/applicationForm.py @@ -37,6 +37,58 @@ def __init__(self, application_type: Optional[str], full_name: Optional[FullName self.phone = phone +class ApplicationLink(object): + def __init__( + self, + type, + href, + ): + self.type = type + self.href = type + + +class ApplicationFormV2DTO(object): + def __init__( + self, + id, + created_at: datetime, + updated_at: datetime, + tags: Optional[Dict[str, str]], + token: str, + expiration: datetime, + relationships: Optional[Dict[str, Relationship]], + url: str + ): + self.type = "applicationFormV2" + self.id = id + self.attributes = { + "created_at": created_at, + "updated_at": updated_at, + "tags": tags, + "token": token, + "expiration": expiration, + } + self.relationships = relationships + self.url = url + + @staticmethod + def from_json_api( + _id, + attributes, + relationships, + links, + ): + return ApplicationFormV2DTO( + id=_id, + created_at=attributes["createdAt"], + updated_at=attributes["updatedAt"], + tags=attributes["tags"], + token=attributes["applicationFormToken"]["token"], + expiration=attributes["applicationFormToken"]["expiration"], + relationships=relationships, + url=links["related"]["href"], + ) + class ApplicationFormDTO(object): def __init__(self, id: str, url: str, stage: ApplicationFormStage, applicant_details: ApplicationFormPrefill, tags: Optional[Dict[str, str]], relationships: Optional[Dict[str, Relationship]]): @@ -58,10 +110,12 @@ class CreateApplicationFormRequest(UnitRequest): def __init__( self, relationships: [Dict[str, Relationship]], + idempotency_key: str = None, tags: Optional[Dict[str, str]] = None, application_details: Optional[ApplicationFormPrefill] = None, allowed_application_types: [AllowedApplicationTypes] = None ): + self.idempotency_key = idempotency_key self.tags = tags self.application_details = application_details self.allowed_application_types = allowed_application_types @@ -71,7 +125,9 @@ def to_json_api(self) -> Dict: payload = { "data": { "type": "applicationForm", - "attributes": {}, + "attributes": { + "idempotencyKey": self.idempotency_key + }, "relationships": self.relationships, } } diff --git a/unit/models/codecs.py b/unit/models/codecs.py index 4674ea34..350315c1 100644 --- a/unit/models/codecs.py +++ b/unit/models/codecs.py @@ -1,20 +1,14 @@ -import json -from unit.models import * -from datetime import datetime, date - from unit.models.batch_release import BatchReleaseDTO from unit.models.check_payment import CheckPaymentDTO from unit.models.reward import RewardDTO -from unit.utils import date_utils -from unit.models.applicationForm import ApplicationFormDTO +from unit.models.applicationForm import ApplicationFormDTO, ApplicationFormV2DTO from unit.models.application import IndividualApplicationDTO, BusinessApplicationDTO, ApplicationDocumentDTO from unit.models.account import DepositAccountDTO, AccountLimitsDTO from unit.models.customer import IndividualCustomerDTO, BusinessCustomerDTO from unit.models.card import IndividualDebitCardDTO, BusinessDebitCardDTO, IndividualVirtualDebitCardDTO,\ BusinessVirtualDebitCardDTO, PinStatusDTO, CardLimitsDTO from unit.models.transaction import * -from unit.models.payment import AchPaymentDTO, BookPaymentDTO, WirePaymentDTO, AchReceivedPaymentDTO, BillPaymentDTO, \ - SimulateIncomingAchPaymentDTO +from unit.models.payment import AchPaymentDTO, BookPaymentDTO, WirePaymentDTO, AchReceivedPaymentDTO, BillPaymentDTO from unit.models.customerToken import CustomerTokenDTO, CustomerVerificationTokenDTO from unit.models.fee import FeeDTO from unit.models.event import * @@ -214,6 +208,9 @@ "applicationForm": lambda _id, _type, attributes, relationships: ApplicationFormDTO.from_json_api(_id, _type, attributes, relationships), + "applicationFormV2": lambda _id, _type, attributes, relationships, links: + ApplicationFormV2DTO.from_json_api(_id, attributes, relationships, links), + "fee": lambda _id, _type, attributes, relationships: FeeDTO.from_json_api(_id, _type, attributes, relationships), @@ -361,6 +358,10 @@ def split_json_api_single_response(payload: Dict): _id, _type, attributes = payload.get("id"), payload["type"], payload["attributes"] relationships = None + links = None + + if payload.get("links"): + links = payload.get("links") if payload.get("relationships"): relationships = dict() @@ -371,7 +372,7 @@ def split_json_api_single_response(payload: Dict): else: relationships[k] = Relationship(v["data"]["type"], v["data"]["id"]) - return _id, _type, attributes, relationships + return _id, _type, attributes, relationships, links def split_json_api_array_response(payload): @@ -391,8 +392,10 @@ def decode_limits(attributes: Dict): else: return CardLimitsDTO.from_json_api(attributes) -def mapping_wraper(_id, _type, attributes, relationships): +def mapping_wraper(_id, _type, attributes, relationships, links): if _type in mappings: + if links: + return mappings[_type](_id, _type, attributes, relationships, links) return mappings[_type](_id, _type, attributes, relationships) else: return RawUnitObject(_id, _type, attributes, relationships) @@ -411,8 +414,8 @@ def decode(payload): return response else: - _id, _type, attributes, relationships = split_json_api_single_response(payload) - return mapping_wraper(_id, _type, attributes, relationships) + _id, _type, attributes, relationships, links = split_json_api_single_response(payload) + return mapping_wraper(_id, _type, attributes, relationships, links) class UnitEncoder(json.JSONEncoder): def default(self, obj): From 3fee69af2c49e7460b7612daa0aa9d97f281dba7 Mon Sep 17 00:00:00 2001 From: Avery Kushner Date: Thu, 25 Jul 2024 09:53:16 -0400 Subject: [PATCH 3/3] DTO Updates --- unit/api/applicationForm_resource.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unit/api/applicationForm_resource.py b/unit/api/applicationForm_resource.py index 7ab0b893..1f86745e 100644 --- a/unit/api/applicationForm_resource.py +++ b/unit/api/applicationForm_resource.py @@ -23,12 +23,12 @@ def create(self, request: CreateApplicationFormRequest) -> Union[UnitResponse[Ap else: return UnitError.from_json_api(response.json()) - def get(self, application_form_id: str, include: Optional[str] = "") -> Union[UnitResponse[ApplicationFormDTO], UnitError]: + def get(self, application_form_id: str, include: Optional[str] = "") -> Union[UnitResponse[ApplicationFormV2DTO], UnitError]: response = super().get(f"{self.resource}/{application_form_id}", {"include": include}) if super().is_20x(response.status_code): data = response.json().get("data") included = response.json().get("included") - return UnitResponse[ApplicationFormDTO](DtoDecoder.decode(data), DtoDecoder.decode(included)) + return UnitResponse[ApplicationFormV2DTO](DtoDecoder.decode(data), DtoDecoder.decode(included)) else: return UnitError.from_json_api(response.json())