(20250102) Testing receipt-add with structured metadata.

This commit is contained in:
2025-01-02 10:51:55 +00:00
parent 7f98f1f662
commit fd2a1ef6d1
5 changed files with 71 additions and 23 deletions
@@ -172,6 +172,12 @@ async def request_payment(
message = f"No such token key." message = f"No such token key."
) )
# Get the user's info:
user_info = CoreUserInfoModel(**kwargs["session_info"])
# Add required details to the payment's metadata:
inbound_data.metadata.idUser = user_info.userId
# ┳┓ ┏┓ # ┳┓ ┏┓
# ┣┫┏┓┏┓┓┏┏┓┏╋ ┃┃┏┓┓┏┏┳┓┏┓┏┓╋ # ┣┫┏┓┏┓┓┏┏┓┏╋ ┃┃┏┓┓┏┏┳┓┏┓┏┓╋
# ┛┗┗ ┗┫┗┻┗ ┛┗ ┣┛┗┻┗┫┛┗┗┗ ┛┗┗ # ┛┗┗ ┗┫┗┻┗ ┛┗ ┣┛┗┻┗┫┛┗┗┗ ┛┗┗
@@ -183,7 +189,7 @@ async def request_payment(
sql_conn = current_app.sql_writer, sql_conn = current_app.sql_writer,
mongo_data_conn = current_app.data_mongo, mongo_data_conn = current_app.data_mongo,
auth_token = auth_token, auth_token = auth_token,
user_info = CoreUserInfoModel(**kwargs["session_info"]), user_info = user_info,
payment_request = inbound_data payment_request = inbound_data
) )
+10 -9
View File
@@ -37,6 +37,7 @@ sys.path.append("..")
# My async utils: # My async utils:
from utils_v2.string import json from utils_v2.string import json
from utils_v2.date_time import date_time
from utils_v2.database.async_mysql_v2 import AsyncMySQL from utils_v2.database.async_mysql_v2 import AsyncMySQL
from utils_v2.database.async_mongo_v2 import AsyncMongo from utils_v2.database.async_mongo_v2 import AsyncMongo
from utils_v2.cache.async_redis_cache_v2 import AsyncRedisCache from utils_v2.cache.async_redis_cache_v2 import AsyncRedisCache
@@ -334,15 +335,15 @@ class PaymentsController(CoreAuthTokenController, ABC):
sql_conn = sql_conn, sql_conn = sql_conn,
proc_name = "accounting_receipt_add", proc_name = "accounting_receipt_add",
proc_args = ( proc_args = (
payment.metadata["idClient"], payment.metadata.idClient, # .................................... p_client_id
payment.metadata["date"], date_time.get_current_ist_date_time().strftime("%Y-%m-%d"), # ... p_date
payment.metadata["source"], payment.client, # ............................................... p_source
payment.metadata["amount"], payment.amount, # ............................................... p_amount
payment.metadata["reference"], payment.metadata.reference, # ................................... p_reference
payment.metadata["inAccount"], payment.metadata.inAccount, # ................................... p_in_account
payment.metadata["idUser"], payment.metadata.idUser, # ...................................... p_user_id
payment.metadata["documentUrl"], payment.metadata.documentUrl, # ................................. p_document_url
payment.metadata["notes"] payment.metadata.notes # ........................................ p_notes
), ),
retry_count = 1, retry_count = 1,
backoff_seconds = 0.5, backoff_seconds = 0.5,
@@ -367,11 +367,12 @@ class SafaricomMPesaExpressPaymentsController(PaymentsController):
) )
# For when the payment is successful: # For when the payment is successful:
if pg_result_code in []: if pg_result_code in [0]:
await self.add_receipt( await self.add_receipt(
sql_conn = sql_conn, sql_conn = sql_conn,
mongo_data_conn = mongo_data_conn, mongo_data_conn = mongo_data_conn,
payment = payment payment = payment,
session_token = None
) )
# Done here: # Done here:
+47 -8
View File
@@ -41,13 +41,6 @@ from typing import Optional, Literal, Union, List, Any
# My utils: # My utils:
from utils_v2.string import regex from utils_v2.string import regex
from utils_v2.date_time import date_time
# Models:
from models.core.payment import CorePaymentModel, PaymentMetadata
# To work with date and time:
import datetime
# To work with MongoDB: # To work with MongoDB:
from bson.objectid import ObjectId from bson.objectid import ObjectId
@@ -108,6 +101,52 @@ class PGPaymentRequestHeaders(BaseModel):
# --------------------------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------------------------
class PaymentRequestMetadata(BaseModel):
"""
These are things that the UI will send you, and you must use them as-is for adding receipts. Their internal workings
and use-cases are not known and are not of this code's direct concern except that you must ensure that these details
get delivered through the mechanism of adding receipts.
"""
idUser: int | None = Field(frozen = False, default = None, validate_default = True)
idClient: int = Field(frozen = True)
inAccount: int = Field(frozen = True)
reference: str | None = Field(frozen = True, default = None, validate_default = True)
againstReference: str | None = Field(frozen = True, default = None, validate_default = True)
documentUrl: str | None = Field(frozen = False, default = None, validate_default = True)
# ┏┓ ┏•
# ┃ ┏┓┏┓╋┓┏┓
# ┗┛┗┛┛┗┛┗┗┫
# ┛
class Config:
extra = "allow"
# ┓┏ ┓• ┓ •
# ┃┃┏┓┃┓┏┫┏┓╋┓┏┓┏┓
# ┗┛┗┻┗┗┗┻┗┻┗┗┗┛┛┗
@field_validator("reference")
def validate_reference(cls, value):
if not value: value = "On Account"
return value
@field_validator("againstReference")
def validate_against_reference(cls, value):
if not value: value = None
return value
@field_validator("documentUrl")
def validate_document_url(cls, value):
if not value: value = None
return value
# ---------------------------------------------------------------------------------------------------------------------
class PGPaymentRequestData(BaseModel): class PGPaymentRequestData(BaseModel):
tokenKey: ObjectId = Field( tokenKey: ObjectId = Field(
@@ -159,7 +198,7 @@ class PGPaymentRequestData(BaseModel):
frozen = True frozen = True
) )
metadata: PaymentMetadata = Field( metadata: PaymentRequestMetadata = Field(
description = "any extra information about this payment", description = "any extra information about this payment",
frozen = True frozen = True
) )
+4 -3
View File
@@ -142,8 +142,9 @@ class PaymentMetadata(BaseModel):
get delivered through the mechanism of adding receipts. get delivered through the mechanism of adding receipts.
""" """
idClient: int = Field(frozen = True) idUser: int | None = Field(frozen = True, default = None, validate_default = True)
inAccount: int = Field(frozen = True) idClient: int | None = Field(frozen = True, default = None, validate_default = True)
inAccount: int | None = Field(frozen = True, default = None, validate_default = True)
reference: str | None = Field(frozen = True, default = None, validate_default = True) reference: str | None = Field(frozen = True, default = None, validate_default = True)
againstReference: str | None = Field(frozen = True, default = None, validate_default = True) againstReference: str | None = Field(frozen = True, default = None, validate_default = True)
documentUrl: str | None = Field(frozen = False, default = None, validate_default = True) documentUrl: str | None = Field(frozen = False, default = None, validate_default = True)
@@ -314,7 +315,7 @@ class CorePaymentModel(BaseModel):
examples = ["INR", "USD", "KES"] examples = ["INR", "USD", "KES"]
) )
metadata: dict | None = Field( metadata: PaymentMetadata = Field(
description = "any arbitrary amount of data to identify the user and payment details", description = "any arbitrary amount of data to identify the user and payment details",
frozen = True frozen = True
) )