diff --git a/app/api/routes/routes.py b/app/api/routes/routes.py index 767a86a..92a5cff 100644 --- a/app/api/routes/routes.py +++ b/app/api/routes/routes.py @@ -10,8 +10,9 @@ from app.api.services import ( TokenValidationService, LienCheckService, NewTransactionCheckService, - RepaymentService, # Added RepaymentService - StatusCallService, # Added StatusCallService + RepaymentService, + StatusCallService, + LoanStatusService ) from app.utils.logger import logger from app.api.middlewares import require_api_key, require_app_id, enforce_json @@ -59,6 +60,16 @@ def disbursement(): response = DisbursementService.process_request(data) return response +# LoanStatus Endpoint +@api.route('/LoanStatus', methods=['POST']) +@require_api_key +@require_app_id +def loan_status(): + data = request.get_json() + # logger.info(f"LoanStatus request received: {data}") + response = LoanStatusService.process_request(data) + return response + # CollectLoan Endpoint @api.route('/CollectLoan', methods=['POST']) @require_api_key diff --git a/app/api/schemas/bulk_sms.py b/app/api/schemas/bulk_sms.py new file mode 100644 index 0000000..5ab32e6 --- /dev/null +++ b/app/api/schemas/bulk_sms.py @@ -0,0 +1,18 @@ +from marshmallow import Schema, fields + +# Individual SMS item schema for BulkSMS +class BulkSMSItemSchema(Schema): + text = fields.Str(required=True, description="Message to send to customer") + dest = fields.Str(required=True, description="Phone Number in international format") + unicode = fields.Bool(required=True, description="Character encoding standard (set as True for bulk SMS)") + +# BulkSMS Request Schema (list of SMS items) +class BulkSMSSchema(Schema): + _schema = fields.List(fields.Nested(BulkSMSItemSchema), required=True) + +# BulkSMS Response Schema +class BulkSMSResponseSchema(Schema): + data = fields.Str(required=True, description="Any additional data in response") + statusCode = fields.Int(required=True, description="Result code of executed process (200 = Success)") + IsSuccessful = fields.Bool(required=True, description="An Indicator that the process was successful or not") + errorMessage = fields.Str(required=True, allow_none=True, description="Description of status code if process is failed, null if successful") \ No newline at end of file diff --git a/app/api/schemas/collect_loan.py b/app/api/schemas/collect_loan.py index fb5bc76..07ccadc 100644 --- a/app/api/schemas/collect_loan.py +++ b/app/api/schemas/collect_loan.py @@ -1,16 +1,32 @@ -from marshmallow import Schema, fields +from marshmallow import Schema, fields, validate -# Collect Loan Schema +# CollectLoan Request Schema class CollectLoanSchema(Schema): - transactionId = fields.Str(required=True) - fbnTransactionId = fields.Str(required=True) - debtId = fields.Str(required=True) - customerId = fields.Str(required=True) - accountId = fields.Str(required=True) - productId = fields.Str(required=True) - collectAmount = fields.Float(required=True) - penalCharge = fields.Float(required=False) # Optional - collectionMethod = fields.Int(required=True) - lienAmount = fields.Float(required=True) - countryId = fields.Str(required=True) - comment = fields.Str(required=False) # Optional \ No newline at end of file + transactionId = fields.Str(required=True, description="Unique identifier of transaction in Simbrella system") + fbnTransactionId = fields.Str(required=True, description="Unique id of the transaction received from FBN in Eligibility or Provision requests") + debtId = fields.Str(required=True, description="Unique identifier of a loan in Simbrella system that is going to be collected (it correlates with provision request)") + customerId = fields.Str(required=True, description="Unique identifier of a user") + accountId = fields.Str(required=True, description="Specific identifier of a user's account") + productId = fields.Str(required=True, description="Identifier of a product for which collection to be made") + collectAmount = fields.Float(required=True, description="Amount to be collected from user's account (penalCharge is not included)") + penalCharge = fields.Float(required=False, description="Amount of penalty to be collected from user's account. If there is no penalty, amount is '0'") + collectionMethod = fields.Int(required=True, description="1 - on deposit of salary; 2 - on due date; 3 - initiated by user", + validate=validate.OneOf([1, 2, 3])) + lienAmount = fields.Float(required=True, description="Aggregated (summed up) lien amount") + countryId = fields.Str(required=True, description="Set to static value '01'") + comment = fields.Str(required=False, description="Any additional comment for provided loan operation") + +# CollectLoan Response Schema +class CollectLoanResponseSchema(Schema): + transactionId = fields.Str(required=True, description="Unique identifier of transaction in Simbrella system") + debtId = fields.Str(required=True, description="Unique identifier of a loan in Simbrella system that is going to be collected (it correlates with provision request)") + customerId = fields.Str(required=True, description="Unique identifier of a user") + accountId = fields.Str(required=True, description="Specific identifier of a user's account") + productId = fields.Str(required=True, description="Identifier of a product for which collection to be made") + collectAmount = fields.Float(required=True, description="Amount collected from user's account (penalCharge is not included)") + penalCharge = fields.Float(required=True, description="Amount of penalty collected from user's account. If there is no penalty, amount is '0'") + lienAmount = fields.Float(required=True, description="Aggregated (summed up) lien amount") + countryId = fields.Str(required=False, description="Set to static value '01'") + comment = fields.Str(required=False, description="Any additional comment for provided loan operation") + resultCode = fields.Str(required=True, description="Result code of executed transaction, e.g. (00 – Success etc.) see result codes table") + resultDescription = fields.Str(required=True, description="Description of provided result code") \ No newline at end of file diff --git a/app/api/schemas/lien_check.py b/app/api/schemas/lien_check.py index 7a0912a..41e74e0 100644 --- a/app/api/schemas/lien_check.py +++ b/app/api/schemas/lien_check.py @@ -1,8 +1,13 @@ from marshmallow import Schema, fields -# Lien Check Schema +# LienCheck Request Schema class LienCheckSchema(Schema): - transactionId = fields.Str(required=True) - customerId = fields.Str(required=True) - accountId = fields.Str(required=True) - countryId = fields.Str(required=True) \ No newline at end of file + transactionId = fields.Str(required=True, description="Unique Identifier in Simbrella system") + customerId = fields.Str(required=True, description="Unique identifier of customer") + accountId = fields.Str(required=True, description="Unique identifier of account") + +# LienCheck Response Schema +class LienCheckResponseSchema(Schema): + lienAmount = fields.Float(required=True, description="Lien amount applied to the account") + resultCode = fields.Str(required=True, description="Result code of response") + resultDescription = fields.Str(required=True, description="Response description") \ No newline at end of file diff --git a/app/api/schemas/loan_status.py b/app/api/schemas/loan_status.py new file mode 100644 index 0000000..2a144bf --- /dev/null +++ b/app/api/schemas/loan_status.py @@ -0,0 +1,29 @@ +from marshmallow import Schema, fields, validate + +# Schema for the loan item in the response +class LoanItemSchema(Schema): + debtId = fields.Str(required=True, description="Unique identifier of a debt of a user") + loanDate = fields.Str(required=True, description="Date and time of provided loan") + dueDate = fields.Str(required=True, description="Due date of provided loan") + currentLoanAmount = fields.Float(required=True, description="Outstanding debt amount of the user") + initialLoanAmount = fields.Float(required=True, description="Initial loan amount") + defaultPenaltyFee = fields.Float(required=True, description="Penalty fee amount") + continuousFee = fields.Float(required=True, description="Interest fee charged continuously. First occurs when payment is delayed") + productId = fields.Str(required=True, description="Identifier of a provided product to a user") + +# LoanStatus Request Schema +class LoanStatusSchema(Schema): + transactionId = fields.Str(required=True, description="Unique identifier of transaction. This transaction Id must be consistent across all platforms") + customerId = fields.Str(required=True, description="Unique identifier of a customer") + msisdn = fields.Str(required=False, description="User's mobile number in an international format") + channel = fields.Str(required=True, description="Request channel: USSD, MobileApp, or Web", + validate=validate.OneOf(["USSD", "MobileApp", "Web", "100", "101", "102", "103"])) # Added numeric channel codes + +# LoanStatus Response Schema +class LoanStatusResponseSchema(Schema): + customerId = fields.Str(required=True, description="Unique identifier of a user") + transactionId = fields.Str(required=True, description="Unique identifier of transaction. This transaction Id must be consistent across all platforms") + loans = fields.List(fields.Nested(LoanItemSchema), required=True, description="Array of loan entities. If customer doesn't have a loan, this array will be empty") + totalDebtAmount = fields.Float(required=False, description="Sum amount of all existing debts of a user") + resultCode = fields.Str(required=True, description="Result code of executed transaction, e.g. (00 – Success etc.) see result codes table") + resultDescription = fields.Str(required=True, description="Description of provided result code") \ No newline at end of file diff --git a/app/api/schemas/penal_charge.py b/app/api/schemas/penal_charge.py index 40d6d0a..2f0cb8f 100644 --- a/app/api/schemas/penal_charge.py +++ b/app/api/schemas/penal_charge.py @@ -1,14 +1,17 @@ from marshmallow import Schema, fields - -# Penal Charge Schema +# PenalCharge Request Schema class PenalChargeSchema(Schema): - transactionId = fields.Str(required=True) - fbnTransactionId = fields.Str(required=True) - debtId = fields.Str(required=True) - customerId = fields.Str(required=True) - accountId = fields.Str(required=True) - penalCharge = fields.Decimal(required=True) - lienAmount = fields.Decimal(required=True) - countryId = fields.Str(required=True) - comment = fields.Str(required=False) + transactionId = fields.Str(required=True, description="Unique identifier of transaction in Simbrella system") + fbnTransactionId = fields.Str(required=True, description="Unique id of the transaction received from FBN in Eligibility or Provision requests") + debtId = fields.Str(required=True, description="Unique identifier of providing loan in Simbrella system") + customerId = fields.Str(required=True, description="Unique identifier of a user") + accountId = fields.Str(required=True, description="Specific identifier of a user's account") + penalCharge = fields.Float(required=True, description="Penalty amount that needs to be collected from user's account") + lienAmount = fields.Float(required=True, description="Aggregated (summed up) lien amount") + comment = fields.Str(required=False, description="Any additional comment for provided loan operation") + +# PenalCharge Response Schema +class PenalChargeResponseSchema(Schema): + resultCode = fields.Str(required=True, description="Result code of executed transaction, e.g. (00 – Success etc.) see result codes table") + resultDescription = fields.Str(required=True, description="Description of provided result code") \ No newline at end of file diff --git a/app/api/schemas/provide_loan.py b/app/api/schemas/provide_loan.py new file mode 100644 index 0000000..e808b6a --- /dev/null +++ b/app/api/schemas/provide_loan.py @@ -0,0 +1,26 @@ +from marshmallow import Schema, fields, validate + +# ProvideLoan Request Schema +class ProvideLoanSchema(Schema): + requestId = fields.Str(required=False, description="Unique identifier of request") + transactionId = fields.Str(required=True, description="Unique identifier of transaction. This transaction Id must be consistent across all platforms") + customerId = fields.Str(required=True, description="Unique identifier of a customer") + accountId = fields.Str(required=True, description="Specific identifier of a user's account") + msisdn = fields.Str(required=False, description="User's mobile number in an international format") + productId = fields.Str(required=True, description="Identifier of a product chosen by user") + requestedAmount = fields.Float(required=True, description="Amount of loan that requested by user") + collectionType = fields.Int(required=True, description="Type of collection that user is preferred. 0 – as soon as salary inflow occurs; 1- as soon as any new inflow occurs, 1 – collection after XX days.", + validate=validate.OneOf([0, 1])) + offerId = fields.Int(required=True, description="Offer ID of the loan selected by Customer") + channel = fields.Str(required=True, description="Request channel: 'USSD' or 'MobileApp' or 'Web' - Reference Channel types", + validate=validate.OneOf(["USSD", "MobileApp", "Web", "100", "101", "102", "103"])) # Added numeric channel codes + +# ProvideLoan Response Schema +class ProvideLoanResponseSchema(Schema): + requestId = fields.Str(required=True, description="Unique identifier of request") + transactionId = fields.Str(required=True, description="Unique identifier of transaction. This transaction Id must be consistent across all platforms") + customerId = fields.Str(required=True, description="Unique identifier of a customer") + accountId = fields.Str(required=True, description="Specific identifier of a user's account") + msisdn = fields.Str(required=False, description="User's mobile number in an international format") + resultCode = fields.Str(required=True, description="Result code of executed transaction, e.g. (00 – Success etc.) see result codes table") + resultDescription = fields.Str(required=True, description="Description of provided result code") \ No newline at end of file diff --git a/app/api/schemas/rac_check.py b/app/api/schemas/rac_check.py index 3b858d2..894dd18 100644 --- a/app/api/schemas/rac_check.py +++ b/app/api/schemas/rac_check.py @@ -1,23 +1,32 @@ from marshmallow import Schema, fields -class RACItemSchema(Schema): - salaryAccount = fields.Bool(required=True) - bvn = fields.Str(required=True) - crc = fields.Bool(required=True) - crms = fields.Bool(required=True) - accountStatus = fields.Str(required=True) - lien = fields.Bool(required=True) - noBouncedCheck = fields.Bool(required=True) - existingLoan = fields.Bool(required=True) - whitelist = fields.Bool(required=True) - noPastDueSalaryLoan = fields.Bool(required=True) - noPastDueOtherLoans = fields.Bool(required=True) +# RACResponse Schema +class RACResponseSchema(Schema): + Salary_account = fields.Str(data_key="Salary account", required=True, description="Has Salary account or Not (1 = Yes, 0 = No)") + BVN = fields.Str(required=False, description="BVN Ok (1 = Yes, 0 = No)") + BVNAttachedToAccount = fields.Str(required=True, description="BVN attached to account (1 = Yes, 0 = No)") + CRMS = fields.Str(required=True, description="No Delinquent loan in CRMS (1 = Yes, 0 = No)") + CRC = fields.Str(required=True, description="No Delinquent loan in CRC (1 = Yes, 0 = No)") + AccountStatus = fields.Str(required=True, description="Has 'Regular' account status (1 = Yes, 0 = No)") + Lien = fields.Str(required=True, description="No Lien on account (1 = Yes, 0 = No)") + NoBouncedCheck = fields.Str(required=True, description="No Bounced Check (1 = Yes, 0 = No)") + Whitelist = fields.Str(required=True, description="Not blacklisted (1 = Yes, 0 = No)") + NoPastDueSalaryLoan = fields.Str(required=True, description="No Past Due Salary Loan (1 = Yes, 0 = No)") + NoPastDueOtherLoan = fields.Str(required=True, description="No Past Due Other Loans (1 = Yes, 0 = No)") - -# RAC Check Schema +# RACCheck Request Schema class RACCheckSchema(Schema): - transactionId = fields.Str(required=True) - fbnTransactionId = fields.Str(required=True) - customerId = fields.Str(required=True) - accountId = fields.Str(required=True) - RAC_Array = fields.List(fields.Nested(RACItemSchema), required=True) \ No newline at end of file + transactionId = fields.Str(required=True, description="Unique identifier of transaction. This transaction Id must be consistent across all platforms") + fbnTransactionId = fields.Str(required=True, description="Unique id of the transaction received from FBN in Eligibility or Provision requests") + customerId = fields.Str(required=True, description="Unique identifier of a user") + accountId = fields.Str(required=True, description="Specific identifier of a user's account") + RAC_Array = fields.List(fields.Str(), required=True, description="Array of RAC items to check (BVN, CRC, CRMS, Salary account, lien, whitelist, lien, account status, no bounced check and existing loan)") + +# RACCheck Response Schema +class RACCheckResponseSchema(Schema): + transactionId = fields.Str(required=True, description="Unique identifier of transaction in Simbrella system") + customerId = fields.Str(required=True, description="Unique identifier of a user") + accountId = fields.Str(required=True, description="Specific identifier of a user's account") + RACResponse = fields.Nested(RACResponseSchema, required=True, description="Object containing binary responses for each RAC check") + resultCode = fields.Str(required=False, description="Result code of executed transaction") + resultDescription = fields.Str(required=True, description="Description of provided result code") \ No newline at end of file diff --git a/app/api/schemas/repayment.py b/app/api/schemas/repayment.py new file mode 100644 index 0000000..8099d0d --- /dev/null +++ b/app/api/schemas/repayment.py @@ -0,0 +1,33 @@ +from marshmallow import Schema, fields, validate + +# Repayment Request Schema +class RepaymentSchema(Schema): + requestId = fields.Str(required=True, description="Unique identifier of request") + countryCode = fields.Str(required=True, description="Unique country code. Please refer to Country Codes table") + transactionId = fields.Str(required=True, description="Unique identifier of transaction in Simbrella system") + debtId = fields.Str(required=True, description="Unique identifier of a loan in Simbrella system that is going to be collected (it correlates with provision request)") + customerId = fields.Str(required=True, description="Unique identifier of a user") + accountId = fields.Str(required=True, description="Specific identifier of a user's account") + productId = fields.Str(required=True, description="Identifier of a product for which collection to be made") + collectedAmount = fields.Float(required=True, description="Amount to be collected from user's account (penalCharge is not included)") + penalCharge = fields.Float(required=False, description="Amount of penalty to be collected from user's account. If there is no penalty, amount is '0'") + collectionMethod = fields.Int(required=True, description="1 - on deposit of salary, 2 - on due date, 3 - initiated by user", + validate=validate.OneOf([1, 2, 3])) + lienAmount = fields.Float(required=True, description="Aggregated (summed up) lien amount") + comment = fields.Str(required=False, description="Any additional comment for provided loan operation") + +# Repayment Response Schema +class RepaymentResponseSchema(Schema): + requestId = fields.Str(required=True, description="Unique identifier of request") + countryCode = fields.Str(required=True, description="Unique country code. Please refer to Country Codes table") + transactionId = fields.Str(required=True, description="Unique identifier of transaction in Simbrella system") + debtId = fields.Str(required=True, description="Unique identifier of a loan in Simbrella system that is going to be collected (it correlates with provision request)") + customerId = fields.Str(required=True, description="Unique identifier of a user") + accountId = fields.Str(required=True, description="Specific identifier of a user's account") + productId = fields.Str(required=True, description="Identifier of a product for which collection to be made") + collectedAmount = fields.Float(required=True, description="Amount to be collected from user's account (penalCharge is not included)") + penalCharge = fields.Float(required=False, description="Amount of penalty to be collected from user's account. If there is no penalty, amount is '0'") + lienAmount = fields.Float(required=True, description="Aggregated (summed up) lien amount") + comment = fields.Str(required=False, description="Any additional comment for provided loan operation") + resultCode = fields.Str(required=True, description="Result code of executed transaction, e.g. (00 – Success etc.) see result codes table") + resultDescription = fields.Str(required=True, description="Description of provided result code") \ No newline at end of file diff --git a/app/api/schemas/sms.py b/app/api/schemas/sms.py new file mode 100644 index 0000000..8f1013d --- /dev/null +++ b/app/api/schemas/sms.py @@ -0,0 +1,14 @@ +from marshmallow import Schema, fields + +# SMS Request Schema +class SMSSchema(Schema): + text = fields.Str(required=True, description="Message to send to customer") + dest = fields.Str(required=True, description="Phone Number in international format") + unicode = fields.Bool(required=True, description="Character encoding standard (set as False for single SMS)") + +# SMS Response Schema +class SMSResponseSchema(Schema): + data = fields.Str(required=True, description="Any additional data in response") + statusCode = fields.Int(required=True, description="Result code of executed process (200 = Success)") + IsSuccessful = fields.Bool(required=True, description="An Indicator that the process was successful or not") + errorMessage = fields.Str(required=True, allow_none=True, description="Description of status code if process is failed, null if successful") \ No newline at end of file diff --git a/app/api/schemas/status_call.py b/app/api/schemas/status_call.py new file mode 100644 index 0000000..9bf0e09 --- /dev/null +++ b/app/api/schemas/status_call.py @@ -0,0 +1,27 @@ +from marshmallow import Schema, fields, validate + +# Nested data schema for StatusCallResponse +class StatusCallDataSchema(Schema): + transactionId = fields.Str(required=True, description="Unique identifier of transaction in Simbrella system that was sent for transaction check") + providedAmount = fields.Float(required=True, description="Amount collected from user's account within disbursement operation. Amount should always be equal to zero if operation is of any type other than Disbursement") + collectedAmount = fields.Float(required=True, description="Amount collected from user's account. In case of Disbursement this value will be equal to 0. In case of Collection this value will represent amount successfully collected from customers account. In case of Penal charge this value will represent penalty amount collected from customer's account.") + resultCode = fields.Str(required=True, description="Result code of the operation one sent for transaction check, e.g. (00 – Success etc.)") + resultDescription = fields.Str(required=True, description="Description of provided result code that was sent for transaction check") + +# StatusCall Request Schema +class StatusCallSchema(Schema): + requestId = fields.Str(required=True, description="RequestId for transaction sent by Simbrella within initial request to Firstbank API") + countryCode = fields.Str(required=True, description="Unique country code.") + transactionId = fields.Str(required=True, description="Unique identifier of transaction. This transaction Id must be consistent across all platforms") + debtId = fields.Str(required=True, description="Unique identifier of provided loan in Simbrella system") + transactionType = fields.Str(required=True, + description="Type of Transaction Simbrella is sending Transaction Check for", + validate=validate.OneOf(["Disbursement", "Collection", "PenalCharge"])) + customerId = fields.Str(required=True, description="Unique identifier of a user") + +# StatusCall Response Schema +class StatusCallResponseSchema(Schema): + transactionId = fields.Str(required=True, description="Unique identifier of request in Simbrella system") + data = fields.Nested(StatusCallDataSchema, required=True, description="Object containing details of transaction Simbrella querying") + resultCode = fields.Str(required=True, description="Result code of executed transaction, e.g. (00 – Success etc.)") + resultDescription = fields.Str(required=True, description="Description of provided result code") \ No newline at end of file diff --git a/app/api/schemas/transaction_verify.py b/app/api/schemas/transaction_verify.py index 221e2b6..ef180af 100644 --- a/app/api/schemas/transaction_verify.py +++ b/app/api/schemas/transaction_verify.py @@ -1,12 +1,27 @@ -from marshmallow import Schema, fields +from marshmallow import Schema, fields, validate - -# Transaction Verify Schema +# TransactionVerify Request Schema class TransactionVerifySchema(Schema): - counter = fields.Str(required=True) - transactionId = fields.Str(required=True) - requestID = fields.Str(required=True) - customerId = fields.Str(required=True) - accountId = fields.Str(required=True) - countryId = fields.Str(required=True) # Static value “01” - transactionType = fields.Str(required=True) \ No newline at end of file + requestId = fields.Str(required=True, description="Unique identifier of request") + countryCode = fields.Str(required=True, description="Unique country code. Please refer to Country Codes table") + counter = fields.Str(required=True, description="Unique counter for number of attempts of the API call. Original attempt is 1") + transactionId = fields.Str(required=True, description="Id of the transaction we are checking") + customerId = fields.Str(required=True, description="Unique identifier of a user") + accountId = fields.Str(required=True, description="Specific identifier of a user's account") + transactionType = fields.Str(required=True, + description="To check state of loan disbursal transaction, value must be 'Disbursement', to check state of loan collection transaction, value must be 'Collection', to check state of penalty charge transaction, value must be 'Penalty'", + validate=validate.OneOf(["Disbursement", "Collection", "Penalty"])) + +# TransactionVerify Response Schema +class TransactionVerifyResponseSchema(Schema): + requestId = fields.Str(required=True, description="Unique identifier of request") + countryCode = fields.Str(required=True, description="Unique country code. Please refer to Country Codes table") + transactionId = fields.Str(required=True, description="Unique identifier of transaction in Simbrella system") + transactionType = fields.Str(required=True, description="Type of transaction: Disbursement, Collection, or Penalty", + validate=validate.OneOf(["Disbursement", "Collection", "Penalty"])) + customerId = fields.Str(required=True, description="Unique identifier of a user") + accountId = fields.Str(required=True, description="Specific identifier of a user's account") + providedAmount = fields.Float(required=True, description="Amount provided to a user within loan provision operation") + collectedAmount = fields.Float(required=True, description="Amount collected from user's account within collection operation") + resultCode = fields.Str(required=True, description="Result code of executed transaction, e.g. (00 – Success etc.) see result codes table") + resultDescription = fields.Str(required=True, description="Description of provided result code") \ No newline at end of file diff --git a/app/api/services/__init__.py b/app/api/services/__init__.py index e58aec6..7a9d5fc 100644 --- a/app/api/services/__init__.py +++ b/app/api/services/__init__.py @@ -1,12 +1,18 @@ -from app.api.services.rac_check import RACCheckService from app.api.services.disbursement import DisbursementService from app.api.services.select_offer import SelectOfferService +from app.api.services.provide_loan import ProvideLoanService +from app.api.services.loan_status import LoanStatusService +from app.api.services.repayment import RepaymentService from app.api.services.collect_loan import CollectLoanService +from app.api.services.rac_check import RACCheckService from app.api.services.transaction_verify import TransactionVerifyService from app.api.services.penal_charge import PenalChargeService -from app.api.services.revoke_enable_consent import RevokeEnableConsentService -from app.api.services.token_validation import TokenValidationService from app.api.services.lien_check import LienCheckService -from app.api.services.new_transaction_check import NewTransactionCheckService -from app.api.services.repayment import RepaymentService -from app.api.services.status_call import StatusCallService \ No newline at end of file +from app.api.services.status_call import StatusCallService +from app.api.services.sms import SMSService +from app.api.services.bulk_sms import BulkSMSService + +# from app.api.services.revoke_enable_consent import RevokeEnableConsentService +# from app.api.services.token_validation import TokenValidationService +# from app.api.services.new_transaction_check import NewTransactionCheckService +# from app.api.services.status_call import StatusCallService \ No newline at end of file diff --git a/app/api/services/bulk_sms.py b/app/api/services/bulk_sms.py new file mode 100644 index 0000000..e9d757c --- /dev/null +++ b/app/api/services/bulk_sms.py @@ -0,0 +1,78 @@ +from flask import request, jsonify +from marshmallow import ValidationError +from app.utils.logger import logger +from app.api.schemas.bulk_sms import BulkSMSSchema, BulkSMSResponseSchema + + +class BulkSMSService: + @staticmethod + def process_request(data): + """ + Process the BulkSMS request. + + Args: + data (list): The request data as a list of SMS items. + + Returns: + dict: A standardized response. + """ + try: + logger.info("Processing BulkSMS request") + + # Check if the data is a list and not too large + if not isinstance(data, list): + return jsonify({ + "data": "", + "statusCode": 400, + "IsSuccessful": False, + "errorMessage": "Request must be a list of SMS items" + }), 400 + + if len(data) > 20: + return jsonify({ + "data": "", + "statusCode": 400, + "IsSuccessful": False, + "errorMessage": "Maximum of 20 SMS items allowed" + }), 400 + + # Validate each item in the list + schema = BulkSMSSchema() + # We need to wrap the list in a dictionary with a key that matches the schema field name + validated_data = schema.load({"_schema": data}) # Raises ValidationError if invalid + + # Simulated processing logic + # In a real implementation, this would interact with your business logic + # to send bulk SMS messages to customers + + # For demonstration, we'll simulate a successful bulk SMS send + response_data = { + "data": "", + "statusCode": 200, + "IsSuccessful": True, + "errorMessage": None + } + + # Validate the response using the response schema + response_schema = BulkSMSResponseSchema() + validated_response = response_schema.dump(response_data) + + return jsonify(validated_response) + + except ValidationError as err: + logger.error(f"Validation Error: {err.messages}") + return jsonify({ + "data": "", + "statusCode": 400, + "IsSuccessful": False, + "errorMessage": f"Validation error: {err.messages}" + }), 400 + + except Exception as e: + logger.error(f"An error occurred: {str(e)}", exc_info=True) + return jsonify({ + "data": "", + "statusCode": 500, + "IsSuccessful": False, + "errorMessage": f"Error occurred: {str(e)}" + }), 500 \ No newline at end of file diff --git a/app/api/services/collect_loan.py b/app/api/services/collect_loan.py index 1c99a4c..a088e4d 100644 --- a/app/api/services/collect_loan.py +++ b/app/api/services/collect_loan.py @@ -1,8 +1,8 @@ from flask import request, jsonify from marshmallow import ValidationError from app.utils.logger import logger -from app.api.helpers.response_helper import ResponseHelper -from app.api.schemas.collect_loan import CollectLoanSchema +from app.api.schemas.collect_loan import CollectLoanSchema, CollectLoanResponseSchema + class CollectLoanService: @staticmethod @@ -21,41 +21,47 @@ class CollectLoanService: # Validate input data using CollectLoanSchema schema = CollectLoanSchema() - validated_data = schema.load(data) + validated_data = schema.load(data) # Raises ValidationError if invalid # Simulated processing logic + # In a real implementation, this would interact with your business logic + # to process the loan collection + + # For demonstration, we'll simulate a partial collection + collect_amount = validated_data.get('collectAmount') * 0.75 # 75% of requested amount + lien_amount = validated_data.get('lienAmount') * 0.25 # 25% of requested amount as lien + response_data = { - "transactionId": "T002", - "debtId": "273194670", - "customerId": "CN621868", - "accountId": "2017821799", - "productId": "101", - "collectAmount": 60000.00, - "penalCharge": 0, - "lienAmount": 20000, - "countryId": "01", - "comment": "Testing CollectionLoanRequest", + "transactionId": validated_data.get('transactionId'), + "debtId": validated_data.get('debtId'), + "customerId": validated_data.get('customerId'), + "accountId": validated_data.get('accountId'), + "productId": validated_data.get('productId'), + "collectAmount": collect_amount, + "penalCharge": validated_data.get('penalCharge', 0), + "lienAmount": lien_amount, + "countryId": validated_data.get('countryId'), + "comment": validated_data.get('comment', ""), "resultCode": "00", "resultDescription": "Loan Collection Successful" } + # Validate the response using the response schema + response_schema = CollectLoanResponseSchema() + validated_response = response_schema.dump(response_data) - # return ResponseHelper.success( - # data=response_data, - # message="Loan collection completed successfully" - # ) - - return response_data + return jsonify(validated_response) except ValidationError as err: logger.error(f"Validation Error: {err.messages}") return jsonify({ - "message": "Validation exception" - }) , 422 - + "resultCode": "01", + "resultDescription": f"Validation error: {err.messages}" + }), 422 except Exception as e: logger.error(f"An error occurred: {str(e)}", exc_info=True) return jsonify({ - "message": "Internal Server Error" - }) , 500 + "resultCode": "08", + "resultDescription": f"Error occurred: {str(e)}" + }), 500 \ No newline at end of file diff --git a/app/api/services/lien_check.py b/app/api/services/lien_check.py index eae8e6a..eb01b60 100644 --- a/app/api/services/lien_check.py +++ b/app/api/services/lien_check.py @@ -1,8 +1,8 @@ +from flask import request, jsonify from marshmallow import ValidationError from app.utils.logger import logger -from app.api.helpers.response_helper import ResponseHelper -from app.api.schemas.lien_check import LienCheckSchema -from flask import request, jsonify +from app.api.schemas.lien_check import LienCheckSchema, LienCheckResponseSchema + class LienCheckService: @staticmethod @@ -23,29 +23,33 @@ class LienCheckService: schema = LienCheckSchema() validated_data = schema.load(data) # Raises ValidationError if invalid - # Simulated lien check logic + # Simulated processing logic + # In a real implementation, this would interact with your business logic + # to check the lien amount on the account + + # For demonstration, we'll simulate a lien amount of 20000.0 response_data = { "lienAmount": 20000.0, "resultCode": "00", "resultDescription": "Successful" } + # Validate the response using the response schema + response_schema = LienCheckResponseSchema() + validated_response = response_schema.dump(response_data) - # return ResponseHelper.success( - # data=response_data, - # message="Lien check completed successfully" - # ) - - return response_data + return jsonify(validated_response) except ValidationError as err: logger.error(f"Validation Error: {err.messages}") return jsonify({ - "message": "Validation exception" - }) , 422 + "resultCode": "01", + "resultDescription": f"Validation error: {err.messages}" + }), 422 except Exception as e: logger.error(f"An error occurred: {str(e)}", exc_info=True) return jsonify({ - "message": "Internal Server Error" - }) , 500 + "resultCode": "08", + "resultDescription": f"Error occurred: {str(e)}" + }), 500 \ No newline at end of file diff --git a/app/api/services/loan_status.py b/app/api/services/loan_status.py new file mode 100644 index 0000000..e20e0f8 --- /dev/null +++ b/app/api/services/loan_status.py @@ -0,0 +1,77 @@ +from flask import request, jsonify +from marshmallow import ValidationError +from app.utils.logger import logger +from app.api.schemas.loan_status import LoanStatusSchema, LoanStatusResponseSchema +from datetime import datetime, timedelta + + +class LoanStatusService: + @staticmethod + def process_request(data): + """ + Process the LoanStatus request. + + Args: + data (dict): The request data. + + Returns: + dict: A standardized response. + """ + try: + logger.info("Processing LoanStatus request") + + # Validate input data using LoanStatusSchema + schema = LoanStatusSchema() + validated_data = schema.load(data) # Raises ValidationError if invalid + + # Simulated processing logic + # In a real implementation, this would interact with your business logic + # to retrieve the customer's loan status + + # For demonstration, we'll create a sample response with one loan + # In a real implementation, you would query your database for actual loan data + current_date = datetime.now() + loan_date = (current_date - timedelta(days=30)).strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] + due_date = (current_date + timedelta(days=30)).strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] + + # Sample loan data + loan_data = { + "debtId": "123456789", + "loanDate": loan_date, + "dueDate": due_date, + "currentLoanAmount": 8500.0, + "initialLoanAmount": 10000.0, + "defaultPenaltyFee": 0.0, + "continuousFee": 0.0, + "productId": "101" + } + + # Create response with the loan data + response_data = { + "customerId": validated_data.get('customerId'), + "transactionId": validated_data.get('transactionId'), + "loans": [loan_data], # Array with one loan + "totalDebtAmount": 8500.0, # Same as currentLoanAmount for this example + "resultCode": "00", + "resultDescription": "Successful" + } + + # Validate the response using the response schema + response_schema = LoanStatusResponseSchema() + validated_response = response_schema.dump(response_data) + + return jsonify(validated_response) + + except ValidationError as err: + logger.error(f"Validation Error: {err.messages}") + return jsonify({ + "resultCode": "01", + "resultDescription": f"Validation error: {err.messages}" + }), 422 + + except Exception as e: + logger.error(f"An error occurred: {str(e)}", exc_info=True) + return jsonify({ + "resultCode": "08", + "resultDescription": f"Error occurred: {str(e)}" + }), 500 \ No newline at end of file diff --git a/app/api/services/penal_charge.py b/app/api/services/penal_charge.py index 8a4924c..fd4b515 100644 --- a/app/api/services/penal_charge.py +++ b/app/api/services/penal_charge.py @@ -1,8 +1,7 @@ from flask import request, jsonify from marshmallow import ValidationError from app.utils.logger import logger -from app.api.helpers.response_helper import ResponseHelper -from app.api.schemas.penal_charge import PenalChargeSchema +from app.api.schemas.penal_charge import PenalChargeSchema, PenalChargeResponseSchema class PenalChargeService: @@ -25,27 +24,31 @@ class PenalChargeService: validated_data = schema.load(data) # Raises ValidationError if invalid # Simulated processing logic + # In a real implementation, this would interact with your business logic + # to process the penal charge + + # For demonstration, we'll simulate a successful penal charge response_data = { "resultCode": "00", "resultDescription": "Penal charge debited successfully" } + # Validate the response using the response schema + response_schema = PenalChargeResponseSchema() + validated_response = response_schema.dump(response_data) - # return ResponseHelper.success( - # data=response_data, - # message="Penal charge applied successfully" - # ) - - return response_data + return jsonify(validated_response) except ValidationError as err: logger.error(f"Validation Error: {err.messages}") return jsonify({ - "message": "Validation exception" - }) , 422 + "resultCode": "01", + "resultDescription": f"Validation error: {err.messages}" + }), 422 except Exception as e: logger.error(f"An error occurred: {str(e)}", exc_info=True) return jsonify({ - "message": "Internal Server Error" - }) , 500 + "resultCode": "08", + "resultDescription": f"Error occurred: {str(e)}" + }), 500 \ No newline at end of file diff --git a/app/api/services/provide_loan.py b/app/api/services/provide_loan.py new file mode 100644 index 0000000..c191bd1 --- /dev/null +++ b/app/api/services/provide_loan.py @@ -0,0 +1,56 @@ +from flask import request, jsonify +from marshmallow import ValidationError +from app.utils.logger import logger +from app.api.schemas.provide_loan import ProvideLoanSchema, ProvideLoanResponseSchema + +class ProvideLoanService: + @staticmethod + def process_request(data): + """ + Process the ProvideLoan request. + + Args: + data (dict): The request data. + + Returns: + dict: A standardized response. + """ + try: + logger.info("Processing ProvideLoan request") + + # Validate input data using ProvideLoanSchema + schema = ProvideLoanSchema() + validated_data = schema.load(data) # Raises ValidationError if invalid + + # Simulated processing logic + # In a real implementation, this would interact with your business logic + # to process the loan provision request + response_data = { + "requestId": validated_data.get('requestId', f"REQ-{validated_data.get('transactionId')}"), + "transactionId": validated_data.get('transactionId'), + "customerId": validated_data.get('customerId'), + "accountId": validated_data.get('accountId'), + "msisdn": validated_data.get('msisdn', ""), + "resultCode": "00", + "resultDescription": "Successful" + } + + # Validate the response using the response schema + response_schema = ProvideLoanResponseSchema() + validated_response = response_schema.dump(response_data) + + return jsonify(validated_response) + + except ValidationError as err: + logger.error(f"Validation Error: {err.messages}") + return jsonify({ + "resultCode": "01", + "resultDescription": f"Validation error: {err.messages}" + }), 422 + + except Exception as e: + logger.error(f"An error occurred: {str(e)}", exc_info=True) + return jsonify({ + "resultCode": "08", + "resultDescription": f"Error occurred: {str(e)}" + }), 500 \ No newline at end of file diff --git a/app/api/services/rac_check.py b/app/api/services/rac_check.py index cdc6295..253bfc7 100644 --- a/app/api/services/rac_check.py +++ b/app/api/services/rac_check.py @@ -1,8 +1,8 @@ from flask import request, jsonify from marshmallow import ValidationError from app.utils.logger import logger -from app.api.helpers.response_helper import ResponseHelper -from app.api.schemas.rac_check import RACCheckSchema +from app.api.schemas.rac_check import RACCheckSchema, RACCheckResponseSchema + class RACCheckService: @staticmethod @@ -24,40 +24,49 @@ class RACCheckService: validated_data = schema.load(data) # Raises ValidationError if invalid # Simulated processing logic + # In a real implementation, this would interact with your business logic + # to check the RAC criteria + + # For demonstration, we'll simulate all checks passing + rac_response = { + "Salary account": "1", + "BVN": "1", + "BVNAttachedToAccount": "1", + "CRMS": "1", + "CRC": "1", + "AccountStatus": "1", + "Lien": "1", + "NoBouncedCheck": "1", + "Whitelist": "1", + "NoPastDueSalaryLoan": "1", + "NoPastDueOtherLoan": "1" + } + response_data = { + "transactionId": validated_data.get('transactionId'), + "customerId": validated_data.get('customerId'), + "accountId": validated_data.get('accountId'), + "RACResponse": rac_response, "resultCode": "00", - "RACResponse": { - "SalaryAccount": "1", - "BVN": "1", - "BVNAttachedToAccount": "1", - "CRMS": "1", - "CRC": "1", - "AccountStatus": "1", - "Lien": "1", - "NoBouncedCheck": "1", - "Whitelist": "1", - "NoPastDueSalaryLoan": "1", - "NoPastDueOtherLoan": "1" - }, "resultDescription": "RAC Check Successful" } + # Validate the response using the response schema + response_schema = RACCheckResponseSchema() + validated_response = response_schema.dump(response_data) - # return ResponseHelper.success( - # data=response_data, - # message="RAC check completed successfully" - # ) - - return response_data + return jsonify(validated_response) except ValidationError as err: logger.error(f"Validation Error: {err.messages}") return jsonify({ - "message": "Validation exception" - }) , 422 + "resultCode": "01", + "resultDescription": f"Validation error: {err.messages}" + }), 422 except Exception as e: logger.error(f"An error occurred: {str(e)}", exc_info=True) return jsonify({ - "message": "Internal Server Error" - }) , 500 + "resultCode": "08", + "resultDescription": f"Error occurred: {str(e)}" + }), 500 \ No newline at end of file diff --git a/app/api/services/repayment.py b/app/api/services/repayment.py index 779c0d3..acc97fe 100644 --- a/app/api/services/repayment.py +++ b/app/api/services/repayment.py @@ -1,64 +1,68 @@ -from flask import jsonify +from flask import request, jsonify +from marshmallow import ValidationError from app.utils.logger import logger +from app.api.schemas.repayment import RepaymentSchema, RepaymentResponseSchema class RepaymentService: @staticmethod def process_request(data): """ - Process a repayment request from Simbrella to FirstBank + Process the Repayment request. Args: - data (dict): The request data containing repayment details + data (dict): The request data. Returns: - flask.Response: JSON response with the result of the repayment operation + dict: A standardized response. """ try: - # Log the incoming request - logger.info(f"Processing repayment request: {data}") + logger.info("Processing Repayment request") - # Validate required fields - required_fields = [ - "requestId", "countryCode", "transactionId", "debtId", - "customerId", "accountId", "productId", "collectAmount", - "collectionMethod", "lienAmount" - ] + # Validate input data using RepaymentSchema + schema = RepaymentSchema() + validated_data = schema.load(data) # Raises ValidationError if invalid - for field in required_fields: - if field not in data: - logger.error(f"Missing required field: {field}") - return jsonify({ - "resultCode": "01", - "resultDescription": f"Missing required field: {field}" - }), 400 + # Simulated processing logic + # In a real implementation, this would interact with your business logic + # to process the repayment - # Process the repayment request - # This is where you would implement the actual business logic - # For now, we'll just return a successful response + # For demonstration, we'll simulate a partial repayment + collected_amount = validated_data.get('collectedAmount') * 0.75 # 75% of requested amount + lien_amount = validated_data.get('lienAmount') * 0.25 # 25% of requested amount as lien - response = { - "requestId": data.get("requestId"), - "countryCode": data.get("countryCode"), - "transactionId": data.get("transactionId"), - "debtId": data.get("debtId"), - "customerId": data.get("customerId"), - "accountId": data.get("accountId"), - "productId": data.get("productId"), - "collectAmount": data.get("collectAmount"), - "penalCharge": data.get("penalCharge", 0), - "lienAmount": data.get("lienAmount"), - "comment": data.get("comment", ""), + response_data = { + "requestId": validated_data.get('requestId'), + "countryCode": validated_data.get('countryCode'), + "transactionId": validated_data.get('transactionId'), + "debtId": validated_data.get('debtId'), + "customerId": validated_data.get('customerId'), + "accountId": validated_data.get('accountId'), + "productId": validated_data.get('productId'), + "collectedAmount": collected_amount, + "penalCharge": validated_data.get('penalCharge', 0), + "lienAmount": lien_amount, + "comment": validated_data.get('comment', ""), "resultCode": "00", "resultDescription": "Loan Collection Successful" } - logger.info(f"Repayment response: {response}") - return jsonify(response) + # Validate the response using the response schema + response_schema = RepaymentResponseSchema() + validated_response = response_schema.dump(response_data) + + return jsonify(validated_response) + + except ValidationError as err: + logger.error(f"Validation Error: {err.messages}") + return jsonify({ + "resultCode": "01", + "resultDescription": f"Validation error: {err.messages}" + }), 422 except Exception as e: - logger.error(f"Error processing repayment request: {str(e)}") + logger.error(f"An error occurred: {str(e)}", exc_info=True) return jsonify({ "resultCode": "08", - "resultDescription": "Error occurred" + "resultDescription": f"Error occurred: {str(e)}" }), 500 \ No newline at end of file diff --git a/app/api/services/sms.py b/app/api/services/sms.py new file mode 100644 index 0000000..bc2093e --- /dev/null +++ b/app/api/services/sms.py @@ -0,0 +1,60 @@ +from flask import request, jsonify +from marshmallow import ValidationError +from app.utils.logger import logger +from app.api.schemas.sms import SMSSchema, SMSResponseSchema + + +class SMSService: + @staticmethod + def process_request(data): + """ + Process the SMS request. + + Args: + data (dict): The request data. + + Returns: + dict: A standardized response. + """ + try: + logger.info("Processing SMS request") + + # Validate input data using SMSSchema + schema = SMSSchema() + validated_data = schema.load(data) # Raises ValidationError if invalid + + # Simulated processing logic + # In a real implementation, this would interact with your business logic + # to send an SMS to the customer + + # For demonstration, we'll simulate a successful SMS send + response_data = { + "data": "", + "statusCode": 200, + "IsSuccessful": True, + "errorMessage": None + } + + # Validate the response using the response schema + response_schema = SMSResponseSchema() + validated_response = response_schema.dump(response_data) + + return jsonify(validated_response) + + except ValidationError as err: + logger.error(f"Validation Error: {err.messages}") + return jsonify({ + "data": "", + "statusCode": 400, + "IsSuccessful": False, + "errorMessage": f"Validation error: {err.messages}" + }), 400 + + except Exception as e: + logger.error(f"An error occurred: {str(e)}", exc_info=True) + return jsonify({ + "data": "", + "statusCode": 500, + "IsSuccessful": False, + "errorMessage": f"Error occurred: {str(e)}" + }), 500 \ No newline at end of file diff --git a/app/api/services/status_call.py b/app/api/services/status_call.py index 2437c35..b691d52 100644 --- a/app/api/services/status_call.py +++ b/app/api/services/status_call.py @@ -1,84 +1,77 @@ -from flask import jsonify +from flask import request, jsonify +from marshmallow import ValidationError from app.utils.logger import logger +from app.api.schemas.status_call import StatusCallSchema, StatusCallResponseSchema class StatusCallService: @staticmethod def process_request(data): """ - Process a status call request to check transaction status + Process the StatusCall request. Args: - data (dict): The request data containing transaction details to check + data (dict): The request data. Returns: - flask.Response: JSON response with the status of the transaction + dict: A standardized response. """ try: - # Log the incoming request - logger.info(f"Processing status call request: {data}") + logger.info("Processing StatusCall request") - # Validate required fields - required_fields = [ - "transactionId", "transactionType", "customerId" - ] + # Validate input data using StatusCallSchema + schema = StatusCallSchema() + validated_data = schema.load(data) # Raises ValidationError if invalid - for field in required_fields: - if field not in data: - logger.error(f"Missing required field: {field}") - return jsonify({ - "resultCode": "01", - "resultDescription": f"Missing required field: {field}" - }), 400 + # Simulated processing logic + # In a real implementation, this would interact with your business logic + # to check the status of a transaction - # Process the status call request based on transaction type - transaction_type = data.get("transactionType") + # For demonstration, we'll simulate different responses based on transaction type + transaction_type = validated_data.get('transactionType') - # Prepare the response based on transaction type if transaction_type == "Disbursement": - status = { - "providedAmount": 1000.00, - "collectedAmount": 0.00, - "resultCode": "00", - "resultDescription": "Loan Provision is successful" - } + provided_amount = 1000.00 + collected_amount = 0.00 + inner_result_description = "Loan Provision is successful" elif transaction_type == "Collection": - status = { - "providedAmount": 0.00, - "collectedAmount": 100.00, - "resultCode": "00", - "resultDescription": "Loan Collection is successful" - } - elif transaction_type == "PenalCharge": - status = { - "transactionId": data.get("transactionId"), - "providedAmount": 0.00, - "collectedAmount": 100.00, - "resultCode": "00", - "resultDescription": "Penal Charge is successful" - } - else: - logger.error(f"Invalid transaction type: {transaction_type}") - return jsonify({ - "resultCode": "01", - "resultDescription": f"Invalid transaction type: {transaction_type}" - }), 400 + provided_amount = 0.00 + collected_amount = 1050.00 + inner_result_description = "Loan Collection is successful" + else: # PenalCharge + provided_amount = 0.00 + collected_amount = 50.00 + inner_result_description = "Penal Charge is successful" - response = { - "requestId": data.get("requestId", ""), - "countryCode": data.get("countryCode", "NGR"), - "transactionId": data.get("transactionId"), - "Status": status, + response_data = { + "transactionId": "24110114545374721", # This would be generated in a real system + "data": { + "transactionId": validated_data.get('transactionId'), + "providedAmount": provided_amount, + "collectedAmount": collected_amount, + "resultCode": "00", + "resultDescription": inner_result_description + }, "resultCode": "00", "resultDescription": "SUCCESS" } - logger.info(f"Status call response: {response}") - return jsonify(response) + # Validate the response using the response schema + response_schema = StatusCallResponseSchema() + validated_response = response_schema.dump(response_data) + + return jsonify(validated_response) + + except ValidationError as err: + logger.error(f"Validation Error: {err.messages}") + return jsonify({ + "resultCode": "01", + "resultDescription": f"Validation error: {err.messages}" + }), 422 except Exception as e: - logger.error(f"Error processing status call request: {str(e)}") + logger.error(f"An error occurred: {str(e)}", exc_info=True) return jsonify({ "resultCode": "08", - "resultDescription": "Error occurred" + "resultDescription": f"Error occurred: {str(e)}" }), 500 \ No newline at end of file diff --git a/app/api/services/transaction_verify.py b/app/api/services/transaction_verify.py index e55e2de..a7c956f 100644 --- a/app/api/services/transaction_verify.py +++ b/app/api/services/transaction_verify.py @@ -1,8 +1,7 @@ from flask import request, jsonify from marshmallow import ValidationError from app.utils.logger import logger -from app.api.helpers.response_helper import ResponseHelper -from app.api.schemas.transaction_verify import TransactionVerifySchema +from app.api.schemas.transaction_verify import TransactionVerifySchema, TransactionVerifyResponseSchema class TransactionVerifyService: @@ -25,33 +24,54 @@ class TransactionVerifyService: validated_data = schema.load(data) # Raises ValidationError if invalid # Simulated processing logic + # In a real implementation, this would interact with your business logic + # to verify the transaction status + + # For demonstration, we'll simulate different responses based on transaction type + transaction_type = validated_data.get('transactionType') + + if transaction_type == "Disbursement": + provided_amount = 100.0 + collected_amount = 0.0 + result_description = "Disbursement Status retrieved successfully." + elif transaction_type == "Collection": + provided_amount = 0.0 + collected_amount = 75.0 + result_description = "Collection Status retrieved successfully." + else: # Penalty + provided_amount = 0.0 + collected_amount = 7.50 + result_description = "Penalty Status retrieved successfully." + response_data = { - "type": "TransactionCheckResponse", - "nativeId": "FBN20191031104405CN621868", - "customerId": "CN621868", - "accountId": "2017821799", - "providedAmount": 0.0, - "collectedAmount": 7.50, + "requestId": validated_data.get('requestId'), + "countryCode": validated_data.get('countryCode'), + "transactionId": validated_data.get('transactionId'), + "transactionType": transaction_type, + "customerId": validated_data.get('customerId'), + "accountId": validated_data.get('accountId'), + "providedAmount": provided_amount, + "collectedAmount": collected_amount, "resultCode": "00", - "resultDescription": "Collect Status retrieved successfully." + "resultDescription": result_description } + # Validate the response using the response schema + response_schema = TransactionVerifyResponseSchema() + validated_response = response_schema.dump(response_data) - # return ResponseHelper.success( - # data=response_data, - # message="Transaction verification completed successfully" - # ) - - return response_data + return jsonify(validated_response) except ValidationError as err: logger.error(f"Validation Error: {err.messages}") return jsonify({ - "message": "Validation exception" - }) , 422 + "resultCode": "01", + "resultDescription": f"Validation error: {err.messages}" + }), 422 except Exception as e: logger.error(f"An error occurred: {str(e)}", exc_info=True) return jsonify({ - "message": "Internal Server Error" - }) , 500 + "resultCode": "08", + "resultDescription": f"Error occurred: {str(e)}" + }), 500 \ No newline at end of file