diff options
author | Riley L. <riley@e926.de> | 2025-01-02 00:03:45 +0100 |
---|---|---|
committer | Riley L. <riley@e926.de> | 2025-01-02 00:03:45 +0100 |
commit | 5be820b181360f7c5fcf4ebd8b8159e4c07e4e5a (patch) | |
tree | 6472460e96de37b259229b2c1b79f7f8cc0127c2 | |
parent | a23cdf1ee425e024139cc1647a8760c593feac5a (diff) | |
download | abrechenbarkeit-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-x | abrechenbarkeit.lua | 177 | ||||
-rw-r--r-- | locale/en.ini | 5 |
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. |