mirror of
https://codeberg.org/metamuffin/abrechenbarkeit.git
synced 2025-05-22 14:34:44 +00:00
Add print button
This commit is contained in:
parent
ee7987599e
commit
3b5948682a
2 changed files with 154 additions and 146 deletions
|
@ -114,6 +114,8 @@ local translations = load_translations({ "en", config.language })
|
|||
local stylesheet = io.open("style.css"):read("a")
|
||||
local script = io.open("script.js"):read("a")
|
||||
|
||||
local can_print = false
|
||||
|
||||
local function format(template, params)
|
||||
params = params or {}
|
||||
if template == nil then return "NIL TEMPLATE" end
|
||||
|
@ -144,23 +146,23 @@ local function format_amount(amount, tag, classes)
|
|||
end
|
||||
|
||||
local function format_list(list)
|
||||
if list == nil then
|
||||
return nil
|
||||
end
|
||||
if list == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local not_first = false
|
||||
local out = ""
|
||||
for _, barcode in pairs(list) do
|
||||
if not_first then
|
||||
out = out .. ", " .. barcode
|
||||
else
|
||||
out = barcode
|
||||
end
|
||||
local not_first = false
|
||||
local out = ""
|
||||
for _, barcode in pairs(list) do
|
||||
if not_first then
|
||||
out = out .. ", " .. barcode
|
||||
else
|
||||
out = barcode
|
||||
end
|
||||
|
||||
not_first = true
|
||||
end
|
||||
not_first = true
|
||||
end
|
||||
|
||||
return out
|
||||
return out
|
||||
end
|
||||
|
||||
local function get_user_theme(username)
|
||||
|
@ -225,6 +227,7 @@ local function respond(status, title, body)
|
|||
<a href="/?spus">{+spus}</a>
|
||||
<a href="/?products">{+products}</a>
|
||||
<a href="/?log">{+log}</a>
|
||||
{print_button}
|
||||
<a href="/?about">{+about}</a>
|
||||
</nav>
|
||||
]], {
|
||||
|
@ -232,7 +235,9 @@ local function respond(status, title, body)
|
|||
style = stylesheet,
|
||||
user_style = get_user_theme(path and path:sub(2)),
|
||||
script = script,
|
||||
head_extra = config.head_extra or ""
|
||||
head_extra = config.head_extra or "",
|
||||
print_button = can_print and
|
||||
[[<script>document.write('<a href="javascript:print()" style="float:right;">{+print}</a>')</script>]] or ""
|
||||
}))
|
||||
if config.header ~= nil then
|
||||
print(config.header)
|
||||
|
@ -373,24 +378,24 @@ local function r_transaction_post()
|
|||
local pcode = data.pcode
|
||||
local pcount = tonumber(data.pcount)
|
||||
local comment = data.comment
|
||||
local pname = data.pname
|
||||
|
||||
local pname = data.pname
|
||||
|
||||
if pname ~= nil or (pcode ~= nil and pcode ~= "") then
|
||||
-- check if barcode exists
|
||||
if pname == nil then
|
||||
local exists = false
|
||||
for p_name, p_barcode in read_barcodes() do
|
||||
if p_barcode == pcode then
|
||||
exists = true
|
||||
pname = p_name
|
||||
end
|
||||
end
|
||||
if not exists then
|
||||
return error_box("{+error.unknown_barcode}")
|
||||
end
|
||||
-- check if barcode exists
|
||||
if pname == nil then
|
||||
local exists = false
|
||||
for p_name, p_barcode in read_barcodes() do
|
||||
if p_barcode == pcode then
|
||||
exists = true
|
||||
pname = p_name
|
||||
end
|
||||
end
|
||||
if not exists then
|
||||
return error_box("{+error.unknown_barcode}")
|
||||
end
|
||||
end
|
||||
|
||||
-- check if product exists
|
||||
|
||||
-- check if product exists
|
||||
local exists = false
|
||||
for p_amount, p_user, p_name in read_products() do
|
||||
if pname == p_name then
|
||||
|
@ -403,11 +408,11 @@ local function r_transaction_post()
|
|||
end
|
||||
end
|
||||
if not exists then
|
||||
return error_box("{+error.unknown_product}: "..pname)
|
||||
return error_box("{+error.unknown_product}: " .. pname)
|
||||
end
|
||||
end
|
||||
|
||||
-- for outside money
|
||||
-- for outside money
|
||||
user_src = user_src or "@Potential"
|
||||
if amount == nil then
|
||||
return error_box("{+error.invalid_amount}")
|
||||
|
@ -469,8 +474,8 @@ local function r_user(username)
|
|||
{ time = format_duration(os.time() - last_txn), username = urlencode(username) }))
|
||||
print([[</div>]])
|
||||
end
|
||||
|
||||
print([[<ul class="userforms"><li>
|
||||
|
||||
print([[<ul class="userforms"><li>
|
||||
<div class="amount-presets backgroundbox">]])
|
||||
for _, type in ipairs({ 1, -1 }) do
|
||||
for _, amount in ipairs({ 50, 100, 150, 200, 500, 1000 }) do
|
||||
|
@ -490,45 +495,45 @@ local function r_user(username)
|
|||
end
|
||||
end
|
||||
print("</div></li>")
|
||||
|
||||
|
||||
print(format([[<li><div class="backgroundbox shortcuts">
|
||||
<h3>{+user.shortcuts}</h3>]]))
|
||||
local lastcategory = nil
|
||||
-- user is category; @ is removed for ZSKs
|
||||
for price, category, name in read_products() do
|
||||
if lastcategory ~= category then
|
||||
if lastcategory ~= nil then
|
||||
print("</ul></div></label>")
|
||||
end
|
||||
print(format([[<label>
|
||||
-- user is category; @ is removed for ZSKs
|
||||
for price, category, name in read_products() do
|
||||
if lastcategory ~= category then
|
||||
if lastcategory ~= nil then
|
||||
print("</ul></div></label>")
|
||||
end
|
||||
print(format([[<label>
|
||||
<input type="checkbox" hidden />
|
||||
<div>
|
||||
<span class="button amount-ntr">{c}</span>
|
||||
<ul>]], {
|
||||
c = category:gsub("@", ""),
|
||||
}))
|
||||
c = category:gsub("@", ""),
|
||||
}))
|
||||
|
||||
lastcategory = category
|
||||
end
|
||||
lastcategory = category
|
||||
end
|
||||
|
||||
print(format([[<li><form method="POST">
|
||||
print(format([[<li><form method="POST">
|
||||
<input type="text" name="user_dst" value="{!username}" hidden />
|
||||
<input type="number" name="pcount" value="-1" hidden />
|
||||
<input type="text" name="pname" value="{name}" hidden />
|
||||
<input type="text" name="pname" value="{name}" hidden />
|
||||
<input class="button amount-ntr" value="{name}
|
||||
{+price.amount}" type="submit" />
|
||||
</form></li>]], {
|
||||
name = name,
|
||||
username = username,
|
||||
sign = price >= 0 and "-" or "+",
|
||||
amount = string.format("%.2f", math.abs(price / 100)),
|
||||
unit = config.unit or "€",
|
||||
}))
|
||||
end
|
||||
print("</ul></div></label>")
|
||||
name = name,
|
||||
username = username,
|
||||
sign = price >= 0 and "-" or "+",
|
||||
amount = string.format("%.2f", math.abs(price / 100)),
|
||||
unit = config.unit or "€",
|
||||
}))
|
||||
end
|
||||
print("</ul></div></label>")
|
||||
|
||||
print("</div></li>")
|
||||
print(format([[
|
||||
print("</div></li>")
|
||||
print(format([[
|
||||
<li><form class="transaction box backgroundbox {disable_class}" action="" method="POST">
|
||||
<h3>{+user.form.transaction}</h3>
|
||||
<input type="text" name="user_dst" value="{!username}" hidden />
|
||||
|
@ -552,13 +557,13 @@ local function r_user(username)
|
|||
<h3>{+user.form.transfer}</h3>
|
||||
<label for="user_dst">{+field.destination}: </label>
|
||||
<select name="user_dst">]],
|
||||
{ username = username, disable_class = is_special and "disabled" or "" }))
|
||||
local users = get_active_users();
|
||||
for _, u in ipairs(users) do
|
||||
if u.name ~= username then
|
||||
print(format([[<option value="{!name}">{name}</option>]], { name = u.name }))
|
||||
end
|
||||
end
|
||||
{ username = username, disable_class = is_special and "disabled" or "" }))
|
||||
local users = get_active_users();
|
||||
for _, u in ipairs(users) do
|
||||
if u.name ~= username then
|
||||
print(format([[<option value="{!name}">{name}</option>]], { name = u.name }))
|
||||
end
|
||||
end
|
||||
print(format([[</select>
|
||||
<input type="text" name="user_src" value="{!username}" hidden />
|
||||
<label for="amount">{+field.amount}: </label>
|
||||
|
@ -579,8 +584,8 @@ local function r_user(username)
|
|||
<input type="submit" value="{+user.form.restock.submit}" class="button amount-pos" />
|
||||
</form></li>]],
|
||||
{
|
||||
username = username,
|
||||
disable_class = is_special and "disabled" or "",
|
||||
username = username,
|
||||
disable_class = is_special and "disabled" or "",
|
||||
}))
|
||||
print("</ul>")
|
||||
end)
|
||||
|
@ -591,6 +596,7 @@ local function r_log(filter)
|
|||
if method == "POST" then
|
||||
notif = r_transaction_post()
|
||||
end
|
||||
can_print = true
|
||||
return respond(200, "Abrechnungen", function()
|
||||
if notif then print(notif) end
|
||||
print([[<table class="log"]])
|
||||
|
@ -648,9 +654,9 @@ local function r_log(filter)
|
|||
end
|
||||
|
||||
local function r_users(show_special, filter_negative)
|
||||
if filter_negative ~= nil then
|
||||
filter_negative = tonumber(filter_negative) or 0
|
||||
end
|
||||
if filter_negative ~= nil then
|
||||
filter_negative = tonumber(filter_negative) or 0
|
||||
end
|
||||
|
||||
return respond(200, "Abrechenbarkeit", function()
|
||||
local users = get_active_users()
|
||||
|
@ -701,8 +707,8 @@ local function r_users(show_special, filter_negative)
|
|||
local is_spu = user.name:sub(1, 1) == "@"
|
||||
local filter_out = query.prefix ~= nil and user.name:sub(1, 1):lower() ~= query.prefix
|
||||
if is_spu == show_special and
|
||||
((filter_negative ~= nil and user.balance < filter_negative)
|
||||
or (filter_negative == nil and (not filter_out))) then
|
||||
((filter_negative ~= nil and user.balance < filter_negative)
|
||||
or (filter_negative == nil and (not filter_out))) then
|
||||
print(format([[<li>
|
||||
<a href="/{username_url}">
|
||||
<span class="name">{!username}</span>
|
||||
|
@ -715,31 +721,31 @@ local function r_users(show_special, filter_negative)
|
|||
}))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if filter_negative ~= nil then
|
||||
table.sort(users, function(a, b)
|
||||
return a.balance < b.balance
|
||||
end)
|
||||
table.sort(users, function(a, b)
|
||||
return a.balance < b.balance
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local inactive_cutoff = os.time() - (tonumber(config.inactive_cutoff) or (30 * 24 * 60 * 60))
|
||||
local embezzlement = 0
|
||||
for _, user in ipairs(users) do
|
||||
for _, user in ipairs(users) do
|
||||
if filter_negative or user.time > inactive_cutoff then
|
||||
show_user(user)
|
||||
show_user(user)
|
||||
|
||||
if user.name:sub(1,1) ~= "@" then
|
||||
if user.balance < 0 then embezzlement = embezzlement - user.balance end
|
||||
end
|
||||
if user.name:sub(1, 1) ~= "@" then
|
||||
if user.balance < 0 then embezzlement = embezzlement - user.balance end
|
||||
end
|
||||
end
|
||||
end
|
||||
print("</ul>")
|
||||
if filter_negative ~= nil then
|
||||
print(format([[<section class="section" style="margin-top: 0">{+users.embezzlement}</section>]], {
|
||||
amount = format_amount(embezzlement)
|
||||
}))
|
||||
print(format([[<section class="section" style="margin-top: 0">{+users.embezzlement}</section>]], {
|
||||
amount = format_amount(embezzlement)
|
||||
}))
|
||||
|
||||
return
|
||||
return
|
||||
end
|
||||
print(format([[
|
||||
<details {oclass}><summary>{+users.inactive_list}</summary><ul class="userlist">
|
||||
|
@ -763,7 +769,7 @@ local function r_products_post()
|
|||
local data = form_data()
|
||||
|
||||
if data.deletebarcode then
|
||||
local barcode = data.barcode
|
||||
local barcode = data.barcode
|
||||
|
||||
-- remove barcode
|
||||
local new_barcodes = io.open("barcodes.new", "w+")
|
||||
|
@ -778,9 +784,9 @@ local function r_products_post()
|
|||
new_barcodes:flush()
|
||||
new_barcodes:close()
|
||||
os.rename("barcodes.new", "barcodes")
|
||||
return
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
local name = data.name
|
||||
if name == nil or name:match("^" .. matchers.name .. "$") == nil then
|
||||
return error_box("{+error.invalid_name}")
|
||||
|
@ -801,31 +807,31 @@ local function r_products_post()
|
|||
new_products:close()
|
||||
os.rename("products.new", "products")
|
||||
elseif data.addbarcode then
|
||||
-- add barcode
|
||||
local name = data.name
|
||||
local barcode = data.barcode
|
||||
-- add barcode
|
||||
local name = data.name
|
||||
local barcode = data.barcode
|
||||
if name == nil or name:match(matchers_global.name) == nil then
|
||||
return error_box("{+error.invalid_name}")
|
||||
end
|
||||
if barcode == nil or barcode:match(matchers_global.barcode) == nil then
|
||||
return error_box("{+error.invalid_barcode}")
|
||||
end
|
||||
local exists = false
|
||||
for _, a_barcode in read_barcodes() do
|
||||
if a_barcode == barcode then
|
||||
exists = true
|
||||
end
|
||||
end
|
||||
local exists = false
|
||||
for _, a_barcode in read_barcodes() do
|
||||
if a_barcode == barcode then
|
||||
exists = true
|
||||
end
|
||||
end
|
||||
|
||||
if exists then
|
||||
return error_box("{+error.invalid_barcode}")
|
||||
end
|
||||
if exists then
|
||||
return error_box("{+error.invalid_barcode}")
|
||||
end
|
||||
|
||||
local barcodes = io.open("barcodes", "a+")
|
||||
if barcodes == nil then
|
||||
return error_box("{+error.open_barcodes}")
|
||||
end
|
||||
barcodes:write(string.format("%s,%s\n", name, barcode))
|
||||
local barcodes = io.open("barcodes", "a+")
|
||||
if barcodes == nil then
|
||||
return error_box("{+error.open_barcodes}")
|
||||
end
|
||||
barcodes:write(string.format("%s,%s\n", name, barcode))
|
||||
barcodes:flush()
|
||||
barcodes:close()
|
||||
else
|
||||
|
@ -841,26 +847,26 @@ local function r_products_post()
|
|||
if user == nil or user:match(matchers_global.user) == nil then
|
||||
return error_box("{+error.invalid_user}")
|
||||
end
|
||||
-- add product
|
||||
-- add product
|
||||
local new_products = io.open("products.new", "w+")
|
||||
if new_products == nil then
|
||||
return error_box("{+error.open_new_products}")
|
||||
end
|
||||
local wrote = nil
|
||||
-- prepend to any block in the file containing products of the same user
|
||||
-- the shortcuts feature expects this!
|
||||
local wrote = nil
|
||||
-- prepend to any block in the file containing products of the same user
|
||||
-- the shortcuts feature expects this!
|
||||
for a_price, a_user, a_name in read_products() do
|
||||
if user == a_user and not wrote then
|
||||
wrote = true
|
||||
products:write(string.format("%d,%s,%s\n", price, user, name))
|
||||
wrote = true
|
||||
products:write(string.format("%d,%s,%s\n", price, user, name))
|
||||
end
|
||||
|
||||
new_products:write(string.format("%d,%s,%s\n", a_price, a_user, a_name))
|
||||
end
|
||||
|
||||
-- append if not wrote already
|
||||
if not wrote then
|
||||
products:write(string.format("%d,%s,%s\n", price, user, name))
|
||||
-- append if not wrote already
|
||||
if not wrote then
|
||||
products:write(string.format("%d,%s,%s\n", price, user, name))
|
||||
end
|
||||
|
||||
new_products:flush()
|
||||
|
@ -874,6 +880,7 @@ local function r_products()
|
|||
if method == "POST" then
|
||||
notif = r_products_post()
|
||||
end
|
||||
can_print = true
|
||||
respond(200, "Abrechenbare Product List", function()
|
||||
print(format("<h1>{+products.title}</h1>"))
|
||||
if notif then print(notif) end
|
||||
|
@ -895,15 +902,15 @@ local function r_products()
|
|||
<label for="name">{+field.name}: </label>
|
||||
<select type="text" name="name" id="name">
|
||||
]], {
|
||||
currency = config.unit or "€",
|
||||
currency = config.unit or "€",
|
||||
}))
|
||||
for _, _, name in read_products() do
|
||||
print(format([[<option value="{name}">{name}</option>]], {
|
||||
name = name,
|
||||
}))
|
||||
end
|
||||
|
||||
print(format([[</select>
|
||||
print(format([[<option value="{name}">{name}</option>]], {
|
||||
name = name,
|
||||
}))
|
||||
end
|
||||
|
||||
print(format([[</select>
|
||||
<label for="barcode">{+field.barcode}: </label>
|
||||
<input type="text" name="barcode" id="barcode" />
|
||||
<input type="submit" value="{+products.form.add.submit}" class="amount-ntr button" />
|
||||
|
@ -914,14 +921,14 @@ local function r_products()
|
|||
<label for="name">{+field.name}: </label>
|
||||
<select type="text" name="name" id="name">
|
||||
]], {
|
||||
currency = config.unit or "€",
|
||||
currency = config.unit or "€",
|
||||
}))
|
||||
for _, _, name in read_products() do
|
||||
print(format([[<option value="{name}">{!name}</option>]], {
|
||||
name = name,
|
||||
}))
|
||||
end
|
||||
print(format([[</select>
|
||||
print(format([[<option value="{name}">{!name}</option>]], {
|
||||
name = name,
|
||||
}))
|
||||
end
|
||||
print(format([[</select>
|
||||
<input type="submit" value="{+products.form.remove.submit}" class="amount-ntr button" />
|
||||
</form>
|
||||
<!-- remove barcode -->
|
||||
|
@ -931,24 +938,24 @@ local function r_products()
|
|||
<label for="barcode">{+field.barcode}: </label>
|
||||
<select type="text" name="barcode" id="barcode">
|
||||
]], {
|
||||
currency = config.unit or "€",
|
||||
currency = config.unit or "€",
|
||||
}))
|
||||
|
||||
|
||||
local barcodes = {}
|
||||
for name, barcode in read_barcodes() do
|
||||
print(format([[<option value="{barcode}">{!barcode} ({!name})</option>]], {
|
||||
name = name,
|
||||
barcode = barcode,
|
||||
}))
|
||||
if barcodes[name] ~= nil then
|
||||
table.insert(barcodes[name], barcode)
|
||||
else
|
||||
barcodes[name] = {}
|
||||
table.insert(barcodes[name], barcode)
|
||||
end
|
||||
end
|
||||
print(format([[<option value="{barcode}">{!barcode} ({!name})</option>]], {
|
||||
name = name,
|
||||
barcode = barcode,
|
||||
}))
|
||||
if barcodes[name] ~= nil then
|
||||
table.insert(barcodes[name], barcode)
|
||||
else
|
||||
barcodes[name] = {}
|
||||
table.insert(barcodes[name], barcode)
|
||||
end
|
||||
end
|
||||
|
||||
print(format([[</select>
|
||||
print(format([[</select>
|
||||
<input type="submit" value="{+products.form.remove.submit}" class="amount-ntr button" />
|
||||
</form>
|
||||
</div>
|
||||
|
@ -977,8 +984,8 @@ local function r_products()
|
|||
user = user,
|
||||
barcodes = format_list(barcodes[name]) or "{+field.not_set}",
|
||||
}))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
print("</table>")
|
||||
end)
|
||||
end
|
||||
|
@ -1063,7 +1070,7 @@ if path == "/" then
|
|||
elseif query.spus then
|
||||
return r_users(true, nil)
|
||||
elseif query.users and query.export then
|
||||
return r_export_balances()
|
||||
return r_export_balances()
|
||||
else
|
||||
return r_users(false, query.negative and (query.maximum or 0))
|
||||
end
|
||||
|
|
|
@ -79,3 +79,4 @@ error.open_barcodes=Failed to open barcodes file
|
|||
error.no_path=No path
|
||||
users.inactive_list=Inactive Users
|
||||
users.embezzlement=A total of {amount} are currently under embezzlement.
|
||||
print=Print
|
Loading…
Add table
Reference in a new issue