forked from Support/sp-hydra-veil-gui
Introduced Resume pre-existing invoice. Feature is stable for individual profiles.
This commit is contained in:
parent
40ee53197e
commit
41ac3a75ff
3 changed files with 66 additions and 39 deletions
|
|
@ -1,37 +1,66 @@
|
||||||
from core.services.payment_phase.payment_state import PaymentData
|
# core
|
||||||
from core.services.subscriptions.check_payment_loop import CheckPaidTimer
|
from core.services.subscriptions.check_payment_loop import CheckPaidTimer
|
||||||
from core.services.subscriptions.subscriptions_by_protocol import create_invoice, save_billing_code, return_pre_existing_payment_data, get_profile_subscription
|
from core.services.subscriptions.subscriptions_by_protocol import create_invoice, save_billing_code, get_profile_subscription
|
||||||
from core.models.enum_models import PaymentType
|
from core.models.enum_models import PaymentType
|
||||||
from core.models.pydantic_models.ServerReply import SubscriptionInvoice
|
|
||||||
from core.models.Result import Result
|
|
||||||
from core.models.Subscription import Subscription
|
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
|
|
||||||
|
|
||||||
# gui
|
# gui
|
||||||
from gui.v2.infrastructure.ThreadSafetyTool import ThreadSafetyTool
|
from gui.v2.infrastructure.ThreadSafetyTool import ThreadSafetyTool
|
||||||
from gui.v2.infrastructure.take_plumbing_action import take_action
|
from gui.v2.infrastructure.take_plumbing_action import take_action
|
||||||
from gui.v2.infrastructure.setup_observers import connection_observer
|
from gui.v2.infrastructure.setup_observers import connection_observer
|
||||||
|
|
||||||
|
# generic
|
||||||
from typing import Callable, Optional
|
from typing import Callable, Optional
|
||||||
|
|
||||||
def gui_starts_invoice(profile_id: int, ui_caller: Callable) -> Result:
|
def gui_starts_invoice(profile_id: int, invoice_ui_caller: Callable, timer_resume_caller: Callable) -> str | None:
|
||||||
"""Create a new invoice if we don't have one yet, or re-use the saved data."""
|
"""Create a new invoice if we don't have one yet, or re-use the saved data. Returns any errors as strings for UI to display."""
|
||||||
|
|
||||||
subscription = get_profile_subscription(profile_id)
|
subscription = get_profile_subscription(profile_id)
|
||||||
print(f"in gui_starts_invoice, subscription is {subscription}")
|
|
||||||
|
|
||||||
if not subscription:
|
#----------------------------
|
||||||
logger.info(f"Starting a New Invoice for Profile {profile_id}..")
|
# INVOICE DATA
|
||||||
|
#----------------------------
|
||||||
take_action(
|
take_action(
|
||||||
action=create_invoice,
|
action=create_invoice,
|
||||||
ui_caller=ui_caller,
|
ui_caller=invoice_ui_caller,
|
||||||
profile_id=profile_id,
|
profile_id=profile_id,
|
||||||
connection_observer=connection_observer
|
connection_observer=connection_observer
|
||||||
)
|
)
|
||||||
return Result(valid=True)
|
|
||||||
else:
|
#----------------------------
|
||||||
return return_pre_existing_payment_data(profile_id=profile_id, subscription=subscription)
|
# FILTER
|
||||||
|
#----------------------------
|
||||||
|
if not subscription:
|
||||||
|
logger.info(f"Started a New Invoice for Profile {profile_id}..")
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not subscription.billing_pending:
|
||||||
|
logger.error("This function should not have been called if the invoice is already paid.")
|
||||||
|
return "Invoice already paid."
|
||||||
|
|
||||||
|
if not subscription.billing_code:
|
||||||
|
return "Previous subscription didn't have a billing code."
|
||||||
|
|
||||||
|
#----------------------------
|
||||||
|
# CHECK PAID ON PRE-EXISTING INVOICE
|
||||||
|
#----------------------------
|
||||||
|
logger.info("Resuming a pre-existing payment..")
|
||||||
|
|
||||||
|
# Setup PyQt6 GUI as mainthread to bring back to:
|
||||||
|
pyqt_threader = ThreadSafetyTool()
|
||||||
|
|
||||||
|
# setup the timer with the callback:
|
||||||
|
# it doesn't return result here. It calls the view_callback function.
|
||||||
|
check_paid_timer = CheckPaidTimer(
|
||||||
|
view_callback=timer_resume_caller,
|
||||||
|
billing_code=subscription.billing_code,
|
||||||
|
ui_dispatcher=pyqt_threader,
|
||||||
|
payment_type=PaymentType.CRYPTO,
|
||||||
|
connection_observer=connection_observer,
|
||||||
|
profile_id=profile_id
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def save_and_begin_timer(
|
def save_and_begin_timer(
|
||||||
|
|
@ -71,25 +100,8 @@ def save_and_begin_timer(
|
||||||
billing_code=billing_code,
|
billing_code=billing_code,
|
||||||
ui_dispatcher=pyqt_threader,
|
ui_dispatcher=pyqt_threader,
|
||||||
payment_type=payment_type,
|
payment_type=payment_type,
|
||||||
connection_observer=connection_observer
|
connection_observer=connection_observer,
|
||||||
|
profile_id=profile_id
|
||||||
)
|
)
|
||||||
|
|
||||||
return True # this is just that it started
|
return True # this is just that it started
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# def create_an_invoice(ui_caller: Callable, profile_id: int, connection_observer: ConnectionObserver) -> SubscriptionInvoice|str:
|
|
||||||
# """Create an Invoice for regular single profile billing"""
|
|
||||||
|
|
||||||
# take_action(
|
|
||||||
# action=create_invoice,
|
|
||||||
# ui_caller=ui_caller,
|
|
||||||
# profile_id=profile_id,
|
|
||||||
# connection_observer=connection_observer
|
|
||||||
# )
|
|
||||||
|
|
||||||
# subscription_plan_id=subscription_plan_id,
|
|
||||||
# location_id=location_id,
|
|
||||||
# protocol_choice=protocol_choice,
|
|
||||||
# currency=currency_choice,
|
|
||||||
|
|
|
||||||
|
|
@ -182,9 +182,19 @@ def _enable(request: dict[str, Any], emit: MenuCallback, max_resolution: str | N
|
||||||
if needs_download and current_connection() != "tor" and not request.get("allow_uninstalled_tor"):
|
if needs_download and current_connection() != "tor" and not request.get("allow_uninstalled_tor"):
|
||||||
return _confirmation(request, "tor_download", "The Tor browser is not installed; switch to Tor to download it or proceed over clearweb.")
|
return _confirmation(request, "tor_download", "The Tor browser is not installed; switch to Tor to download it or proceed over clearweb.")
|
||||||
request["allow_uninstalled_tor"] = True
|
request["allow_uninstalled_tor"] = True
|
||||||
|
|
||||||
|
# Payment not finished:
|
||||||
|
try:
|
||||||
|
if profile.subscription.billing_pending:
|
||||||
|
print("This is resuming a pre-done payment")
|
||||||
|
return {"status": "navigate", "destination": "payment_details"}
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Skipping billing resume check")
|
||||||
|
|
||||||
preparation = _prepare_subscription(profile, request)
|
preparation = _prepare_subscription(profile, request)
|
||||||
if preparation is not None:
|
if preparation is not None:
|
||||||
return preparation
|
return preparation
|
||||||
|
|
||||||
ignored = {"ignore_endpoint_verification": EndpointVerificationError,
|
ignored = {"ignore_endpoint_verification": EndpointVerificationError,
|
||||||
"ignore_profile_state_conflict": ProfileStateConflictError}
|
"ignore_profile_state_conflict": ProfileStateConflictError}
|
||||||
observer = ProfileObserver()
|
observer = ProfileObserver()
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,10 @@ class PaymentDetailsPage(Page):
|
||||||
return # error is already displayed in subfunction.
|
return # error is already displayed in subfunction.
|
||||||
|
|
||||||
# launches background thread tasks:
|
# launches background thread tasks:
|
||||||
gui_starts_invoice(profile_id=self.profile_id, ui_caller=self.receive_invoice)
|
error_msg = gui_starts_invoice(profile_id=self.profile_id, invoice_ui_caller=self.receive_invoice, timer_resume_caller=self.timer_updates_gui)
|
||||||
|
|
||||||
|
if error_msg:
|
||||||
|
self.show_a_popup(error_msg)
|
||||||
|
|
||||||
def create_initial_elements(self):
|
def create_initial_elements(self):
|
||||||
container = QWidget(self)
|
container = QWidget(self)
|
||||||
|
|
@ -250,6 +252,9 @@ class PaymentDetailsPage(Page):
|
||||||
)
|
)
|
||||||
self.fields["address"].setText(elided_text)
|
self.fields["address"].setText(elided_text)
|
||||||
|
|
||||||
|
if self.currency:
|
||||||
|
self.fields["currency"].setText(self.currency.value)
|
||||||
|
|
||||||
# Now that we have the data populated, show the QR code:
|
# Now that we have the data populated, show the QR code:
|
||||||
self.qr_code_button.setDisabled(False)
|
self.qr_code_button.setDisabled(False)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue