# core from core.controllers.tickets.UseTicketController import use_ticket from core.models.BaseProfile import BaseProfile as Profile from core.controllers.ProfileController import ProfileController from core.controllers.tickets.TicketPayController import initiate_payment from core.services.subscriptions.subscriptions_by_protocol import start_new_payment_cycle, save_subscription, get_ticket_invoice from core.services.payment_phase.payment_state import OverallPaymentCycle from core.models.enum_models import PaymentCategory from core.services.prepare_tickets.ticket_tracker import get_all_unused_tickets from core.models.Result import Result, ResultError from core.errors.logger import logger # gui from gui.v2.infrastructure.take_plumbing_action import take_action from gui.v2.infrastructure.setup_observers import connection_observer, ticket_observer # generic: from typing import Callable def start_ticket(ui_caller: Callable) -> Result: logger.info("started ticketing billing state") return take_action( action=start_new_payment_cycle, category=PaymentCategory.TICKET, ui_caller=ui_caller ) def fetch_ticket_invoice(ui_caller: Callable) -> str | None: return take_action( action=get_ticket_invoice, ui_caller=ui_caller, connection_observer=connection_observer ) def get_ticket_data() -> Result: """This is running in the background ALREADY. Get & format a list of unused tickets from core""" ticket_results = get_all_unused_tickets() valid = ticket_results.get('valid') if not valid: message = ticket_results.get('message') if not message: message = "Error gathering ticket data" Result(valid=False, error_type=ResultError.MISSING_FILE, message=message) raw_tickets = ticket_results.get('data') print(f"raw_tickets is {raw_tickets}") if not raw_tickets: Result(valid=False, error_type=ResultError.NO_TICKET, message="No tickets available. Would you like to get some?") formatted_data = [(f"Ticket #{t}", t) for t in raw_tickets] print(f"formatted_data is {formatted_data}") return Result(valid=True, data=formatted_data) def use_a_ticket(profile_id: int, which_ticket: int, ui_caller: Callable) -> str | None: """Coordinate the use of a given ticket. Returns a string on error, or None on success""" try: profile = ProfileController.get(int(profile_id)) except Exception as e: return f"The selected profile of {str(profile_id)} is either malformed or missing. {str(e)}" which_location = profile.location.id protocol_choice = profile.connection.code PRE_REQS = [profile, which_ticket, which_location, protocol_choice, ui_caller] if None in PRE_REQS: return "You are missing one of the pre-reqs to use a ticket." ticket_user = TicketUser( actual_profile=profile, which_ticket=which_ticket, ui_caller=ui_caller ) ticket_user.begin_thread() return None # no error class TicketUser(): actual_profile: Profile which_ticket: int ui_caller: Callable def begin_thread(self): """Step 1, begin a background thread with use""" take_action( action=use_ticket, ui_caller=self.apply_code, which_location=self.which_location, protocol_choice=self.protocol_choice, ticket_observer=ticket_observer, connection_observer=connection_observer, ) def apply_code(self, result: Result): """Step 2. Check if it worked. If so, apply it""" if not result.valid: logger.error("Use failed, returning to UI layer..") self.ui_caller(result) subscription = result.data if not subscription: logger.error("Use of ticket gave a blank subscription, returning to UI layer..") self.ui_caller(result) # core saves it: logger.info("saving subscription..") saved = save_subscription(profile=self.actual_profile, subscription=subscription) if not saved: error_msg = "Could not save the subscription" logger.error(error_msg) new_result = Result(valid=False, error_type=ResultError.FILE_SYSTEM, message=error_msg) self.ui_caller(new_result) logger.info("Saved sub, returning to UI layer..") self.ui_caller(result) def wipe_ticket_billing(): """Wipe existing data and start over."""