bank_accounts/computer2.lua.bak.1
2025-08-22 02:10:35 +02:00

290 lines
16 KiB
Groff

-- computer2.lua (Fixed translation error and deposit form flow)
-- Uses the global 'pos_info' variable for consistency.
-- This table will temporarily store which customer a teller is currently serving for the deposit form.
local teller_current_customer = {}
-- Copy currency definitions and helper functions from atm2.lua
local currency_values = {
{name = "currency:minegeld_100", value = 100},
{name = "currency:minegeld_50", value = 50},
{name = "currency:minegeld_10", value = 10},
{name = "currency:minegeld_5", value = 5},
{name = "currency:minegeld", value = 1},
{name = "currency:minegeld_cent_25", value = 0.25},
{name = "currency:minegeld_cent_10", value = 0.10},
{name = "currency:minegeld_cent_5", value = 0.05},
}
local function round(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end
local function get_item_value(itemstack)
local name = itemstack:get_name(); for _, c in ipairs(currency_values) do if c.name == name then return c.value end end; return 0
end
local function amount_to_itemstacks(amount)
local items = {}; local rem = amount; for _, c in ipairs(currency_values) do if rem >= c.value then local count = math.floor(rem / c.value); if count > 0 then table.insert(items, {name=c.name, count=count}); rem = rem - (count*c.value); rem = round(rem, 2); if rem < 0.001 then break end end end end; return items
end
-- Formspec for the initial customer selection screen
local function show_teller2_selection_form(player, pos, search_term)
local all_accounts = bank_accounts.get_all_data()
local customer_list = {}
for name, balance in pairs(all_accounts.balance) do
if not search_term or search_term == "" or name:lower():find(search_term:lower(), 1, true) then
table.insert(customer_list, minetest.formspec_escape(name))
end
end
table.sort(customer_list)
minetest.show_formspec(player:get_player_name(), "bank_accounts:teller2_select",
"size[8,9.5]"..
"label[0,0;"..S("Select Customer Account").."]"..
"label[0,0.5;"..S("Search by Name:").."]"..
"field[0,0.8;6,1;search_name;;"..minetest.formspec_escape(search_term or "").."]"..
"button_exit[6.2,0.8;1.8,1;search;"..S("Search").."]"..
"table[0,1.8;8,7;customer_list;"..table.concat(customer_list, ",").."]"
)
end
-- Formspec for viewing and managing a selected customer's account
local function show_teller2_customer_view(player, pos, customer_name)
local data = bank_accounts.get_account_data(customer_name)
minetest.show_formspec(player:get_player_name(), "bank_accounts:teller2_view@"..customer_name,
"size[8,9]"..
"label[0,0;"..S("Managing Account: @1", customer_name).."]"..
"label[0.5,1;"..S("Balance: @1", string.format("%.2f", data.balance).." MG").."]"..
"label[4.5,1;"..S("Credit Debt: @1", string.format("%.2f", data.credit).." MG").."]"..
"container[0,0.5;8,1.25]"..
"container_end[]"..
"button_exit[0.5,2.5;3,1;deposit;"..S("Deposit").."]"..
"button_exit[4.5,2.5;3,1;withdrawal;"..S("Withdrawal").."]"..
"button_exit[0.5,4;3,1;statement;"..S("Account Statement").."]"..
"button_exit[4.5,4;3,1;reset_pin;"..S("Reset PIN").."]"..
"button_exit[0.5,5.5;3,1;back_to_search;"..S("Back to Customer List").."]"..
"button_exit[4.5,5.5;3,1;wipe;"..S("Wipe Account").."]"
)
end
-- Formspec for the new deposit form
local function show_teller2_deposit_form(player, pos, customer_name)
local meta = minetest.get_meta(pos)
local deposited_amount = tonumber(meta:get_string("deposit_buffer") or "0")
local list_name = "nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z
minetest.show_formspec(player:get_player_name(), "bank_accounts:teller2_deposit@"..customer_name,
"size[8,9]"..
"label[0,0.5;"..S("Deposit for @1", customer_name).."]"..
"label[0,1.5;"..S("Place coins and notes in the slot below.").."]"..
"list["..list_name..";deposit_slot;3.5,2.5;1,1;]"..
"label[0,4;"..S("Currently Deposited: @1 MG", string.format("%.2f", deposited_amount)).."]"..
"button_exit[0.5,5;3,1;confirm_deposit;"..S("Deposit").."]"..
"button_exit[4.5,5;3,1;return_deposit;"..S("Return").."]"..
"list[current_player;main;0,6;8,3;]")
end
-- Formspec for the account statement
local function show_statement_form(player, pos, customer_name, account_type)
local data = bank_accounts.get_account_data(customer_name)
local history = data.history; local lines = {}; local current_total_label = ""
table.insert(lines, minetest.formspec_escape(string.format("%-11s | %-13s | %-13s | %-20s | %-20s | %s", S("Date"), S("Amount"), S("New Balance"), S("Method"), S("Purpose"), S("Partner"))))
table.insert(lines, minetest.formspec_escape("-----------------------------------------------------------------------------------------"))
if history then for _, t in ipairs(history) do if t.account == account_type then
local parts = {}; table.insert(parts, string.format("%-11s", os.date("%Y-%m-%d", t.timestamp))); table.insert(parts, string.format("%12s", string.format("%+.2f", t.amount) .. " MG")); table.insert(parts, string.format("%12s", string.format("%.2f", t.new_total).." MG")); table.insert(parts, string.format("%-20s", S(t.type)))
-- KORREKTUR: 'purpose' wird direkt angezeigt, nicht erneut übersetzt.
local purpose = t.purpose or ""
local partner = t.other or ""
if purpose ~= "" or partner ~= "" then table.insert(parts, string.format("%-20s", purpose)); if partner ~= "" then table.insert(parts, partner) end end
table.insert(lines, minetest.formspec_escape(table.concat(parts, " | ")))
end end end
if account_type == "balance" then current_total_label = S("Current Balance: @1", string.format("%.2f", data.balance).." MG") else current_total_label = S("Current Credit Debt: @1", string.format("%.2f", data.credit).." MG") end
local form_name = "bank_accounts:teller2_statement@" .. customer_name
local formspec = "size[13,9]".."label[0,0;"..S("Account Statement for @1",customer_name).."]".."button_exit[0,0.5;2,1;view_balance;"..S("Balance").."]".."button_exit[2,0.5;2,1;view_credit;"..S("Credit").."]".."textlist[0,1.2;13,7;statement_list;"..table.concat(lines,",").."]".."label[0,8.4;"..current_total_label.."]".."button_exit[11,8.4;2,1;back;"..S("Back").."]"
minetest.show_formspec(player:get_player_name(), form_name, formspec)
end
minetest.register_node("bank_accounts:teller_computer2", {
description = S("Teller Computer Mark II"),
drawtype = "mesh",
mesh = "computer.obj",
paramtype = "light",
paramtype2 = "facedir",
tiles = {"computer2.png"},
groups = {cracky=3, crumbly=3, oddly_breakable_by_hand=2},
on_construct = function(pos)
local meta = minetest.get_meta(pos); local inv = meta:get_inventory()
inv:set_size("deposit_slot", 1)
for _, currency in ipairs(currency_values) do inv:set_size(currency.name, 1) end
end,
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
pos_info = pos
if minetest.check_player_privs(player:get_player_name(), {bank_teller=true, server=true}) then
show_teller2_selection_form(player, pos, "")
else
minetest.chat_send_player(player:get_player_name(), S("[Bank] Insufficient privileges."))
end
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname ~= "deposit_slot" then return end
local value = get_item_value(stack)
if value > 0 then
local meta = minetest.get_meta(pos); local inv = meta:get_inventory()
local current_buffer = tonumber(meta:get_string("deposit_buffer") or "0")
meta:set_string("deposit_buffer", tostring(current_buffer + value * stack:get_count()))
inv:set_stack(listname, index, "")
local customer_name = teller_current_customer[player:get_player_name()]
if customer_name then
minetest.after(0, show_teller2_deposit_form, player, pos, customer_name)
end
end
end,
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if not formname:find("bank_accounts:teller2_") then return end
local player_name = player:get_player_name(); local pos = pos_info; if not pos then return end
local meta = minetest.get_meta(pos)
local function on_fail()
minetest.chat_send_player(player_name, S("[Bank] System is busy, please try again in a moment."))
end
-- Customer Selection Form
if formname == "bank_accounts:teller2_select" then
local customer_name = fields.search_name or ""
if fields.customer_list then
local event = minetest.explode_table_event(fields.customer_list)
if event.type == "CHG" or event.type == "DCL" then
local all_accounts = bank_accounts.get_all_data()
local customer_list = {}
for name, _ in pairs(all_accounts.balance) do
if not fields.search_name or fields.search_name == "" or name:lower():find(fields.search_name:lower(), 1, true) then
table.insert(customer_list, name)
end
end
table.sort(customer_list)
customer_name = customer_list[event.row]
end
end
if customer_name and bank_accounts.player_has_account(customer_name) then
show_teller2_customer_view(player, pos, customer_name)
else
show_teller2_selection_form(player, pos, fields.search_name)
end
-- Customer View Form
elseif formname:find("bank_accounts:teller2_view@") then
local customer_name = formname:match("bank_accounts:teller2_view@(.*)")
if not customer_name then return end
if fields.back_to_search then
show_teller2_selection_form(player, pos, "")
elseif fields.statement then
show_statement_form(player, pos, customer_name, "balance")
elseif fields.reset_pin then
if not bank_accounts.set_pin(customer_name, "0000") then on_fail() else minetest.chat_send_player(player_name, S("[Bank] Player's pin successfully reset!")) end
show_teller2_customer_view(player, pos, customer_name)
elseif fields.wipe then
if not bank_accounts.set_balance(customer_name, 0, "Teller Wipe", S("Teller: @1", player_name), player_name) then on_fail() else minetest.chat_send_player(player_name, S("[Bank] Account successfully wiped!")) end
show_teller2_customer_view(player, pos, customer_name)
elseif fields.deposit then
meta:set_string("deposit_buffer", "0")
teller_current_customer[player_name] = customer_name
show_teller2_deposit_form(player, pos, customer_name)
elseif fields.withdrawal then
minetest.show_formspec(player_name, "bank_accounts:teller2_withdrawal@"..customer_name, "size[8,8]" .. "field[2,4;5,1;money;"..S("Amount:")..";]" .. "button_exit[3,6;2,1;exit;"..S("Cancel").."]" .. "button_exit[5,6;2,1;enter;"..S("Enter").."]")
end
-- Deposit Form
elseif formname:find("bank_accounts:teller2_deposit@") then
local customer_name = formname:match("bank_accounts:teller2_deposit@(.*)")
local buffer = tonumber(meta:get_string("deposit_buffer") or "0")
if fields.confirm_deposit then
if buffer > 0 then
if not bank_accounts.add_balance(customer_name, buffer, "Teller Deposit", S("Teller: @1", player_name), player_name) then
on_fail()
else
minetest.chat_send_player(player_name, S("[Bank] Deposited @1 for @2.", string.format("%.2f", buffer), customer_name))
end
end
elseif fields.return_deposit or fields.quit then
if buffer > 0 then
local items_to_return = amount_to_itemstacks(buffer)
for _, item in ipairs(items_to_return) do player:get_inventory():add_item("main", item) end
if fields.quit then minetest.chat_send_player(player_name, S("[Bank] The deposit was cancelled and returned to your inventory.")) end
end
end
meta:set_string("deposit_buffer", "0")
teller_current_customer[player_name] = nil
if not fields.quit then
show_teller2_customer_view(player, pos, customer_name)
end
-- Withdrawal Amount Entry
elseif formname:find("bank_accounts:teller2_withdrawal@") then
local customer_name = formname:match("bank_accounts:teller2_withdrawal@(.*)")
if fields.enter then
local requested_amount = normalize_and_tonumber(fields.money)
if requested_amount and requested_amount > 0 and bank_accounts.get_balance(customer_name) >= requested_amount then
local items_to_dispense = amount_to_itemstacks(requested_amount)
local dispensable_amount = 0
for _, item_data in ipairs(items_to_dispense) do for _, currency in ipairs(currency_values) do if currency.name == item_data.name then dispensable_amount = dispensable_amount + (currency.value * item_data.count); break end end end
if not bank_accounts.add_balance(customer_name, -dispensable_amount, "Teller Withdrawal", S("Teller: @1", player_name), player_name) then on_fail(); return end
local inv = meta:get_inventory(); local list_elements = ""; local warning_label = ""
if dispensable_amount < requested_amount then warning_label = "label[0,1;`"..S("Note: Amount was rounded down...").."`]" .. "style[label;color=yellow]" end
for i, item in ipairs(items_to_dispense) do
inv:set_stack(item.name, 1, {name = item.name, count = item.count})
list_elements = list_elements .. "list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";"..item.name..";"..(i-1)..",2;1,1;]"
end
minetest.show_formspec(player_name, "bank_accounts:teller2_withdrawal_output@"..customer_name, "size[8,4]" .. "label[0,0.5;"..S("Teller: Give these items to @1 (@2 MG):", customer_name, string.format("%.2f", dispensable_amount)).."]" .. warning_label .. list_elements .. "button_exit[2.5,3.25;3,1;take_all;"..S("Take All").."]")
else minetest.chat_send_player(player_name, S("[Bank] Insufficient funds or invalid amount.")); show_teller2_customer_view(player, pos, customer_name) end
else show_teller2_customer_view(player, pos, customer_name) end
-- Withdrawal Output
elseif formname:find("bank_accounts:teller2_withdrawal_output@") then
local customer_name = formname:match("bank_accounts:teller2_withdrawal_output@(.*)")
if fields.take_all or fields.quit then
local inv = meta:get_inventory(); local any_left = false
for _, currency in ipairs(currency_values) do
local stack = inv:get_stack(currency.name, 1)
if not stack:is_empty() then
if fields.take_all then player:get_inventory():add_item("main", stack)
else
local success = bank_accounts.add_balance(customer_name, get_item_value(stack) * stack:get_count(), "Teller Withdraw Cancel", S("Cancelled by teller @1", player_name), player_name)
if success then any_left = true end
end
inv:set_stack(currency.name, 1, "")
end
end
if any_left and fields.quit then minetest.chat_send_player(player_name, S("[Bank] Withdrawn money was returned to the customer's account.")) end
end
if not fields.quit then show_teller2_customer_view(player, pos, customer_name) end
-- Statement Form
elseif formname:find("bank_accounts:teller2_statement@") then
local customer_name = formname:match("bank_accounts:teller2_statement@(.*)")
if not customer_name then return end
if fields.view_balance then
show_statement_form(player, pos, customer_name, "balance")
elseif fields.view_credit then
show_statement_form(player, pos, customer_name, "credit")
elseif fields.back then
show_teller2_customer_view(player, pos, customer_name)
end
end
end)