Big Bang Refactor of Payments. Introduced a new paymentdata singleton that stores data across pages and on disk. Also introduced a suite of functions for handling payments
This commit is contained in:
parent
57774ae697
commit
52b3e1ba94
6 changed files with 228 additions and 52 deletions
|
|
@ -1,13 +1,15 @@
|
||||||
|
from core.services.payment_phase.payment_state import PaymentData
|
||||||
|
from core.models.BaseProfile import BaseProfile as Profile
|
||||||
from core.models.orm_models.Plan import Plan
|
from core.models.orm_models.Plan import Plan
|
||||||
from core.models.orm_calls.model_neutral_tools import get_all_for_model
|
from core.models.orm_calls.model_neutral_tools import get_all_for_model
|
||||||
from core.models.orm_calls.location_calls import get_profile_location_data
|
from core.models.orm_calls.location_calls import get_profile_location_data
|
||||||
from core.models.enum_models import ProtocolChoice
|
from core.models.enum_models import ProtocolChoice, Currency
|
||||||
from core.models.orm_models.Location import Location
|
from core.models.orm_models.Location import Location
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
from core.models.Result import Result, ResultError
|
from core.models.Result import Result, ResultError
|
||||||
|
|
||||||
ALL_PROTOCOLS = [e.value for e in ProtocolChoice]
|
ALL_PROTOCOLS = [e.value for e in ProtocolChoice]
|
||||||
|
ALL_CURRENCIES = [e.value for e in Currency]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Outputs:
|
Outputs:
|
||||||
|
|
@ -57,16 +59,41 @@ def _get_supported_protocols_for_location(location: Location, as_strings: bool =
|
||||||
return SUPPORTED_PROTOCOLS
|
return SUPPORTED_PROTOCOLS
|
||||||
|
|
||||||
|
|
||||||
def get_all_plans(chosen_protocol: ProtocolChoice) -> Result:
|
def get_plans_for_profile(profile_id: int) -> Result:
|
||||||
|
"""
|
||||||
|
Get a formatted list of all Plans for a given profile.
|
||||||
|
And save the protocol in the PaymentData singleton.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Get profile:
|
||||||
|
profile = Profile.find_by_id(profile_id)
|
||||||
|
if not profile:
|
||||||
|
error_msg = f"Invalid profile id of {profile_id}"
|
||||||
|
return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT)
|
||||||
|
|
||||||
|
# Get Protocol for that profile:
|
||||||
|
chosen_protocol = ProtocolChoice(profile.connection.code)
|
||||||
|
|
||||||
|
# create or get the singleton:
|
||||||
|
billing_data = PaymentData(instance_id=profile_id)
|
||||||
|
|
||||||
|
# set it's value across modules:
|
||||||
|
billing_data.protocol_choice = chosen_protocol
|
||||||
|
|
||||||
|
# Return plans for that protocol:
|
||||||
|
return get_all_plans_by_protocol(chosen_protocol)
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_plans_by_protocol(chosen_protocol: ProtocolChoice) -> Result:
|
||||||
"""Get a formatted list of all Plans for a given protocol."""
|
"""Get a formatted list of all Plans for a given protocol."""
|
||||||
|
|
||||||
all_plans = get_all_for_model(model_type=Plan)
|
all_plans = get_all_for_model(model_type=Plan)
|
||||||
|
|
||||||
if not all_plans:
|
if not all_plans:
|
||||||
error_msg = "There are no plans in your local SQL database. Please sync or make sure there's no SQL errors."
|
error_msg = "There are no plans in your local SQL database. Please sync or make sure there's no SQL errors."
|
||||||
return Result(valid=False, error_type=ResultError.SYNC, message=error_msg)
|
return Result(valid=False, error_type=ResultError.MISSING_DATA, message=error_msg)
|
||||||
|
|
||||||
PLANS_TO_RETURN = []
|
PLANS_TO_RETURN = {}
|
||||||
|
|
||||||
for each_plan in all_plans:
|
for each_plan in all_plans:
|
||||||
|
|
||||||
|
|
@ -74,12 +101,7 @@ def get_all_plans(chosen_protocol: ProtocolChoice) -> Result:
|
||||||
if chosen_protocol not in each_plan.supported_protocols:
|
if chosen_protocol not in each_plan.supported_protocols:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
each_json = {
|
plan_format = str(f"{each_plan.months} months (€{each_plan.cost})")
|
||||||
'id': each_plan.id,
|
PLANS_TO_RETURN[plan_format] = each_plan.id
|
||||||
'cost': each_plan.cost,
|
|
||||||
'months': each_plan.months
|
|
||||||
}
|
|
||||||
PLANS_TO_RETURN.append(each_json)
|
|
||||||
|
|
||||||
|
|
||||||
return Result(valid=True, data=PLANS_TO_RETURN)
|
return Result(valid=True, data=PLANS_TO_RETURN)
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ import tempfile
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
from core.models.manage.session_management import init_session, get_session
|
from core.models.manage.session_management import init_session, get_session
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ class Subscription:
|
||||||
exclude=lambda value: value is None
|
exclude=lambda value: value is None
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
billing_pending: bool = False
|
||||||
|
|
||||||
def get_sanitized_billing_code(self):
|
def get_sanitized_billing_code(self):
|
||||||
return '-'.join(['****'] * 3 + [self.billing_code[-4:]])
|
return '-'.join(['****'] * 3 + [self.billing_code[-4:]])
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ def register_wireguard_session(
|
||||||
# print(f"wireguard_configuration value is {wireguard_configuration}")
|
# print(f"wireguard_configuration value is {wireguard_configuration}")
|
||||||
|
|
||||||
if isinstance(wireguard_configuration, dict):
|
if isinstance(wireguard_configuration, dict):
|
||||||
logger.error("Server isn't returning a WG config, it's an error.")
|
logger.error("Server isn't returning a WG config, it's trying to tell you a ServerReply message...")
|
||||||
return handle_config_error(wireguard_configuration)
|
return handle_config_error(wireguard_configuration)
|
||||||
|
|
||||||
if wireguard_configuration is None:
|
if wireguard_configuration is None:
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ def singleton(cls):
|
||||||
# for saving.
|
# for saving.
|
||||||
EXCLUDED_FIELDS = {"parent_folder", "folder_path", "_data_file"}
|
EXCLUDED_FIELDS = {"parent_folder", "folder_path", "_data_file"}
|
||||||
|
|
||||||
|
|
||||||
class StatePersistenceMixin(ValidatedDataclass):
|
class StatePersistenceMixin(ValidatedDataclass):
|
||||||
def _serialize_value(self, value):
|
def _serialize_value(self, value):
|
||||||
"""Helper method to ensure values are JSON-serializable"""
|
"""Helper method to ensure values are JSON-serializable"""
|
||||||
|
|
@ -89,6 +90,7 @@ class StatePersistenceMixin(ValidatedDataclass):
|
||||||
# Add it to the dictionary
|
# Add it to the dictionary
|
||||||
data[f.name] = clean_value
|
data[f.name] = clean_value
|
||||||
|
|
||||||
|
print(f"saving to {self._data_file}")
|
||||||
with open(self._data_file, "w") as f:
|
with open(self._data_file, "w") as f:
|
||||||
json.dump(data, f, indent=4, sort_keys=True)
|
json.dump(data, f, indent=4, sort_keys=True)
|
||||||
|
|
||||||
|
|
@ -122,6 +124,10 @@ class StatePersistenceMixin(ValidatedDataclass):
|
||||||
setattr(self, field.name, value)
|
setattr(self, field.name, value)
|
||||||
|
|
||||||
|
|
||||||
|
def exists_already(self) -> bool:
|
||||||
|
return os.path.exists(self._data_file)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@singleton
|
@singleton
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
@ -134,7 +140,7 @@ class TicketPaymentData(StatePersistenceMixin):
|
||||||
_data_file: str = None
|
_data_file: str = None
|
||||||
|
|
||||||
# actual payload data:
|
# actual payload data:
|
||||||
billing_code: str = None
|
# billing_code: str = None
|
||||||
currency: Currency = None
|
currency: Currency = None
|
||||||
payment_type: PaymentType = PaymentType.CRYPTO
|
payment_type: PaymentType = PaymentType.CRYPTO
|
||||||
|
|
||||||
|
|
@ -153,7 +159,7 @@ class TicketPaymentData(StatePersistenceMixin):
|
||||||
@singleton
|
@singleton
|
||||||
@dataclass
|
@dataclass
|
||||||
class PaymentData(StatePersistenceMixin):
|
class PaymentData(StatePersistenceMixin):
|
||||||
PAYLOAD_FIELDS = {"billing_code", "currency", "plan_id", "location_id", "protocol_choice", "payment_type"}
|
PAYLOAD_FIELDS = {"currency", "plan_id", "location_id", "protocol_choice", "payment_type"}
|
||||||
|
|
||||||
# metadata on it's own instance:
|
# metadata on it's own instance:
|
||||||
parent_folder = None
|
parent_folder = None
|
||||||
|
|
@ -162,11 +168,8 @@ class PaymentData(StatePersistenceMixin):
|
||||||
_data_file: str = None
|
_data_file: str = None
|
||||||
|
|
||||||
# actual payload data:
|
# actual payload data:
|
||||||
billing_code: str = None
|
|
||||||
currency: Currency = None
|
currency: Currency = None
|
||||||
payment_type: PaymentType = PaymentType.CRYPTO
|
payment_type: PaymentType = PaymentType.CRYPTO
|
||||||
|
|
||||||
# for traditional plans:
|
|
||||||
plan_id: int = None
|
plan_id: int = None
|
||||||
location_id: int = None
|
location_id: int = None
|
||||||
protocol_choice: ProtocolChoice = None
|
protocol_choice: ProtocolChoice = None
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
|
from core.models.BaseProfile import BaseProfile as Profile
|
||||||
|
from core.services.payment_phase.payment_state import PaymentData
|
||||||
from core.services.networking.httpx import connect
|
from core.services.networking.httpx import connect
|
||||||
from core.models.enum_models import ProtocolChoice, Currency
|
from core.models.enum_models import ProtocolChoice
|
||||||
from core.models.Result import Result, ResultError
|
from core.models.Result import Result, ResultError
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
from core.observers.ConnectionObserver import ConnectionObserver
|
from core.observers.ConnectionObserver import ConnectionObserver
|
||||||
from core.models.pydantic_models.type_checker import validate_model
|
from core.models.pydantic_models.type_checker import validate_model
|
||||||
from core.models.pydantic_models.ServerReply import ServerReply, ServerError, SubscriptionInvoice
|
from core.models.pydantic_models.ServerReply import ServerReply, ServerError, SubscriptionInvoice
|
||||||
|
from core.models.Subscription import Subscription
|
||||||
from core.Constants import Constants
|
from core.Constants import Constants
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -32,11 +34,10 @@ def check_paid(billing_code: str, connection_observer: ConnectionObserver) -> Re
|
||||||
|
|
||||||
# Layer 2: Server's Reply:
|
# Layer 2: Server's Reply:
|
||||||
raw_reply = api_response.data
|
raw_reply = api_response.data
|
||||||
print(f"validating the server reply of {raw_reply}")
|
|
||||||
server_reply = validate_model(ServerReply, raw_reply)
|
server_reply = validate_model(ServerReply, raw_reply)
|
||||||
|
|
||||||
if not server_reply:
|
if not server_reply:
|
||||||
print("invalid structure for ServerReply")
|
logger.error(f"Invalid structure for ServerReply, which had a raw reply of {raw_reply}")
|
||||||
return invalid_server_format()
|
return invalid_server_format()
|
||||||
|
|
||||||
# paid
|
# paid
|
||||||
|
|
@ -51,68 +52,200 @@ def check_paid(billing_code: str, connection_observer: ConnectionObserver) -> Re
|
||||||
return translate_server_failure(server_reply)
|
return translate_server_failure(server_reply)
|
||||||
|
|
||||||
|
|
||||||
def create_invoice(
|
def create_invoice(profile_id: int, connection_observer: ConnectionObserver) -> Result:
|
||||||
subscription_plan_id: int,
|
"""Prepare the payment data payload and send it to the API. Returns an invoice nested inside Result's data"""
|
||||||
location_id: int,
|
|
||||||
protocol_choice: ProtocolChoice,
|
|
||||||
currency: Currency,
|
|
||||||
connection_observer: ConnectionObserver
|
|
||||||
) -> Result:
|
|
||||||
submit_data = {
|
|
||||||
"subscription_plan_id": subscription_plan_id,
|
|
||||||
"location_id": location_id,
|
|
||||||
"protocol_choice": protocol_choice.value,
|
|
||||||
"currency": currency.value,
|
|
||||||
"payment_type": "crypto"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
# Get profile object:
|
||||||
|
profile = Profile.find_by_id(profile_id)
|
||||||
|
if not profile:
|
||||||
|
error_msg = f"Invalid profile id of {profile_id}"
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT)
|
||||||
|
|
||||||
|
#-----------------------------
|
||||||
|
# MAKE PAYLOAD. PIECE BY PIECE
|
||||||
|
#-----------------------------
|
||||||
|
# get the payment data singleton:
|
||||||
|
billing_data = PaymentData(instance_id=profile_id)
|
||||||
|
|
||||||
|
# make sure the protocol is saved in the singleton already,
|
||||||
|
if not billing_data.protocol_choice:
|
||||||
|
# If not, then get the Protocol for that profile:
|
||||||
|
billing_data.protocol_choice = ProtocolChoice(profile.connection.code)
|
||||||
|
|
||||||
|
# location
|
||||||
|
billing_data.location_id = profile.location.id
|
||||||
|
|
||||||
|
# plan id
|
||||||
|
if not billing_data.plan_id:
|
||||||
|
error_msg = "Missing a plan id to make an invoice"
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT)
|
||||||
|
|
||||||
|
# currency
|
||||||
|
if not billing_data.currency:
|
||||||
|
error_msg = "Missing a currency to make an invoice"
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT)
|
||||||
|
|
||||||
|
# saves it to disk (organized by profile id) & returns a json:
|
||||||
|
payload = billing_data.prep_payload()
|
||||||
|
|
||||||
|
if not payload:
|
||||||
|
error_msg = "Unable to save the payload, or missing fields. Check the error log."
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=False, message=error_msg, error_type=ResultError.FILE_SYSTEM)
|
||||||
|
|
||||||
|
#-----------------------------
|
||||||
|
# SEND TO API
|
||||||
|
#-----------------------------
|
||||||
url = f'{Constants.SP_BASE_URL}/v2/start_billing'
|
url = f'{Constants.SP_BASE_URL}/v2/start_billing'
|
||||||
print(f"url is {url}")
|
|
||||||
|
|
||||||
api_response = connect.single_endpoint(
|
api_response = connect.single_endpoint(
|
||||||
method="post",
|
method="post",
|
||||||
url=url,
|
url=url,
|
||||||
observer=connection_observer,
|
observer=connection_observer,
|
||||||
payload=submit_data,
|
payload=payload,
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f"api_response is {api_response.valid}")
|
#-----------------------------
|
||||||
print(f"api_response is {api_response.error_type}")
|
# EVALUATE CONNECTION FAILURE
|
||||||
|
#-----------------------------
|
||||||
# Layer 1: API failure:
|
# Layer 1: API failure:
|
||||||
if not api_response.valid:
|
if not api_response.valid:
|
||||||
error_msg = f"API Error: {api_response.error_type} {api_response.message}"
|
error_msg = f"Connection/500s Error prevented the server from replying: {api_response.error_type} {api_response.message}"
|
||||||
logger.error(error_msg)
|
logger.error(error_msg)
|
||||||
return Result(valid=False, error_type=ResultError.CONNECTION, message=error_msg)
|
return Result(valid=False, error_type=ResultError.CONNECTION, message=error_msg)
|
||||||
|
|
||||||
# Layer 2: Server's Reply:
|
#-----------------------------
|
||||||
|
# EVALUATE SERVER-SIDE ISSUES (assuming it replied)
|
||||||
|
#-----------------------------
|
||||||
|
# Layer 2: Validity of Server's Reply:
|
||||||
raw_reply = api_response.data
|
raw_reply = api_response.data
|
||||||
print(f"validating the server reply of {raw_reply}.")
|
logger.info("Validating the Validity of the Server's Reply..")
|
||||||
server_reply = validate_model(ServerReply, raw_reply)
|
server_reply = validate_model(ServerReply, raw_reply)
|
||||||
|
|
||||||
if not server_reply:
|
if not server_reply:
|
||||||
print("invalid structure for ServerReply")
|
logger.error(f"Invalid Structure for ServerReply! The raw data is {raw_reply}")
|
||||||
return invalid_server_format()
|
return invalid_server_format()
|
||||||
|
|
||||||
if not server_reply.valid:
|
if not server_reply.valid:
|
||||||
print("Server reply was correctly structured, but was a failure..")
|
logger.error(f"Server reply was correctly structured, but the actual invoice failed to be created. The raw data is {raw_reply}")
|
||||||
|
# translate by enum error code:
|
||||||
return translate_server_failure(server_reply)
|
return translate_server_failure(server_reply)
|
||||||
|
|
||||||
|
#-----------------------------
|
||||||
|
# EVALUATE SERVER'S ACTUAL DATA
|
||||||
|
#-----------------------------
|
||||||
# Layer 3: Payload Data
|
# Layer 3: Payload Data
|
||||||
payload_data = server_reply.data
|
payload_data = server_reply.data
|
||||||
print(f"validating the final invoice with this data: {payload_data}")
|
logger.info("Validating the final invoice")
|
||||||
final_invoice = validate_model(SubscriptionInvoice, payload_data)
|
final_invoice = validate_model(SubscriptionInvoice, payload_data)
|
||||||
|
|
||||||
print(f"final_invoice is {final_invoice}")
|
|
||||||
print(f"final_invoice type is {type(final_invoice)}")
|
|
||||||
|
|
||||||
if not final_invoice:
|
if not final_invoice:
|
||||||
|
logger.error(f"Failed to create an invoice object with this data: {payload_data}")
|
||||||
return invalid_server_format()
|
return invalid_server_format()
|
||||||
|
|
||||||
print("returning True with the data")
|
|
||||||
return Result(valid=True, data=final_invoice)
|
return Result(valid=True, data=final_invoice)
|
||||||
|
|
||||||
|
|
||||||
|
def get_profile_subscription(profile_id: int) -> Subscription:
|
||||||
|
"""Lookup the full profile object & get it's subscription"""
|
||||||
|
print(f"starting lookup of profile id {profile_id}")
|
||||||
|
profile = Profile.find_by_id(profile_id)
|
||||||
|
if not profile:
|
||||||
|
error_msg = f"Invalid profile id of {profile_id}"
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT)
|
||||||
|
|
||||||
|
print(f"returning profile {profile}")
|
||||||
|
return profile.subscription
|
||||||
|
|
||||||
|
|
||||||
|
def save_billing_code(profile_id: int, billing_code: str, expires_at: str) -> Result:
|
||||||
|
"""Checks if the billing code is already saved, and if not, saves it."""
|
||||||
|
|
||||||
|
logger.info("Saving billing code..")
|
||||||
|
|
||||||
|
PRE_REQS = [profile_id, billing_code, expires_at]
|
||||||
|
if None in PRE_REQS:
|
||||||
|
error_msg = "Missing critical required data to save!"
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=False, message=error_msg, error_type=ResultError.MISSING_DATA)
|
||||||
|
|
||||||
|
# Get profile object:
|
||||||
|
profile = Profile.find_by_id(profile_id)
|
||||||
|
if not profile:
|
||||||
|
error_msg = f"Invalid profile id of {profile_id}"
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT)
|
||||||
|
|
||||||
|
try:
|
||||||
|
profile.subscription = Subscription(
|
||||||
|
billing_code=billing_code,
|
||||||
|
expires_at=expires_at,
|
||||||
|
billing_pending=True
|
||||||
|
)
|
||||||
|
profile.save()
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = f"Legacy system wouldn't create or save Subscription object with {str(billing_code)} and {str(expires_at)} or type {type(expires_at)}, with error: {str(e)}"
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT)
|
||||||
|
|
||||||
|
return Result(valid=True)
|
||||||
|
|
||||||
|
|
||||||
|
# # get the payment data singleton:
|
||||||
|
# billing_data = PaymentData(instance_id=profile_id)
|
||||||
|
|
||||||
|
# # new
|
||||||
|
# if billing_data.billing_code is None:
|
||||||
|
# billing_data.billing_code = billing_code
|
||||||
|
# billing_data.save()
|
||||||
|
# logger.info("saved billing_code")
|
||||||
|
# return Result(valid=True)
|
||||||
|
|
||||||
|
# # Already exists and is different:
|
||||||
|
# if regular_billing.billing_code != billing_code:
|
||||||
|
# error_msg = "Critical Error! Billing codes do NOT match"
|
||||||
|
# logger.error(error_msg)
|
||||||
|
# return Result(valid=False, error_type=ResultError.UNKNOWN, message=error_msg)
|
||||||
|
|
||||||
|
# # already saved:
|
||||||
|
# return Result(valid=True, message="Already saved.")
|
||||||
|
|
||||||
|
|
||||||
|
def return_pre_existing_payment_data(profile_id: int, subscription: SubscriptionInvoice) -> Result:
|
||||||
|
"""Return the pre-existing payment details (or lack of) for a profile"""
|
||||||
|
|
||||||
|
logger.info("Starting a fetch of pre-existing payment data")
|
||||||
|
|
||||||
|
# singleton:
|
||||||
|
regular_billing = PaymentData(instance_id=profile_id)
|
||||||
|
if not regular_billing.exists_already():
|
||||||
|
error_msg = f"You have a billing id of {subscription.billing_code}, but no related payment data."
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=False, message=error_msg, error_type=ResultError.MISSING_DATA)
|
||||||
|
|
||||||
|
# dump data:
|
||||||
|
logger.info("Payment data already exists for this profile.")
|
||||||
|
payload = regular_billing.prep_payload
|
||||||
|
|
||||||
|
# add on billing code & expires
|
||||||
|
if payload and isinstance(payload, dict):
|
||||||
|
payload["billing_code"] = subscription.billing_code
|
||||||
|
payload["expires_at"] = subscription.expires_at
|
||||||
|
|
||||||
|
# form an invoice with Profile data & PaymentData singleton for the gui
|
||||||
|
subscription = SubscriptionInvoice(**payload)
|
||||||
|
return Result(valid=True, data=subscription)
|
||||||
|
else:
|
||||||
|
error_msg = "Invalid format for the local PaymentData. It expected a dict and the payload produced to not be blank."
|
||||||
|
logger.error(error_msg)
|
||||||
|
return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Translate Server-side to client-side errors in THIS CONTEXT,
|
# Translate Server-side to client-side errors in THIS CONTEXT,
|
||||||
TRANSLATION_DICT = {
|
TRANSLATION_DICT = {
|
||||||
ServerError.WRONG_LOCATION: ResultError.WRONG_LOCATION,
|
ServerError.WRONG_LOCATION: ResultError.WRONG_LOCATION,
|
||||||
|
|
@ -133,3 +266,21 @@ def translate_server_failure(server_reply: ServerReply) -> Result:
|
||||||
def invalid_server_format() -> Result:
|
def invalid_server_format() -> Result:
|
||||||
error_msg = "The server gave an invalid response format."
|
error_msg = "The server gave an invalid response format."
|
||||||
return Result(valid=False, error_type=ResultError.INVALID_API_REPLY, message=error_msg)
|
return Result(valid=False, error_type=ResultError.INVALID_API_REPLY, message=error_msg)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# def create_invoice(
|
||||||
|
# subscription_plan_id: int,
|
||||||
|
# location_id: int,
|
||||||
|
# protocol_choice: ProtocolChoice,
|
||||||
|
# currency: Currency,
|
||||||
|
# connection_observer: ConnectionObserver
|
||||||
|
# ) -> Result:
|
||||||
|
# submit_data = {
|
||||||
|
# "subscription_plan_id": subscription_plan_id,
|
||||||
|
# "location_id": location_id,
|
||||||
|
# "protocol_choice": protocol_choice.value,
|
||||||
|
# "currency": currency.value,
|
||||||
|
# "payment_type": "crypto"
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue