forked from Simnation/Main
ed
This commit is contained in:
parent
2fe7be05aa
commit
12740ce5d5
2 changed files with 246 additions and 57 deletions
|
@ -45,7 +45,7 @@ function OpenCreateBillMenu()
|
|||
if cooldown then
|
||||
lib.notify({
|
||||
title = 'Billing System',
|
||||
description = 'Please wait before using the billing system again',
|
||||
description = 'Bitte warte, bevor du das Abrechnungssystem erneut verwendest',
|
||||
type = 'error'
|
||||
})
|
||||
return
|
||||
|
@ -56,7 +56,7 @@ function OpenCreateBillMenu()
|
|||
if #players == 0 then
|
||||
lib.notify({
|
||||
title = 'Billing System',
|
||||
description = 'No players nearby to bill',
|
||||
description = 'Keine Spieler in der Nähe zum Abrechnen',
|
||||
type = 'error'
|
||||
})
|
||||
return
|
||||
|
@ -69,7 +69,7 @@ function OpenCreateBillMenu()
|
|||
-- Add default bank account
|
||||
table.insert(accountOptions, {
|
||||
value = 'personal',
|
||||
label = 'Personal Bank Account'
|
||||
label = 'Persönliches Bankkonto'
|
||||
})
|
||||
|
||||
-- Add other accounts
|
||||
|
@ -97,7 +97,7 @@ function OpenCreateBillMenu()
|
|||
-- Register and show the player selection menu
|
||||
lib.registerContext({
|
||||
id = 'nearby_players_menu',
|
||||
title = 'Select Player to Bill',
|
||||
title = 'Spieler zum Abrechnen auswählen',
|
||||
menu = 'main_billing_menu', -- Add back button to main menu
|
||||
options = playerOptions
|
||||
})
|
||||
|
@ -107,11 +107,11 @@ end
|
|||
|
||||
-- Function to show the billing form after selecting a player
|
||||
function ShowBillingForm(selectedPlayer, accountOptions)
|
||||
local input = lib.inputDialog('Create Bill for ' .. selectedPlayer.name, {
|
||||
local input = lib.inputDialog('Rechnung erstellen für ' .. selectedPlayer.name, {
|
||||
{
|
||||
type = 'number',
|
||||
label = 'Amount ($)',
|
||||
description = 'Enter the bill amount',
|
||||
label = 'Betrag ($)',
|
||||
description = 'Gib den Rechnungsbetrag ein',
|
||||
icon = 'dollar-sign',
|
||||
required = true,
|
||||
min = 1,
|
||||
|
@ -119,14 +119,14 @@ function ShowBillingForm(selectedPlayer, accountOptions)
|
|||
},
|
||||
{
|
||||
type = 'input',
|
||||
label = 'Reason',
|
||||
description = 'Enter the reason for the bill',
|
||||
placeholder = 'Services provided...',
|
||||
label = 'Grund',
|
||||
description = 'Gib den Grund für die Rechnung ein',
|
||||
placeholder = 'Erbrachte Dienstleistungen...',
|
||||
required = true
|
||||
},
|
||||
{
|
||||
type = 'select',
|
||||
label = 'Receiving Account',
|
||||
label = 'Empfangskonto',
|
||||
options = accountOptions,
|
||||
required = true
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ function ShowBillingForm(selectedPlayer, accountOptions)
|
|||
if success then
|
||||
lib.notify({
|
||||
title = 'Billing System',
|
||||
description = 'Bill sent successfully to ' .. selectedPlayer.name,
|
||||
description = 'Rechnung erfolgreich an ' .. selectedPlayer.name .. ' gesendet',
|
||||
type = 'success'
|
||||
})
|
||||
|
||||
|
@ -163,7 +163,7 @@ function ShowBillingForm(selectedPlayer, accountOptions)
|
|||
else
|
||||
lib.notify({
|
||||
title = 'Billing System',
|
||||
description = 'Failed to send bill',
|
||||
description = 'Fehler beim Senden der Rechnung',
|
||||
type = 'error'
|
||||
})
|
||||
end
|
||||
|
@ -176,7 +176,7 @@ function ViewBills()
|
|||
if not bills or #bills == 0 then
|
||||
lib.notify({
|
||||
title = 'Billing System',
|
||||
description = 'You have no unpaid bills',
|
||||
description = 'Du hast keine unbezahlten Rechnungen',
|
||||
type = 'info'
|
||||
})
|
||||
|
||||
|
@ -190,19 +190,32 @@ function ViewBills()
|
|||
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 billData = lib.callback.await('billing:server:getBillStatus', false, bill.id)
|
||||
local isDeclined = billData and billData.declined == 1
|
||||
|
||||
local status = 'Unbezahlt'
|
||||
if bill.isPaid then
|
||||
status = 'Bezahlt'
|
||||
elseif isDeclined then
|
||||
status = 'Abgelehnt'
|
||||
end
|
||||
|
||||
table.insert(billOptions, {
|
||||
title = bill.description,
|
||||
description = ('Amount: $%s | Date: %s'):format(bill.amount, timestamp),
|
||||
description = ('Betrag: $%s | Datum: %s'):format(bill.amount, timestamp),
|
||||
icon = 'file-invoice',
|
||||
metadata = {
|
||||
{label = 'Bill ID', value = bill.id},
|
||||
{label = 'Type', value = bill.type},
|
||||
{label = 'Status', value = bill.isPaid and 'Paid' or 'Unpaid'}
|
||||
{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
|
||||
local confirm = lib.alertDialog({
|
||||
header = 'Pay Bill',
|
||||
content = ('Do you want to pay $%s for %s?'):format(bill.amount, bill.description),
|
||||
header = 'Rechnung bezahlen',
|
||||
content = ('Möchtest du $%s für %s bezahlen?'):format(bill.amount, bill.description),
|
||||
centered = true,
|
||||
cancel = true
|
||||
})
|
||||
|
@ -212,25 +225,26 @@ function ViewBills()
|
|||
if success then
|
||||
lib.notify({
|
||||
title = 'Billing System',
|
||||
description = 'Bill paid successfully',
|
||||
description = 'Rechnung erfolgreich bezahlt',
|
||||
type = 'success'
|
||||
})
|
||||
ViewBills() -- Refresh the list
|
||||
else
|
||||
lib.notify({
|
||||
title = 'Billing System',
|
||||
description = 'Failed to pay bill. Insufficient funds.',
|
||||
description = 'Fehler beim Bezahlen der Rechnung. Unzureichendes Guthaben.',
|
||||
type = 'error'
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
lib.registerContext({
|
||||
id = 'billing_menu',
|
||||
title = 'Your Bills',
|
||||
title = 'Deine Rechnungen',
|
||||
menu = 'main_billing_menu', -- Add back button to main menu
|
||||
options = billOptions
|
||||
})
|
||||
|
@ -290,3 +304,98 @@ function PlayBillingAnimation()
|
|||
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)
|
||||
|
||||
-- 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 = 'Rechnung sofort bezahlen',
|
||||
icon = 'money-bill',
|
||||
onSelect = function()
|
||||
local success = lib.callback.await('billing:server:handleBillResponse', false, {
|
||||
action = 'pay',
|
||||
billId = data.billId
|
||||
})
|
||||
|
||||
if success then
|
||||
lib.notify({
|
||||
title = 'Rechnung bezahlt',
|
||||
description = 'Du hast die Rechnung erfolgreich bezahlt',
|
||||
type = 'success'
|
||||
})
|
||||
else
|
||||
lib.notify({
|
||||
title = 'Zahlung fehlgeschlagen',
|
||||
description = 'Du hast nicht genug Geld auf deinem Konto',
|
||||
type = 'error'
|
||||
})
|
||||
end
|
||||
end
|
||||
},
|
||||
{
|
||||
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'
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
},
|
||||
{
|
||||
title = 'Später bezahlen',
|
||||
description = 'Rechnung für später speichern',
|
||||
icon = 'clock',
|
||||
onSelect = function()
|
||||
lib.callback.await('billing:server:handleBillResponse', false, {
|
||||
action = 'later',
|
||||
billId = data.billId
|
||||
})
|
||||
|
||||
lib.notify({
|
||||
title = 'Rechnung gespeichert',
|
||||
description = 'Die Rechnung wurde für später gespeichert',
|
||||
type = 'info'
|
||||
})
|
||||
end
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
-- Show the payment prompt
|
||||
lib.showContext('bill_payment_prompt')
|
||||
end)
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
-- Initialize QBCore
|
||||
local QBCore = exports['qb-core']:GetCoreObject()
|
||||
|
||||
-- Register callback for sending bills
|
||||
lib.callback.register('billing:server:sendBill', function(source, data)
|
||||
local src = source
|
||||
|
@ -9,7 +12,7 @@ lib.callback.register('billing:server:sendBill', function(source, data)
|
|||
end
|
||||
|
||||
local senderName = player.PlayerData.charinfo.firstname .. ' ' .. player.PlayerData.charinfo.lastname
|
||||
local description = data.reason .. ' (From: ' .. senderName .. ')'
|
||||
local description = data.reason .. ' (Von: ' .. senderName .. ')'
|
||||
|
||||
-- Create the bill
|
||||
exports["ps-banking"]:createBill({
|
||||
|
@ -19,9 +22,16 @@ lib.callback.register('billing:server:sendBill', function(source, data)
|
|||
amount = data.amount,
|
||||
})
|
||||
|
||||
-- Store additional data about the bill if needed
|
||||
-- You could create a separate table to track which account the payment should go to
|
||||
MySQL.insert.await('INSERT INTO billing_accounts (bill_description, sender_id, receiver_id, account_id, amount, created_at) VALUES (?, ?, ?, ?, ?, NOW())', {
|
||||
-- Get the latest bill ID for this user (assuming it's the one we just created)
|
||||
local result = MySQL.query.await('SELECT id FROM ps_banking_bills WHERE identifier = ? ORDER BY id DESC LIMIT 1', {
|
||||
target.PlayerData.citizenid
|
||||
})
|
||||
|
||||
local billId = result[1] and result[1].id or nil
|
||||
|
||||
-- Store additional data about the bill
|
||||
MySQL.insert.await('INSERT INTO billing_accounts (bill_id, bill_description, sender_id, receiver_id, account_id, amount, created_at) VALUES (?, ?, ?, ?, ?, ?, NOW())', {
|
||||
billId,
|
||||
description,
|
||||
player.PlayerData.citizenid,
|
||||
target.PlayerData.citizenid,
|
||||
|
@ -29,18 +39,77 @@ lib.callback.register('billing:server:sendBill', function(source, data)
|
|||
data.amount
|
||||
})
|
||||
|
||||
-- Notify the target player
|
||||
TriggerClientEvent('QBCore:Notify', data.playerId, 'You received a bill for $' .. data.amount .. ' - ' .. data.reason, 'primary', 7500)
|
||||
-- Send payment prompt to target player
|
||||
TriggerClientEvent('billing:client:showPaymentPrompt', data.playerId, {
|
||||
billId = billId,
|
||||
amount = data.amount,
|
||||
reason = data.reason,
|
||||
sender = senderName
|
||||
})
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
-- Event handler for when a bill is paid
|
||||
RegisterNetEvent('billing:server:billPaid', function(billId)
|
||||
-- Add a callback to get bill status
|
||||
lib.callback.register('billing:server:getBillStatus', function(source, billId)
|
||||
local src = source
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
|
||||
if not player then return end
|
||||
if not player then return nil end
|
||||
|
||||
local result = MySQL.query.await('SELECT * FROM billing_accounts WHERE bill_id = ?', {billId})
|
||||
if result and #result > 0 then
|
||||
return result[1]
|
||||
end
|
||||
|
||||
return nil
|
||||
end)
|
||||
|
||||
-- Add a new callback for handling bill responses
|
||||
lib.callback.register('billing:server:handleBillResponse', function(source, data)
|
||||
local src = source
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
|
||||
if not player then return false end
|
||||
|
||||
if data.action == 'pay' then
|
||||
-- Process payment
|
||||
local success = lib.callback.await('ps-banking:server:payBill', src, data.billId)
|
||||
|
||||
if success then
|
||||
-- Payment successful
|
||||
return true
|
||||
else
|
||||
-- Payment failed (likely insufficient funds)
|
||||
return false
|
||||
end
|
||||
elseif data.action == 'decline' then
|
||||
-- Mark as declined in our system
|
||||
MySQL.update.await('UPDATE billing_accounts SET declined = 1 WHERE bill_id = ?', {data.billId})
|
||||
|
||||
-- Find the sender to notify them
|
||||
local billInfo = MySQL.query.await('SELECT * FROM billing_accounts WHERE bill_id = ?', {data.billId})
|
||||
if billInfo and #billInfo > 0 then
|
||||
local senderId = billInfo[1].sender_id
|
||||
local sender = QBCore.Functions.GetPlayerByCitizenId(senderId)
|
||||
|
||||
if sender then
|
||||
TriggerClientEvent('QBCore:Notify', sender.PlayerData.source, 'Deine Rechnung wurde abgelehnt', 'error')
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
elseif data.action == 'later' then
|
||||
-- No action needed, bill remains in system
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end)
|
||||
|
||||
-- Event handler for when a bill is paid
|
||||
RegisterNetEvent('ps-banking:server:billPaid', function(billId)
|
||||
local src = source
|
||||
|
||||
-- Find the bill in our custom table
|
||||
local billData = MySQL.query.await('SELECT * FROM billing_accounts WHERE bill_id = ?', {billId})
|
||||
|
@ -57,13 +126,13 @@ RegisterNetEvent('billing:server:billPaid', function(billId)
|
|||
if receiver then
|
||||
-- Add money directly to the receiver's bank account
|
||||
receiver.Functions.AddMoney('bank', amount, 'bill-payment')
|
||||
TriggerClientEvent('QBCore:Notify', receiver.PlayerData.source, 'You received $' .. amount .. ' from a bill payment', 'success')
|
||||
TriggerClientEvent('QBCore:Notify', receiver.PlayerData.source, 'Du hast $' .. amount .. ' von einer Rechnungszahlung erhalten', 'success')
|
||||
else
|
||||
-- Handle offline player (could store in a separate table for when they log in)
|
||||
-- Handle offline player
|
||||
MySQL.insert.await('INSERT INTO offline_payments (citizen_id, amount, reason) VALUES (?, ?, ?)', {
|
||||
receiverId,
|
||||
amount,
|
||||
'Bill payment'
|
||||
'Rechnungszahlung'
|
||||
})
|
||||
end
|
||||
else
|
||||
|
@ -92,6 +161,7 @@ MySQL.ready(function()
|
|||
amount DECIMAL(10,2),
|
||||
created_at DATETIME,
|
||||
paid TINYINT DEFAULT 0,
|
||||
declined TINYINT DEFAULT 0,
|
||||
paid_at DATETIME
|
||||
)
|
||||
]])
|
||||
|
@ -127,7 +197,7 @@ RegisterNetEvent('QBCore:Server:PlayerLoaded', function()
|
|||
|
||||
if totalAmount > 0 then
|
||||
player.Functions.AddMoney('bank', totalAmount, 'offline-bill-payments')
|
||||
TriggerClientEvent('QBCore:Notify', src, 'You received $' .. totalAmount .. ' from bill payments while offline', 'success')
|
||||
TriggerClientEvent('QBCore:Notify', src, 'Du hast $' .. totalAmount .. ' von Rechnungszahlungen erhalten, während du offline warst', 'success')
|
||||
|
||||
-- Mark payments as processed
|
||||
MySQL.update.await('UPDATE offline_payments SET processed = 1 WHERE citizen_id = ? AND processed = 0', {citizenId})
|
||||
|
@ -135,7 +205,17 @@ RegisterNetEvent('QBCore:Server:PlayerLoaded', function()
|
|||
end
|
||||
end)
|
||||
|
||||
-- Listen for bill payment events from ps-banking
|
||||
RegisterNetEvent('ps-banking:server:billPaid', function(billId)
|
||||
TriggerEvent('billing:server:billPaid', billId)
|
||||
-- Alternative hook method if you can't modify ps-banking
|
||||
-- This listens for the MySQL query that deletes a bill (which happens when a bill is paid)
|
||||
AddEventHandler('oxmysql:query', function(query, params)
|
||||
if string.find(query, "DELETE FROM ps_banking_bills WHERE id = ?") then
|
||||
-- This is likely a bill payment
|
||||
local billId = params[1]
|
||||
if billId then
|
||||
-- Small delay to ensure the deletion completes
|
||||
SetTimeout(100, function()
|
||||
TriggerEvent('ps-banking:server:billPaid', billId)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue