hydraveil-gui/gui/v2/actions/ticket_actions.py

162 lines
No EOL
5.7 KiB
Python

# 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 fetch_ticket_invoice(invoice_ui_caller: Callable, timer_resume_caller: Callable) -> str | None:
# """Start the Ticketing process on the background thread with the relevant billing data."""
# logger.info("fetching ticket invoice..")
# payment_cycle = OverallPaymentCycle()
# if not payment_cycle:
# "No payment cycle, and therefore no data."
# # already existing but wrong format:
# if payment_cycle.category != PaymentCategory.TICKET:
# return "Wrong payment cycle category."
# billing_data = payment_cycle.instance
# if not billing_data:
# return "No billing data"
# # if not isinstance(billing_data, TicketPaymentData):
# # return "Billing data in the wrong format."
# which_key = billing_data.which_key
# currency = billing_data.currency
# how_many_profiles = billing_data.how_many_profiles
# # Fetch (this function will complain if missing data):
# take_action(
# action=initiate_payment,
# ui_caller=invoice_ui_caller,
# how_many_profiles=how_many_profiles,
# which_key=which_key,
# which_cryptocurrency=currency,
# ticket_observer=ticket_observer,
# connection_observer=connection_observer,
# bypass_existing=True,
# )
# logger.info("Initiated payment")
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)