diff --git a/gui/v2/actions/payment_actions.py b/gui/v2/actions/payment_actions.py index a36ec83..a404d61 100644 --- a/gui/v2/actions/payment_actions.py +++ b/gui/v2/actions/payment_actions.py @@ -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.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.pydantic_models.ServerReply import SubscriptionInvoice -from core.models.Result import Result -from core.models.Subscription import Subscription from core.errors.logger import logger - # gui from gui.v2.infrastructure.ThreadSafetyTool import ThreadSafetyTool from gui.v2.infrastructure.take_plumbing_action import take_action from gui.v2.infrastructure.setup_observers import connection_observer +# generic from typing import Callable, Optional -def gui_starts_invoice(profile_id: int, ui_caller: Callable) -> Result: - """Create a new invoice if we don't have one yet, or re-use the saved data.""" +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. Returns any errors as strings for UI to display.""" subscription = get_profile_subscription(profile_id) - print(f"in gui_starts_invoice, subscription is {subscription}") + #---------------------------- + # INVOICE DATA + #---------------------------- + take_action( + action=create_invoice, + ui_caller=invoice_ui_caller, + profile_id=profile_id, + connection_observer=connection_observer + ) + + #---------------------------- + # FILTER + #---------------------------- if not subscription: - logger.info(f"Starting a New Invoice for Profile {profile_id}..") - take_action( - action=create_invoice, - ui_caller=ui_caller, - profile_id=profile_id, - connection_observer=connection_observer - ) - return Result(valid=True) - else: - return return_pre_existing_payment_data(profile_id=profile_id, subscription=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( @@ -71,25 +100,8 @@ def save_and_begin_timer( billing_code=billing_code, ui_dispatcher=pyqt_threader, payment_type=payment_type, - connection_observer=connection_observer + connection_observer=connection_observer, + profile_id=profile_id ) 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, diff --git a/gui/v2/actions/profile_operations.py b/gui/v2/actions/profile_operations.py index 5376497..85ab208 100755 --- a/gui/v2/actions/profile_operations.py +++ b/gui/v2/actions/profile_operations.py @@ -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"): 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 + + # 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) if preparation is not None: return preparation + ignored = {"ignore_endpoint_verification": EndpointVerificationError, "ignore_profile_state_conflict": ProfileStateConflictError} observer = ProfileObserver() diff --git a/gui/v2/ui/pages/payments2.py b/gui/v2/ui/pages/payments2.py index 2bb9fa3..062c6ca 100644 --- a/gui/v2/ui/pages/payments2.py +++ b/gui/v2/ui/pages/payments2.py @@ -57,8 +57,10 @@ class PaymentDetailsPage(Page): return # error is already displayed in subfunction. # 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): container = QWidget(self) @@ -250,6 +252,9 @@ class PaymentDetailsPage(Page): ) 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: self.qr_code_button.setDisabled(False)