aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRiley L. <riley@e926.de>2025-01-02 00:03:45 +0100
committerRiley L. <riley@e926.de>2025-01-02 00:03:45 +0100
commit5be820b181360f7c5fcf4ebd8b8159e4c07e4e5a (patch)
tree6472460e96de37b259229b2c1b79f7f8cc0127c2
parenta23cdf1ee425e024139cc1647a8760c593feac5a (diff)
downloadabrechenbarkeit-5be820b181360f7c5fcf4ebd8b8159e4c07e4e5a.tar
abrechenbarkeit-5be820b181360f7c5fcf4ebd8b8159e4c07e4e5a.tar.bz2
abrechenbarkeit-5be820b181360f7c5fcf4ebd8b8159e4c07e4e5a.tar.zst
add support for multible barcodes per product; products file needs to be migrated manually
-rwxr-xr-xabrechenbarkeit.lua177
-rw-r--r--locale/en.ini5
2 files changed, 160 insertions, 22 deletions
diff --git a/abrechenbarkeit.lua b/abrechenbarkeit.lua
index 1243d06..2ebafc3 100755
--- a/abrechenbarkeit.lua
+++ b/abrechenbarkeit.lua
@@ -30,6 +30,7 @@ local matchers = {
barcode = "([%w_-]+)",
barcode_opt = "([%w_-]*)",
name = "([%w_ -]+)",
+ name_opt = "([%w_ -]*)",
}
local matchers_global = (function()
local s = {}
@@ -142,6 +143,26 @@ local function format_amount(amount, tag, classes)
})
end
+local function format_list(list)
+ 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
+
+ not_first = true
+ end
+
+ return out
+end
+
local function get_user_theme(username)
local c = ""
if username == "_jeb" then
@@ -254,9 +275,9 @@ local function read_log()
if l == "" or l == nil then
return nil
end
- local time, user_src, user_dst, amount, pcode, pcount, comment = string.match(l,
- format("^{time},{user},{user},{amount},{barcode_opt},{amount_opt},{comment_opt}$", matchers))
- return tonumber(time), user_src, user_dst, tonumber(amount), pcode, tonumber(pcount), comment
+ local time, user_src, user_dst, amount, pname, pcount, comment = string.match(l,
+ format("^{time},{user},{user},{amount},{name_opt},{amount_opt},{comment_opt}$", matchers))
+ return tonumber(time), user_src, user_dst, tonumber(amount), pname, tonumber(pcount), comment
end
end
@@ -271,8 +292,24 @@ local function read_products()
if l == "" or l == nil then
return nil
end
- local barcode, price, user, name = string.match(l, format("^{barcode},{amount},{user_opt},{name}$", matchers))
- return barcode, tonumber(price), user, name
+ local price, user, name = string.match(l, format("^{amount},{user_opt},{name}$", matchers))
+ return tonumber(price), user, name
+ end
+end
+
+local function read_barcodes()
+ local log = io.open("barcodes", "r")
+ if log == nil then
+ return function() return nil end
+ end
+ local lines = log:lines("l")
+ return function()
+ local l = lines()
+ if l == "" or l == nil then
+ return nil
+ end
+ local name, barcode = string.match(l, format("^{name},{barcode}$", matchers))
+ return name, barcode
end
end
@@ -336,10 +373,25 @@ local function r_transaction_post()
local pcode = data.pcode
local pcount = tonumber(data.pcount)
local comment = data.comment
+ local barcode_name = nil
+
if pcode ~= nil and pcode ~= "" then
+ -- check if barcode exists
+ local exists = false
+ for p_name, p_barcode in read_barcodes() do
+ if p_barcode == pcode then
+ exists = true
+ barcode_name = p_name
+ end
+ end
+ if not exists then
+ return error_box("{+error.unknown_barcode}")
+ end
+
+ -- check if product exists
local exists = false
- for p_barcode, p_amount, p_user, p_name in read_products() do
- if p_barcode == pcode then
+ for p_amount, p_user, p_name in read_products() do
+ if barcode_name == p_name then
pcount = (tonumber(data.pcount) or 1) * (data.negate_pcount ~= nil and -1 or 1)
amount = amount or pcount * p_amount
user_src = user_src or p_user
@@ -349,9 +401,11 @@ local function r_transaction_post()
end
end
if not exists then
- return error_box("{+error.unknown_product}")
+ return error_box("{+error.unknown_product}"..barcode_name)
end
end
+
+ -- for outside money
user_src = user_src or "@Potential"
if amount == nil then
return error_box("{+error.invalid_amount}")
@@ -371,7 +425,7 @@ local function r_transaction_post()
end
local time = os.time()
log:write(string.format("%d,%s,%s,%d,%s,%s,%s\n",
- time, user_src, user_dst, amount, pcode or "", pcount or "", comment))
+ time, user_src, user_dst, amount, barcode_name or "", pcount or "", comment))
log:flush()
log:close()
return format([[
@@ -644,23 +698,41 @@ end
local function r_products_post()
local data = form_data()
- local barcode = data.barcode
- if barcode == nil or barcode:match("^[%w_-]*$") == nil then
- return error_box("{+error.invalid_barcode}")
+ local name = data.name
+ if name == nil or name:match("^[%w_-]*$") == nil then
+ return error_box("{+error.invalid_name}")
end
+
if data.delete then
local new_products = io.open("products.new", "w+")
if new_products == nil then
return error_box("{+error.open_new_products}")
end
- for a_barcode, price, user, name in read_products() do
- if barcode ~= a_barcode then
- new_products:write(string.format("%s,%d,%s,%s\n", a_barcode, price, user, name))
+ for price, user, a_name in read_products() do
+ if name ~= a_name then
+ new_products:write(string.format("%d,%s,%s\n", price, user, name))
end
end
new_products:flush()
new_products:close()
os.rename("products.new", "products")
+ elseif data.addbarcode then
+ -- 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 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
local price = tonumber(data.price)
local name = data.name
@@ -678,7 +750,7 @@ local function r_products_post()
if products == nil then
return error_box("{+error.open_products}")
end
- products:write(string.format("%s,%d,%s,%s\n", barcode, price, user, name))
+ products:write(string.format("%d,%s,%s\n", price, user, name))
products:flush()
products:close()
end
@@ -702,6 +774,23 @@ local function r_products()
<input type="number" name="price" id="price" />
<label for="user">{+field.user}: </label>
<input type="text" name="user" id="user" />
+ <input type="submit" value="{+products.form.add.submit}" class="amount-ntr button" />
+ </form>
+ <form action="/?products" method="POST" class="box backgroundbox">
+ <h3>{+products.form.addbarcode}</h3>
+ <input type="text" name="addbarcode" value="1" hidden />
+ <label for="name">{+field.name}: </label>
+ <select type="text" name="name" id="name">
+ ]], {
+ currency = config.unit or "€",
+ }))
+ for _, _, name in read_products() do
+ print(format([[<option name="{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" />
@@ -709,8 +798,51 @@ local function r_products()
<form action="/?products" method="POST" class="box backgroundbox">
<h3>{+products.form.remove}</h3>
<input type="text" name="delete" value="1" hidden />
+ <label for="name">{+field.name}: </label>
+ <select type="text" name="name" id="name">
+ ]], {
+ currency = config.unit or "€",
+ }))
+ for _, _, name in read_products() do
+ print(format([[<option name="{name}">{!name}</option>]], {
+ name = name,
+ }))
+ end
+ print(format([[</select>
+ <input type="submit" value="{+products.form.remove.submit}" class="amount-ntr button" />
+ </form>
+ <!-- remove barcode -->
+ <form action="/?products" method="POST" class="box backgroundbox">
+ <h3>{+products.form.removebarcode}</h3>
+ <input type="text" name="delete" value="1" hidden />
<label for="barcode">{+field.barcode}: </label>
- <input type="text" name="barcode" id="barcode" />
+ <select type="text" name="barcode" id="barcode">
+ ]], {
+ currency = config.unit or "€",
+ }))
+
+ local barcodes = {}
+ for name, barcode in read_barcodes() do
+ print(format([[<option name="{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
+
+ for a, b in pairs(barcodes) do
+ print("name: " .. a)
+ for _, c in pairs(b) do
+ print("\t"..c)
+ end
+ end
+
+ print(format([[</select>
<input type="submit" value="{+products.form.remove.submit}" class="amount-ntr button" />
</form>
</div>
@@ -720,26 +852,27 @@ local function r_products()
print(format([[<table class="productlist"><tr>
<th>{+field.name}</th>
<th>{+field.price}</th>
- <th>{+field.barcode}</th>
<th>{+field.count}</th>
<th>{+field.user}</th>
+ <th>{+field.barcode}</th>
</tr>]]))
local pbals = product_balances()
- for barcode, price, user, name in read_products() do
+ for price, user, name in read_products() do
print(format([[<tr>
<td>{!name}</td>
{price}
- <td>{!barcode}</td>
<td>{!count}</td>
<td>{!user}</td>
+ <td>{barcodes}</td>
</tr>]], {
name = name,
price = format_amount(-price, "td"),
- barcode = barcode,
count = tostring(pbals[barcode] or 0),
user = user,
+ barcodes = format_list(barcodes[name]) or "{+field.not_set}",
}))
- end
+ end
+
print("</table>")
end)
end
diff --git a/locale/en.ini b/locale/en.ini
index 98dffee..d051b50 100644
--- a/locale/en.ini
+++ b/locale/en.ini
@@ -16,14 +16,17 @@ field.time=Time
field.upstream_price=Upstream Price
field.user=User
field.username=Username
+field.not_set=Not Set
index.form.create_user.submit=Continue
index.form.create_user=User Creation
log.actions.revert=Revert
log.actions=Actions
log=Log
products.form.add=Add Product
+products.form.addbarcode=Add Barcode
products.form.add.submit=Add
products.form.remove=Remove Product
+products.form.removebarcode=Remove Barcode
products.form.remove.submit=Remove
products.form.title=Product List
products.title=Product List
@@ -55,6 +58,7 @@ users=Users
user.special=This is a special user.
users.filter=Filter
error.unknown_product=Unknown product
+error.unknown_barcode=Unknown barcode
error.invalid_amount=Amount invalid
error.invalid_comment=Comment invalid
error.invalid_user_src=Source user invalid
@@ -66,6 +70,7 @@ error.open_new_products=Failed to open new products file
error.invalid_price=Price invalid
error.invalid_name=Name invalid
error.open_products=Failed to open products file
+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.