708 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			708 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| -- Initialize QBCore
 | |
| local QBCore = exports['qb-core']:GetCoreObject()
 | |
| 
 | |
| local isUiOpen = false
 | |
| local cooldown = false
 | |
| local pendingBills = {}
 | |
| 
 | |
| -- Command to open main billing menu
 | |
| RegisterCommand('bill', function()
 | |
|     OpenMainBillingMenu()
 | |
| end, false)
 | |
| 
 | |
| -- Keybind registration
 | |
| RegisterKeyMapping('bill', 'Open Billing Menu', 'keyboard', 'F7') -- Default key is F7, can be changed in settings
 | |
| 
 | |
| -- Function to open the main billing menu
 | |
| function OpenMainBillingMenu()
 | |
|     lib.registerContext({
 | |
|         id = 'main_billing_menu',
 | |
|         title = 'Billing System',
 | |
|         options = {
 | |
|             {
 | |
|                 title = 'Rechnung erstellen',
 | |
|                 description = 'Sende eine Rechnung an einen Spieler in der Nähe',
 | |
|                 icon = 'file-invoice-dollar',
 | |
|                 onSelect = function()
 | |
|                     OpenCreateBillMenu()
 | |
|                 end
 | |
|             },
 | |
|             {
 | |
|                 title = 'Meine Rechnungen',
 | |
|                 description = 'Sehe & bezahle deine erhaltenen Rechnungen',
 | |
|                 icon = 'money-check',
 | |
|                 onSelect = function()
 | |
|                     ViewBills()
 | |
|                 end
 | |
|             }
 | |
|         }
 | |
|     })
 | |
|     
 | |
|     lib.showContext('main_billing_menu')
 | |
| end
 | |
| 
 | |
| -- Function to open the create bill menu
 | |
| function OpenCreateBillMenu()
 | |
|     if cooldown then
 | |
|         lib.notify({
 | |
|             title = 'Billing System',
 | |
|             description = 'Bitte warte, bevor du das Abrechnungssystem erneut verwendest',
 | |
|             type = 'error'
 | |
|         })
 | |
|         return
 | |
|     end
 | |
|     
 | |
|     -- Get nearby players
 | |
|     local players = GetNearbyPlayers()
 | |
|     if #players == 0 then
 | |
|         lib.notify({
 | |
|             title = 'Billing System',
 | |
|             description = 'Keine Spieler in der Nähe zum Abrechnen',
 | |
|             type = 'error'
 | |
|         })
 | |
|         return
 | |
|     end
 | |
|     
 | |
|     -- Get player's accounts for receiving payment
 | |
|     local accounts = lib.callback.await('ps-banking:server:getAccounts', false) or {}
 | |
|     local accountOptions = {}
 | |
|     
 | |
|     -- Add default bank account
 | |
|     table.insert(accountOptions, {
 | |
|         value = 'personal',
 | |
|         label = 'Persönliches Bankkonto'
 | |
|     })
 | |
|     
 | |
|     -- Add other accounts
 | |
|     for _, account in ipairs(accounts) do
 | |
|         table.insert(accountOptions, {
 | |
|             value = account.id,
 | |
|             label = account.holder .. ' - ' .. account.cardNumber
 | |
|         })
 | |
|     end
 | |
|     
 | |
|     -- Show the list of nearby players
 | |
|     local playerOptions = {}
 | |
|     for _, player in ipairs(players) do
 | |
|         table.insert(playerOptions, {
 | |
|             title = player.name,
 | |
|             description = 'ID: ' .. player.id,
 | |
|             icon = 'user',
 | |
|             onSelect = function()
 | |
|                 -- When a player is selected, show the billing form
 | |
|                 ShowBillingForm(player, accountOptions)
 | |
|             end
 | |
|         })
 | |
|     end
 | |
|     
 | |
|     -- Register and show the player selection menu
 | |
|     lib.registerContext({
 | |
|         id = 'nearby_players_menu',
 | |
|         title = 'Spieler zum Abrechnen auswählen',
 | |
|         menu = 'main_billing_menu', -- Add back button to main menu
 | |
|         options = playerOptions
 | |
|     })
 | |
|     
 | |
|     lib.showContext('nearby_players_menu')
 | |
| end
 | |
| 
 | |
| -- Function to show the billing form after selecting a player
 | |
| function ShowBillingForm(selectedPlayer, accountOptions)
 | |
|     local input = lib.inputDialog('Rechnung erstellen für ' .. selectedPlayer.name, {
 | |
|         {
 | |
|             type = 'number',
 | |
|             label = 'Betrag ($)',
 | |
|             description = 'Gib den Rechnungsbetrag ein',
 | |
|             icon = 'dollar-sign',
 | |
|             required = true,
 | |
|             min = 1,
 | |
|             max = 100000
 | |
|         },
 | |
|         {
 | |
|             type = 'input',
 | |
|             label = 'Grund',
 | |
|             description = 'Gib den Grund für die Rechnung ein',
 | |
|             placeholder = 'Erbrachte Dienstleistungen...',
 | |
|             required = true
 | |
|         },
 | |
|         {
 | |
|             type = 'select',
 | |
|             label = 'Empfangskonto',
 | |
|             options = accountOptions,
 | |
|             required = true
 | |
|         }
 | |
|     })
 | |
|     
 | |
|     if not input then return end
 | |
|     
 | |
|     -- Play animation
 | |
|     PlayBillingAnimation()
 | |
|     
 | |
|     -- Send the bill
 | |
|     local billData = lib.callback.await('billing:server:sendBill', false, {
 | |
|         playerId = selectedPlayer.id,
 | |
|         amount = input[1],
 | |
|         reason = input[2],
 | |
|         account = input[3]
 | |
|     })
 | |
|     
 | |
|     if billData and billData.success then
 | |
|         lib.notify({
 | |
|             title = 'Billing System',
 | |
|             description = 'Rechnung erfolgreich an ' .. selectedPlayer.name .. ' gesendet',
 | |
|             type = 'success'
 | |
|         })
 | |
|         
 | |
|         -- Set cooldown
 | |
|         cooldown = true
 | |
|         SetTimeout(5000, function()
 | |
|             cooldown = false
 | |
|         end)
 | |
|         
 | |
|         -- Add to pending bills
 | |
|         pendingBills[billData.billId] = {
 | |
|             player = selectedPlayer,
 | |
|             amount = input[1],
 | |
|             reason = input[2],
 | |
|             account = input[3],
 | |
|             timestamp = GetGameTimer()
 | |
|         }
 | |
|         
 | |
|         -- Show waiting screen with all details
 | |
|         ShowWaitingScreen(billData.billId, selectedPlayer.name, input[1], input[2])
 | |
|     else
 | |
|         lib.notify({
 | |
|             title = 'Billing System',
 | |
|             description = 'Fehler beim Senden der Rechnung',
 | |
|             type = 'error'
 | |
|         })
 | |
|         
 | |
|         -- Return to main menu
 | |
|         OpenMainBillingMenu()
 | |
|     end
 | |
| end
 | |
| 
 | |
| -- Function to show waiting screen
 | |
| function ShowWaitingScreen(billId, playerName, amount, reason)
 | |
|     -- Create a more informative waiting screen
 | |
|     lib.registerContext({
 | |
|         id = 'bill_waiting_screen',
 | |
|         title = 'Warte auf Zahlung',
 | |
|         options = {
 | |
|             {
 | |
|                 title = 'Rechnung Details',
 | |
|                 description = 'Gesendet an: ' .. playerName,
 | |
|                 metadata = {
 | |
|                     {label = 'Betrag', value = '$' .. amount},
 | |
|                     {label = 'Grund', value = reason},
 | |
|                     {label = 'Status', value = 'Warte auf Antwort...'},
 | |
|                 },
 | |
|                 icon = 'file-invoice-dollar',
 | |
|                 disabled = true
 | |
|             },
 | |
|             {
 | |
|                 title = 'Warte auf Antwort',
 | |
|                 progress = 100, -- This creates a loading bar
 | |
|                 description = playerName .. ' entscheidet über die Rechnung',
 | |
|                 icon = 'clock',
 | |
|                 disabled = true
 | |
|             },
 | |
|             {
 | |
|                 title = 'Abbrechen',
 | |
|                 description = 'Zurück zum Hauptmenü',
 | |
|                 icon = 'times-circle',
 | |
|                 onSelect = function()
 | |
|                     pendingBills[billId] = nil
 | |
|                     OpenMainBillingMenu()
 | |
|                 end
 | |
|             }
 | |
|         }
 | |
|     })
 | |
|     
 | |
|     lib.showContext('bill_waiting_screen')
 | |
|     
 | |
|     -- Start a loading animation
 | |
|     Citizen.CreateThread(function()
 | |
|         local dots = 0
 | |
|         local loadingText = {'Warte', 'Warte.', 'Warte..', 'Warte...'}
 | |
|         local progress = 100
 | |
|         
 | |
|         while pendingBills[billId] do
 | |
|             Citizen.Wait(500)
 | |
|             dots = (dots + 1) % 4
 | |
|             
 | |
|             -- Update the context menu with new loading text
 | |
|             lib.registerContext({
 | |
|                 id = 'bill_waiting_screen',
 | |
|                 title = 'Warte auf Zahlung',
 | |
|                 options = {
 | |
|                     {
 | |
|                         title = 'Rechnung Details',
 | |
|                         description = 'Gesendet an: ' .. playerName,
 | |
|                         metadata = {
 | |
|                             {label = 'Betrag', value = '$' .. amount},
 | |
|                             {label = 'Grund', value = reason},
 | |
|                             {label = 'Status', value = 'Warte auf Antwort...'},
 | |
|                         },
 | |
|                         icon = 'file-invoice-dollar',
 | |
|                         disabled = true
 | |
|                     },
 | |
|                     {
 | |
|                         title = loadingText[dots + 1],
 | |
|                         progress = progress,
 | |
|                         description = playerName .. ' entscheidet über die Rechnung',
 | |
|                         icon = 'clock',
 | |
|                         disabled = true
 | |
|                     },
 | |
|                     {
 | |
|                         title = 'Abbrechen',
 | |
|                         description = 'Zurück zum Hauptmenü',
 | |
|                         icon = 'times-circle',
 | |
|                         onSelect = function()
 | |
|                             pendingBills[billId] = nil
 | |
|                             OpenMainBillingMenu()
 | |
|                         end
 | |
|                     }
 | |
|                 }
 | |
|             })
 | |
|             
 | |
|             -- Only refresh the context if it's still showing
 | |
|             if isMenuOpen('bill_waiting_screen') then
 | |
|                 lib.showContext('bill_waiting_screen')
 | |
|             else
 | |
|                 break
 | |
|             end
 | |
|             
 | |
|             -- Cycle the progress bar
 | |
|             progress = progress - 5
 | |
|             if progress <= 0 then
 | |
|                 progress = 100
 | |
|             end
 | |
|         end
 | |
|     end)
 | |
| end
 | |
| 
 | |
| -- Helper function to check if a menu is open
 | |
| function isMenuOpen(menuId)
 | |
|     -- This is a placeholder - ox_lib doesn't provide a direct way to check
 | |
|     -- You might need to track this yourself or use a different approach
 | |
|     return true
 | |
| end
 | |
| 
 | |
| -- Function to show payment account selection
 | |
| function ShowPaymentAccountSelection(billId, amount, description)
 | |
|     -- Get player's accounts for payment
 | |
|     local accounts = lib.callback.await('ps-banking:server:getAccounts', false) or {}
 | |
|     local accountOptions = {}
 | |
|     
 | |
|     -- Add default bank account
 | |
|     table.insert(accountOptions, {
 | |
|         value = 'personal',
 | |
|         label = 'Persönliches Bankkonto',
 | |
|         description = 'Bezahlen mit deinem Hauptkonto'
 | |
|     })
 | |
|     
 | |
|     -- Add other accounts
 | |
|     for _, account in ipairs(accounts) do
 | |
|         table.insert(accountOptions, {
 | |
|             value = account.id,
 | |
|             label = account.holder .. ' - ' .. account.cardNumber,
 | |
|             description = 'Kontostand: $' .. account.balance
 | |
|         })
 | |
|     end
 | |
|     
 | |
|     -- Register and show the account selection menu
 | |
|     lib.registerContext({
 | |
|         id = 'payment_account_menu',
 | |
|         title = 'Wähle Zahlungskonto',
 | |
|         menu = 'billing_menu', -- Add back button to bills menu
 | |
|         options = accountOptions,
 | |
|         onExit = function()
 | |
|             ViewBills() -- Return to bills menu
 | |
|         end,
 | |
|         onSelect = function(selected)
 | |
|             local accountId = selected.value
 | |
|             
 | |
|             local confirm = lib.alertDialog({
 | |
|                 header = 'Rechnung bezahlen',
 | |
|                 content = ('Möchtest du $%s für %s von diesem Konto bezahlen?'):format(amount, description),
 | |
|                 centered = true,
 | |
|                 cancel = true
 | |
|             })
 | |
|             
 | |
|             if confirm == 'confirm' then
 | |
|                 local success = lib.callback.await('billing:server:payBillFromAccount', false, {
 | |
|                     billId = billId,
 | |
|                     accountId = accountId
 | |
|                 })
 | |
|                 
 | |
|                 if success then
 | |
|                     lib.notify({
 | |
|                         title = 'Billing System',
 | |
|                         description = 'Rechnung erfolgreich bezahlt',
 | |
|                         type = 'success'
 | |
|                     })
 | |
|                     ViewBills() -- Refresh the list
 | |
|                 else
 | |
|                     lib.notify({
 | |
|                         title = 'Billing System',
 | |
|                         description = 'Fehler beim Bezahlen der Rechnung. Unzureichendes Guthaben.',
 | |
|                         type = 'error'
 | |
|                     })
 | |
|                 end
 | |
|             end
 | |
|         end
 | |
|     })
 | |
|     
 | |
|     lib.showContext('payment_account_menu')
 | |
| end
 | |
| 
 | |
| -- Function to view received bills
 | |
| function ViewBills()
 | |
|     -- Get all bills from ps-banking
 | |
|     local bills = lib.callback.await('ps-banking:server:getBills', false)
 | |
|     
 | |
|     if not bills or #bills == 0 then
 | |
|         lib.notify({
 | |
|             title = 'Billing System',
 | |
|             description = 'Du hast keine unbezahlten Rechnungen',
 | |
|             type = 'info'
 | |
|         })
 | |
|         
 | |
|         -- Return to main menu after a short delay
 | |
|         SetTimeout(1000, function()
 | |
|             OpenMainBillingMenu()
 | |
|         end)
 | |
|         return
 | |
|     end
 | |
|     
 | |
|     -- Get bill statuses from our custom table
 | |
|     local billStatuses = lib.callback.await('billing:server:getAllBillStatuses', false)
 | |
|     local statusMap = {}
 | |
|     
 | |
|     -- Create a map of bill ID to status for quick lookup
 | |
|     if billStatuses then
 | |
|         for _, status in ipairs(billStatuses) do
 | |
|             statusMap[status.bill_id] = status
 | |
|         end
 | |
|     end
 | |
|     
 | |
|     local billOptions = {}
 | |
|     for _, bill in ipairs(bills) do
 | |
|         local timestamp = os.date('%Y-%m-%d %H:%M', bill.date)
 | |
|         
 | |
|         -- Check if bill is declined in our custom table
 | |
|         local billStatus = statusMap[bill.id]
 | |
|         local isDeclined = billStatus and billStatus.declined == 1
 | |
|         
 | |
|         local status = 'Unbezahlt'
 | |
|         if bill.isPaid then
 | |
|             status = 'Bezahlt'
 | |
|         elseif isDeclined then
 | |
|             status = 'Abgelehnt'
 | |
|         end
 | |
|         
 | |
|         table.insert(billOptions, {
 | |
|             title = bill.description,
 | |
|             description = ('Betrag: $%s | Datum: %s'):format(bill.amount, timestamp),
 | |
|             icon = 'file-invoice',
 | |
|             metadata = {
 | |
|                 {label = 'Rechnungs-ID', value = bill.id},
 | |
|                 {label = 'Typ', value = bill.type},
 | |
|                 {label = 'Status', value = status}
 | |
|             },
 | |
|             onSelect = function()
 | |
|                 if not bill.isPaid and not isDeclined then
 | |
|                     -- Show account selection for payment
 | |
|                     ShowPaymentAccountSelection(bill.id, bill.amount, bill.description)
 | |
|                 end
 | |
|             end
 | |
|         })
 | |
|     end
 | |
|     
 | |
|     lib.registerContext({
 | |
|         id = 'billing_menu',
 | |
|         title = 'Deine Rechnungen',
 | |
|         menu = 'main_billing_menu', -- Add back button to main menu
 | |
|         options = billOptions
 | |
|     })
 | |
|     
 | |
|     lib.showContext('billing_menu')
 | |
| end
 | |
| 
 | |
| -- Helper function to get nearby players
 | |
| function GetNearbyPlayers()
 | |
|     local playerPed = PlayerPedId()
 | |
|     local playerCoords = GetEntityCoords(playerPed)
 | |
|     local players = {}
 | |
|     
 | |
|     -- Get all players
 | |
|     local allPlayers = GetActivePlayers()
 | |
|     
 | |
|     for _, player in ipairs(allPlayers) do
 | |
|         local targetPed = GetPlayerPed(player)
 | |
|         local targetCoords = GetEntityCoords(targetPed)
 | |
|         local distance = #(playerCoords - targetCoords)
 | |
|         
 | |
|         if distance <= 5.0 and targetPed ~= playerPed then
 | |
|             local targetId = GetPlayerServerId(player)
 | |
|             local targetName = GetPlayerName(player)
 | |
|             table.insert(players, {id = targetId, name = targetName})
 | |
|         end
 | |
|     end
 | |
|     
 | |
|     return players
 | |
| end
 | |
| 
 | |
| -- Animation function
 | |
| function PlayBillingAnimation()
 | |
|     lib.requestAnimDict("cellphone@")
 | |
|     
 | |
|     -- Request the prop model
 | |
|     local propModel = 'bzzz_prop_payment_terminal'
 | |
|     lib.requestModel(propModel)
 | |
|     
 | |
|     -- Create prop
 | |
|     local playerPed = PlayerPedId()
 | |
|     local coords = GetEntityCoords(playerPed)
 | |
|     local prop = CreateObject(GetHashKey(propModel), coords.x, coords.y, coords.z, true, true, true)
 | |
|     
 | |
|     -- Attach prop to player
 | |
|     AttachEntityToEntity(prop, playerPed, GetPedBoneIndex(playerPed, 57005), 
 | |
|         0.18, 0.01, 0.0, -54.0, 220.0, 43.0, 
 | |
|         true, true, false, true, 1, true)
 | |
|     
 | |
|     -- Play animation
 | |
|     TaskPlayAnim(playerPed, "cellphone@", "cellphone_text_read_base", 2.0, 3.0, -1, 49, 0, false, false, false)
 | |
|     
 | |
|     -- Wait for animation to complete
 | |
|     Wait(5000)
 | |
|     
 | |
|     -- Clear animation and delete prop
 | |
|     ClearPedTasks(playerPed)
 | |
|     DeleteEntity(prop)
 | |
| end
 | |
| 
 | |
| -- Event to show payment prompt when receiving a bill
 | |
| RegisterNetEvent('billing:client:showPaymentPrompt', function(data)
 | |
|     -- Play a notification sound
 | |
|     PlaySound(-1, "Event_Start_Text", "GTAO_FM_Events_Soundset", 0, 0, 1)
 | |
|     
 | |
|     -- Get player's accounts for payment
 | |
|     local accounts = lib.callback.await('ps-banking:server:getAccounts', false) or {}
 | |
|     local accountOptions = {}
 | |
|     
 | |
|     -- Add default bank account
 | |
|     table.insert(accountOptions, {
 | |
|         title = 'Persönliches Bankkonto',
 | |
|         description = 'Bezahlen mit deinem Hauptkonto',
 | |
|         icon = 'credit-card',
 | |
|         onSelect = function()
 | |
|             local success = lib.callback.await('billing:server:handleBillResponse', false, {
 | |
|                 action = 'pay',
 | |
|                 billId = data.billId,
 | |
|                 accountId = 'personal'
 | |
|             })
 | |
|             
 | |
|             if success then
 | |
|                 lib.notify({
 | |
|                     title = 'Rechnung bezahlt',
 | |
|                     description = 'Du hast die Rechnung erfolgreich bezahlt',
 | |
|                     type = 'success'
 | |
|                 })
 | |
|                 
 | |
|                 -- Notify the sender
 | |
|                 TriggerServerEvent('billing:server:notifyBillSender', data.billId, 'pay')
 | |
|             else
 | |
|                 lib.notify({
 | |
|                     title = 'Zahlung fehlgeschlagen',
 | |
|                     description = 'Du hast nicht genug Geld auf deinem Konto',
 | |
|                     type = 'error'
 | |
|                 })
 | |
|             end
 | |
|         end
 | |
|     })
 | |
|     
 | |
|     -- Add other accounts
 | |
|     for _, account in ipairs(accounts) do
 | |
|         table.insert(accountOptions, {
 | |
|             title = account.holder .. ' - ' .. account.cardNumber,
 | |
|             description = 'Kontostand: $' .. account.balance,
 | |
|             icon = 'university',
 | |
|             onSelect = function()
 | |
|                 local success = lib.callback.await('billing:server:handleBillResponse', false, {
 | |
|                     action = 'pay',
 | |
|                     billId = data.billId,
 | |
|                     accountId = account.id
 | |
|                 })
 | |
|                 
 | |
|                 if success then
 | |
|                     lib.notify({
 | |
|                         title = 'Rechnung bezahlt',
 | |
|                         description = 'Du hast die Rechnung erfolgreich bezahlt',
 | |
|                         type = 'success'
 | |
|                     })
 | |
|                     
 | |
|                     -- Notify the sender
 | |
|                     TriggerServerEvent('billing:server:notifyBillSender', data.billId, 'pay')
 | |
|                 else
 | |
|                     lib.notify({
 | |
|                         title = 'Zahlung fehlgeschlagen',
 | |
|                         description = 'Nicht genug Geld auf diesem Konto',
 | |
|                         type = 'error'
 | |
|                     })
 | |
|                 end
 | |
|             end
 | |
|         })
 | |
|     end
 | |
|     
 | |
|     -- Create the payment prompt
 | |
|     lib.registerContext({
 | |
|         id = 'bill_payment_prompt',
 | |
|         title = 'Neue Rechnung erhalten',
 | |
|         options = {
 | |
|             {
 | |
|                 title = 'Rechnung Details',
 | |
|                 description = 'Von: ' .. data.sender,
 | |
|                 metadata = {
 | |
|                     {label = 'Betrag', value = '$' .. data.amount},
 | |
|                     {label = 'Grund', value = data.reason},
 | |
|                 }
 | |
|             },
 | |
|             {
 | |
|                 title = 'Bezahlen',
 | |
|                 description = 'Wähle ein Konto zum Bezahlen',
 | |
|                 icon = 'money-bill',
 | |
|                 menu = 'payment_account_selection'
 | |
|             },
 | |
|             {
 | |
|                 title = 'Ablehnen',
 | |
|                 description = 'Rechnung ablehnen',
 | |
|                 icon = 'times-circle',
 | |
|                 onSelect = function()
 | |
|                     local confirm = lib.alertDialog({
 | |
|                         header = 'Rechnung ablehnen',
 | |
|                         content = 'Bist du sicher, dass du diese Rechnung ablehnen möchtest?',
 | |
|                         centered = true,
 | |
|                         cancel = true
 | |
|                     })
 | |
|                     
 | |
|                     if confirm == 'confirm' then
 | |
|                         local success = lib.callback.await('billing:server:handleBillResponse', false, {
 | |
|                             action = 'decline',
 | |
|                             billId = data.billId
 | |
|                         })
 | |
|                         
 | |
|                         if success then
 | |
|                             lib.notify({
 | |
|                                 title = 'Rechnung abgelehnt',
 | |
|                                 description = 'Du hast die Rechnung abgelehnt',
 | |
|                                 type = 'info'
 | |
|                             })
 | |
|                             
 | |
|                             -- Notify the sender
 | |
|                             TriggerServerEvent('billing:server:notifyBillSender', data.billId, 'decline')
 | |
|                         else
 | |
|                             lib.notify({
 | |
|                                 title = 'Fehler',
 | |
|                                 description = 'Fehler beim Ablehnen der Rechnung',
 | |
|                                 type = 'error'
 | |
|                             })
 | |
|                         end
 | |
|                     end
 | |
|                 end
 | |
|             }
 | |
|             -- "Pay Later" option removed
 | |
|         }
 | |
|     })
 | |
|     
 | |
|     -- Register the account selection submenu
 | |
|     lib.registerContext({
 | |
|         id = 'payment_account_selection',
 | |
|         title = 'Wähle Zahlungskonto',
 | |
|         menu = 'bill_payment_prompt',
 | |
|         options = accountOptions
 | |
|     })
 | |
|     
 | |
|     -- Show the payment prompt
 | |
|     lib.showContext('bill_payment_prompt')
 | |
| end)
 | |
| 
 | |
| -- Event to handle bill response
 | |
| RegisterNetEvent('billing:client:billResponse', function(billId, action, playerName)
 | |
|     -- Check if this bill is in our pending bills
 | |
|     if pendingBills[billId] then
 | |
|         local bill = pendingBills[billId]
 | |
|         
 | |
|         if action == 'pay' then
 | |
|             lib.notify({
 | |
|                 title = 'Rechnung bezahlt',
 | |
|                 description = playerName .. ' hat deine Rechnung über $' .. bill.amount .. ' bezahlt',
 | |
|                 type = 'success',
 | |
|                 duration = 7000
 | |
|             })
 | |
|             
 | |
|             -- Show a more detailed success message
 | |
|             lib.alertDialog({
 | |
|                 header = 'Zahlung erhalten',
 | |
|                 content = playerName .. ' hat deine Rechnung über $' .. bill.amount .. ' für "' .. bill.reason .. '" bezahlt.',
 | |
|                 centered = true,
 | |
|                 cancel = false
 | |
|             })
 | |
|         elseif action == 'decline' then
 | |
|             lib.notify({
 | |
|                 title = 'Rechnung abgelehnt',
 | |
|                 description = playerName .. ' hat deine Rechnung über $' .. bill.amount .. ' abgelehnt',
 | |
|                 type = 'error',
 | |
|                 duration = 7000
 | |
|             })
 | |
|             
 | |
|             -- Show a more detailed decline message
 | |
|             lib.alertDialog({
 | |
|                 header = 'Rechnung abgelehnt',
 | |
|                 content = playerName .. ' hat deine Rechnung über $' .. bill.amount .. ' für "' .. bill.reason .. '" abgelehnt.',
 | |
|                 centered = true,
 | |
|                 cancel = false
 | |
|             })
 | |
|         end
 | |
|         -- "later" case removed
 | |
|         
 | |
|         -- Remove from pending bills
 | |
|         pendingBills[billId] = nil
 | |
|         
 | |
|         -- Return to main menu
 | |
|         OpenMainBillingMenu()
 | |
|     end
 | |
| end)
 | |
| 
 | |
| -- Event handler for opening bills menu from command
 | |
| RegisterNetEvent('billing:client:openBillsMenu', function()
 | |
|     ViewBills()
 | |
| end)
 | |
| 
 | |
| -- Check for timed out bills every minute
 | |
| Citizen.CreateThread(function()
 | |
|     while true do
 | |
|         Citizen.Wait(60000) -- Check every minute
 | |
|         
 | |
|         local currentTime = GetGameTimer()
 | |
|         local timeoutBills = {}
 | |
|         
 | |
|         for billId, bill in pairs(pendingBills) do
 | |
|             -- If bill is older than 5 minutes, consider it timed out
 | |
|             if (currentTime - bill.timestamp) > 300000 then
 | |
|                 table.insert(timeoutBills, billId)
 | |
|             end
 | |
|         end
 | |
|         
 | |
|         -- Clean up timed out bills
 | |
|         for _, billId in ipairs(timeoutBills) do
 | |
|             lib.notify({
 | |
|                 title = 'Rechnung Timeout',
 | |
|                 description = 'Keine Antwort von ' .. pendingBills[billId].player.name .. ' erhalten',
 | |
|                 type = 'warning'
 | |
|             })
 | |
|             pendingBills[billId] = nil
 | |
|         end
 | |
|     end
 | |
| end)
 | 
