mirror of
https://codeberg.org/metamuffin/abrechenbarkeit.git
synced 2025-01-14 13:14:35 +00:00
add support for multible barcodes per product; products file needs to be migrated manually
This commit is contained in:
parent
a23cdf1ee4
commit
5be820b181
2 changed files with 160 additions and 22 deletions
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue