Skip to content

Commit fc2c45e

Browse files
authored
feat(pay_later): add loan precalculation endpoint (#2)
feat(pay_later): add loan precalculation endpoint
1 parent 6d3881a commit fc2c45e

15 files changed

+607
-127
lines changed

tatrapayplus/client.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
trim_and_remove_special_characters,
2626
)
2727
from tatrapayplus.models import (
28+
BasicCalculationRequest,
29+
BasicCalculationResponseItem,
2830
Field40XErrorBody,
2931
Field400ErrorBody,
3032
GetAccessTokenResponse400,
@@ -253,6 +255,21 @@ def set_appearance_logo(self, request: AppearanceLogoRequest) -> Response:
253255
self.session.headers = self.get_default_headers()
254256
return self.handle_response(self.session.post(url, json=request.to_dict()))
255257

258+
def precalculate_loan(
259+
self, request: BasicCalculationRequest, ip_address: str
260+
) -> list[BasicCalculationResponseItem]:
261+
loan_offers: list[BasicCalculationResponseItem] = []
262+
263+
url = f"{self.base_url}{Urls.LOAN_PRECALCULATION}"
264+
self.session.headers = self.get_default_headers()
265+
self.session.headers["IP-Address"] = ip_address
266+
267+
response = self.handle_response(self.session.put(url, json=request.to_dict()))
268+
for loan_item in response.json():
269+
loan_offers.append(BasicCalculationResponseItem.from_dict(loan_item))
270+
271+
return loan_offers
272+
256273
@staticmethod
257274
def generate_signed_card_id_from_cid(cid: str, public_key_content: Optional[str] = None) -> Optional[str]:
258275
if public_key_content is None:

tatrapayplus/enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class Urls:
1515
STATUS = "/status"
1616
APPEARANCES = "/v1/appearances"
1717
APPEARANCE_LOGO = APPEARANCES + "/logo"
18+
LOAN_PRECALCULATION = "/v1/payments/loans/precalculation"
1819

1920

2021
class SimpleStatus(str, Enum):

tatrapayplus/models/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
from .bank_transfer import BankTransfer
1616
from .bank_transfer_status import BankTransferStatus
1717
from .base_payment import BasePayment
18+
from .basic_calculation_request import BasicCalculationRequest
19+
from .basic_calculation_request_payment_method import BasicCalculationRequestPaymentMethod
20+
from .basic_calculation_response_item import BasicCalculationResponseItem
1821
from .capacity_info import CapacityInfo
1922
from .card_detail import CardDetail
2023
from .card_detail_card_pay_lang_override import CardDetailCardPayLangOverride
@@ -28,7 +31,6 @@
2831
from .comfort_pay import ComfortPay
2932
from .comfort_pay_status import ComfortPayStatus
3033
from .direct_transaction_data import DirectTransactionData
31-
from .direct_transaction_ipsp_data import DirectTransactionIPSPData
3234
from .direct_transaction_status import DirectTransactionStatus
3335
from .direct_transaction_task_status_response import DirectTransactionTaskStatusResponse
3436
from .direct_transaction_tds_data import DirectTransactionTDSData
@@ -62,6 +64,7 @@
6264
from .register_for_comfort_pay_obj import RegisterForComfortPayObj
6365
from .signed_card_id_obj import SignedCardIdObj
6466
from .status import Status
67+
from .transaction_ipsp_data import TransactionIPSPData
6568
from .user_data import UserData
6669

6770
__all__ = (
@@ -80,6 +83,9 @@
8083
"BankTransfer",
8184
"BankTransferStatus",
8285
"BasePayment",
86+
"BasicCalculationRequest",
87+
"BasicCalculationRequestPaymentMethod",
88+
"BasicCalculationResponseItem",
8389
"CapacityInfo",
8490
"CardDetail",
8591
"CardDetailCardPayLangOverride",
@@ -93,7 +99,6 @@
9399
"ComfortPay",
94100
"ComfortPayStatus",
95101
"DirectTransactionData",
96-
"DirectTransactionIPSPData",
97102
"DirectTransactionStatus",
98103
"DirectTransactionTaskStatusResponse",
99104
"DirectTransactionTDSData",
@@ -127,5 +132,6 @@
127132
"RegisterForComfortPayObj",
128133
"SignedCardIdObj",
129134
"Status",
135+
"TransactionIPSPData",
130136
"UserData",
131137
)

tatrapayplus/models/bank_transfer.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,25 @@ class BankTransfer:
1414
"""Bank transder attributes
1515
1616
Attributes:
17-
remittance_information_unstructured (Union[Unset, str]): Unstructured remittance information. At present,
18-
Tatrabanka bank transfer does not display the remittance information. SEPA remittanceInformationUnstructured
19-
contains 140 characters. For TatraPayPlus purposes, the first up to 40 characters are assigned to the paymentId.
20-
Others 100 characters are free to use
17+
remittance_information_unstructured (Union[Unset, str]): Unstructured transfer information. Currently,
18+
Tatrabanka bank transfer does not display the transfer information. The entire SEPA
19+
remittanceInformationUnstructured contains 140 characters. The structure of the string consists of 3 parts:
20+
21+
- A. paymentId - fixed 40 characters are reserved for paymentId
22+
- B. Merchant Name value length - provided in the contract, up to 50 characters
23+
- C. Custom value length - free characters are calculated as C = 140-A-(B+1). Depends on the length of the
24+
merchant name.
25+
26+
E.g. Merchant name = MerchantABCD,s.r.o. (19 characters + 1 separator space). 80 characters are available.
27+
28+
The result of the UnstructuredTransferInformation will look like this
29+
30+
07b940d2-8b82-4c7a-a0dd-5ebeabcf1f3d MerchantABCD,s.r.o. Your text in remittance
31+
32+
If the value of RemittanceInformationUnstructured in this attribute is longer than the calculated C, your
33+
custom value will be truncated.
34+
35+
2136
Example: Ref Number Merchant.
2237
"""
2338

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
from collections.abc import Mapping
2+
from typing import TYPE_CHECKING, Any, TypeVar, Union
3+
4+
from attrs import define as _attrs_define
5+
from attrs import field as _attrs_field
6+
7+
from ..models.basic_calculation_request_payment_method import (
8+
BasicCalculationRequestPaymentMethod,
9+
)
10+
from ..types import UNSET, Unset
11+
12+
if TYPE_CHECKING:
13+
from ..models.capacity_info import CapacityInfo
14+
15+
16+
T = TypeVar("T", bound="BasicCalculationRequest")
17+
18+
19+
@_attrs_define
20+
class BasicCalculationRequest:
21+
"""
22+
Attributes:
23+
loan_amount (float): Loan amount in EUR Example: 156.95.
24+
payment_method (Union[Unset, BasicCalculationRequestPaymentMethod]): Only if isPrecalculationAllowed = true
25+
capacity_info (Union[Unset, CapacityInfo]): Capacity posibilities of user. It is used to specify the calculation
26+
of the client's request. Based on this, the bank can make a more accurate calculation of the possibility of
27+
obtaining a loan
28+
"""
29+
30+
loan_amount: float
31+
payment_method: Union[Unset, BasicCalculationRequestPaymentMethod] = UNSET
32+
capacity_info: Union[Unset, "CapacityInfo"] = UNSET
33+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
34+
35+
def to_dict(self) -> dict[str, Any]:
36+
loan_amount = self.loan_amount
37+
38+
payment_method: Union[Unset, str] = UNSET
39+
if not isinstance(self.payment_method, Unset):
40+
payment_method = self.payment_method.value
41+
42+
capacity_info: Union[Unset, dict[str, Any]] = UNSET
43+
if not isinstance(self.capacity_info, Unset):
44+
capacity_info = self.capacity_info.to_dict()
45+
46+
field_dict: dict[str, Any] = {}
47+
field_dict.update(self.additional_properties)
48+
field_dict.update(
49+
{
50+
"loanAmount": loan_amount,
51+
}
52+
)
53+
if payment_method is not UNSET:
54+
field_dict["paymentMethod"] = payment_method
55+
if capacity_info is not UNSET:
56+
field_dict["capacityInfo"] = capacity_info
57+
58+
return field_dict
59+
60+
@classmethod
61+
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
62+
from ..models.capacity_info import CapacityInfo
63+
64+
d = dict(src_dict)
65+
loan_amount = d.pop("loanAmount")
66+
67+
_payment_method = d.pop("paymentMethod", UNSET)
68+
payment_method: Union[Unset, BasicCalculationRequestPaymentMethod]
69+
if isinstance(_payment_method, Unset):
70+
payment_method = UNSET
71+
else:
72+
payment_method = BasicCalculationRequestPaymentMethod(_payment_method)
73+
74+
_capacity_info = d.pop("capacityInfo", UNSET)
75+
capacity_info: Union[Unset, CapacityInfo]
76+
if isinstance(_capacity_info, Unset):
77+
capacity_info = UNSET
78+
else:
79+
capacity_info = CapacityInfo.from_dict(_capacity_info)
80+
81+
basic_calculation_request = cls(
82+
loan_amount=loan_amount,
83+
payment_method=payment_method,
84+
capacity_info=capacity_info,
85+
)
86+
87+
basic_calculation_request.additional_properties = d
88+
return basic_calculation_request
89+
90+
@property
91+
def additional_keys(self) -> list[str]:
92+
return list(self.additional_properties.keys())
93+
94+
def __getitem__(self, key: str) -> Any:
95+
return self.additional_properties[key]
96+
97+
def __setitem__(self, key: str, value: Any) -> None:
98+
self.additional_properties[key] = value
99+
100+
def __delitem__(self, key: str) -> None:
101+
del self.additional_properties[key]
102+
103+
def __contains__(self, key: str) -> bool:
104+
return key in self.additional_properties
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from enum import Enum
2+
3+
4+
class BasicCalculationRequestPaymentMethod(str, Enum):
5+
PAY_LATER = "PAY_LATER"
6+
7+
def __str__(self) -> str:
8+
return str(self.value)
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
from collections.abc import Mapping
2+
from typing import Any, TypeVar
3+
4+
from attrs import define as _attrs_define
5+
from attrs import field as _attrs_field
6+
7+
T = TypeVar("T", bound="BasicCalculationResponseItem")
8+
9+
10+
@_attrs_define
11+
class BasicCalculationResponseItem:
12+
"""
13+
Attributes:
14+
loan_interest_rate (float): Loan interest rate
15+
installment_amount (float): Installment amount
16+
loan_duration (int): Loan duration
17+
preference (bool): Preferred maturity of loan offer (max 3)
18+
main_preference (bool): Main preferred maturity of loan offer (max 1)
19+
capacity_validity (bool): Loan offer is valid with respect to entered capacity
20+
rpmn (float): Calculated RPMN
21+
total_amount (float): Total amount of the order including all fees, insurance, shipping,... Example: 156.95.
22+
loan_fee (float):
23+
"""
24+
25+
loan_interest_rate: float
26+
installment_amount: float
27+
loan_duration: int
28+
preference: bool
29+
main_preference: bool
30+
capacity_validity: bool
31+
rpmn: float
32+
total_amount: float
33+
loan_fee: float
34+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
35+
36+
def to_dict(self) -> dict[str, Any]:
37+
loan_interest_rate = self.loan_interest_rate
38+
39+
installment_amount = self.installment_amount
40+
41+
loan_duration = self.loan_duration
42+
43+
preference = self.preference
44+
45+
main_preference = self.main_preference
46+
47+
capacity_validity = self.capacity_validity
48+
49+
rpmn = self.rpmn
50+
51+
total_amount = self.total_amount
52+
53+
loan_fee = self.loan_fee
54+
55+
field_dict: dict[str, Any] = {}
56+
field_dict.update(self.additional_properties)
57+
field_dict.update(
58+
{
59+
"loanInterestRate": loan_interest_rate,
60+
"installmentAmount": installment_amount,
61+
"loanDuration": loan_duration,
62+
"preference": preference,
63+
"mainPreference": main_preference,
64+
"capacityValidity": capacity_validity,
65+
"rpmn": rpmn,
66+
"totalAmount": total_amount,
67+
"loanFee": loan_fee,
68+
}
69+
)
70+
71+
return field_dict
72+
73+
@classmethod
74+
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
75+
d = dict(src_dict)
76+
loan_interest_rate = d.pop("loanInterestRate")
77+
78+
installment_amount = d.pop("installmentAmount")
79+
80+
loan_duration = d.pop("loanDuration")
81+
82+
preference = d.pop("preference")
83+
84+
main_preference = d.pop("mainPreference")
85+
86+
capacity_validity = d.pop("capacityValidity")
87+
88+
rpmn = d.pop("rpmn")
89+
90+
total_amount = d.pop("totalAmount")
91+
92+
loan_fee = d.pop("loanFee")
93+
94+
basic_calculation_response_item = cls(
95+
loan_interest_rate=loan_interest_rate,
96+
installment_amount=installment_amount,
97+
loan_duration=loan_duration,
98+
preference=preference,
99+
main_preference=main_preference,
100+
capacity_validity=capacity_validity,
101+
rpmn=rpmn,
102+
total_amount=total_amount,
103+
loan_fee=loan_fee,
104+
)
105+
106+
basic_calculation_response_item.additional_properties = d
107+
return basic_calculation_response_item
108+
109+
@property
110+
def additional_keys(self) -> list[str]:
111+
return list(self.additional_properties.keys())
112+
113+
def __getitem__(self, key: str) -> Any:
114+
return self.additional_properties[key]
115+
116+
def __setitem__(self, key: str, value: Any) -> None:
117+
self.additional_properties[key] = value
118+
119+
def __delitem__(self, key: str) -> None:
120+
del self.additional_properties[key]
121+
122+
def __contains__(self, key: str) -> bool:
123+
return key in self.additional_properties

0 commit comments

Comments
 (0)