summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHolger Cremer <HolgerCremer@gmail.com>2018-07-26 20:09:26 +0200
committerHolger Cremer <HolgerCremer@gmail.com>2018-07-26 20:09:26 +0200
commitbb55e121576a5b5d225bfc68c5062f386cc32db9 (patch)
tree21fe043175183944fe2d9fc0a2e08012c3d195fd /src
parent567dadcd9d8816b447591c266c9ffd5a1c290390 (diff)
downloadserial-barcode-scanner-bb55e121576a5b5d225bfc68c5062f386cc32db9.tar.bz2
adds an inventory function
Diffstat (limited to 'src')
-rw-r--r--src/database/database.vala11
-rw-r--r--src/database/db-interface.vala1
-rw-r--r--src/pdf-stock/Makefile4
-rw-r--r--src/pdf-stock/pdf-stock-interface.vala3
-rw-r--r--src/pdf-stock/pdf-stock.vala5
-rw-r--r--src/web/Makefile2
-rw-r--r--src/web/main.vala11
-rw-r--r--src/web/web.vala145
8 files changed, 173 insertions, 9 deletions
diff --git a/src/database/database.vala b/src/database/database.vala
index fb7bde6..0d3d1ff 100644
--- a/src/database/database.vala
+++ b/src/database/database.vala
@@ -121,6 +121,7 @@ public class DataBase : Object {
queries["total_sales"] = "SELECT SUM(price) FROM invoice WHERE user >= 0 AND timestamp >= ?";
queries["total_profit"] = "SELECT SUM(price - (SELECT price FROM purchaseprices WHERE product = productid)) FROM invoice WHERE user >= 0 AND timestamp >= ?";
queries["user_get_ids"] = "SELECT id FROM users WHERE id > 0";
+ queries["system_user_get_ids"] = "SELECT id FROM users WHERE id <= 0";
queries["user_replace"] = "INSERT OR REPLACE INTO users ('id', 'email', 'firstname', 'lastname', 'gender', 'street', 'plz', 'city', 'pgp', 'hidden', 'disabled', 'joined_at', 'sound_theme') VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, (select sound_theme from users where id = ?))";
queries["user_auth_create"] = "INSERT OR IGNORE INTO authentication (user) VALUES (?)";
queries["user_disable"] = "UPDATE users SET disabled = ? WHERE id = ?";
@@ -841,6 +842,16 @@ public class DataBase : Object {
return result;
}
+ public int[] get_system_member_ids() {
+ int[] result = {};
+
+ statements["system_user_get_ids"].reset();
+ while(statements["system_user_get_ids"].step() == Sqlite.ROW)
+ result += statements["system_user_get_ids"].column_int(0);
+
+ return result;
+ }
+
public void user_disable(int user, bool value) throws DatabaseError {
int rc;
diff --git a/src/database/db-interface.vala b/src/database/db-interface.vala
index bd94ce1..ac8c215 100644
--- a/src/database/db-interface.vala
+++ b/src/database/db-interface.vala
@@ -44,6 +44,7 @@ public interface Database : Object {
public abstract int64 get_last_purchase(int user) throws IOError;
public abstract StatsInfo get_stats_info() throws IOError;
public abstract int[] get_member_ids() throws IOError;
+ public abstract int[] get_system_member_ids() throws IOError;
public abstract void user_disable(int user, bool value) throws IOError, DatabaseError;
public abstract void user_replace(UserInfo u) throws IOError, DatabaseError;
public abstract bool user_is_disabled(int user) throws IOError, DatabaseError;
diff --git a/src/pdf-stock/Makefile b/src/pdf-stock/Makefile
index 2c8be58..a9ad1a6 100644
--- a/src/pdf-stock/Makefile
+++ b/src/pdf-stock/Makefile
@@ -6,10 +6,10 @@ all: pdf-stock
@echo > /dev/null
pdf-stock: main.vala pdf-stock.vala ../database/db-interface.vala ../price.vapi ../../libcairobarcode/libcairobarcode.vapi
- ${VALAC} -X -w ${LIBCAIROBARCODE} -o $@ --pkg cairo --pkg pangocairo --pkg gio-2.0 --pkg posix $^
+ valac -X -w ${LIBCAIROBARCODE} -o $@ --pkg cairo --pkg pangocairo --pkg gio-2.0 --pkg posix $^
test: test.vala pdf-stock-interface.vala
- ${VALAC} -X -w -o $@ --pkg gio-2.0 $^
+ valac -X -w -o $@ --pkg gio-2.0 $^
run: pdf-stock
LD_LIBRARY_PATH=../../libcairobarcode ./pdf-stock
diff --git a/src/pdf-stock/pdf-stock-interface.vala b/src/pdf-stock/pdf-stock-interface.vala
index 415916f..be49a20 100644
--- a/src/pdf-stock/pdf-stock-interface.vala
+++ b/src/pdf-stock/pdf-stock-interface.vala
@@ -15,5 +15,6 @@
[DBus (name = "io.mainframe.shopsystem.StockPDF")]
public interface PDFStock : Object {
- public abstract uint8[] generate() throws IOError;
+ // if false, only products with an amount > 0 are selected
+ public abstract uint8[] generate(bool allProducts) throws IOError;
}
diff --git a/src/pdf-stock/pdf-stock.vala b/src/pdf-stock/pdf-stock.vala
index e971f78..ac51c23 100644
--- a/src/pdf-stock/pdf-stock.vala
+++ b/src/pdf-stock/pdf-stock.vala
@@ -154,7 +154,7 @@ public class StockPDF {
return Cairo.Status.SUCCESS;
}
- public uint8[] generate() {
+ public uint8[] generate(bool allProducts) {
data = null;
var surface = new Cairo.PdfSurface.for_stream(pdf_write, a4w, a4h);
@@ -187,6 +187,9 @@ public class StockPDF {
render_table_header();
foreach(var p in stock) {
+ if (!allProducts && p.amount <= 0) {
+ continue;
+ }
render_table_row(p);
y += eanh + 6;
diff --git a/src/web/Makefile b/src/web/Makefile
index e6094f6..94aab97 100644
--- a/src/web/Makefile
+++ b/src/web/Makefile
@@ -1,7 +1,7 @@
all: web
@echo > /dev/null
-web: main.vala web.vala websession.vala csv.vala template.vala ../database/db-interface.vala ../pgp/pgp-interface.vala ../price.vapi ../config/config-interface.vala ../audio/audio-interface.vala
+web: main.vala web.vala websession.vala csv.vala template.vala ../database/db-interface.vala ../pgp/pgp-interface.vala ../price.vapi ../config/config-interface.vala ../audio/audio-interface.vala ../pdf-stock/pdf-stock-interface.vala
valac -X -w -o $@ --vapidir=../../vapi --enable-experimental --pkg gee-0.8 --pkg gio-2.0 --pkg libsoup-2.4 --pkg posix $^
clean:
diff --git a/src/web/main.vala b/src/web/main.vala
index 7070e66..aefe7fd 100644
--- a/src/web/main.vala
+++ b/src/web/main.vala
@@ -18,6 +18,7 @@ public CSVMemberFile csvimport;
public PGP pgp;
public Config cfg;
public AudioPlayer audio;
+public PDFStock pdfStock;
string templatedir;
public static int main(string[] args) {
@@ -27,10 +28,12 @@ public static int main(string[] args) {
uint port = 8080;
try {
- db = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.Database", "/io/mainframe/shopsystem/database");
- pgp = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.PGP", "/io/mainframe/shopsystem/pgp");
- cfg = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.Config", "/io/mainframe/shopsystem/config");
- audio = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.AudioPlayer", "/io/mainframe/shopsystem/audio");
+ db = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.Database", "/io/mainframe/shopsystem/database");
+ pgp = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.PGP", "/io/mainframe/shopsystem/pgp");
+ cfg = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.Config", "/io/mainframe/shopsystem/config");
+ audio = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.AudioPlayer", "/io/mainframe/shopsystem/audio");
+ pdfStock = Bus.get_proxy_sync(BusType.SYSTEM, "io.mainframe.shopsystem.StockPDF", "/io/mainframe/shopsystem/stockpdf");
+
templatedir = cfg.get_string("WEB", "filepath");
port = cfg.get_integer("WEB", "port");
diff --git a/src/web/web.vala b/src/web/web.vala
index ea0c667..5a44409 100644
--- a/src/web/web.vala
+++ b/src/web/web.vala
@@ -721,6 +721,149 @@ public class WebServer {
}
}
+ void handler_stock_as_pdf(Soup.Server server, Soup.Message msg, string path, GLib.HashTable<string,string>? query, Soup.ClientContext client) {
+ try {
+ var session = new WebSession(server, msg, path, query, client);
+ if(!session.superuser && !session.auth_products) {
+ handler_403(server, msg, path, query, client);
+ return;
+ }
+
+ var allProducts = query.contains("all");
+
+ var pdfdata = pdfStock.generate(allProducts);
+ msg.set_status(200);
+ msg.set_response("application/pdf", Soup.MemoryUse.COPY, pdfdata);
+ } catch(DatabaseError e) {
+ handler_400(server, msg, path, query, client, e.message);
+ } catch(IOError e) {
+ handler_400(server, msg, path, query, client, e.message);
+ }
+ }
+
+ void handler_products_inventory(Soup.Server server, Soup.Message msg, string path, GLib.HashTable<string,string>? query, Soup.ClientContext client) {
+ try {
+ var session = new WebSession(server, msg, path, query, client);
+ var template = new WebTemplate("products/inventory.html", session);
+ template.replace("TITLE", "KtT Shop System: Inventory");
+ template.menu_set_active("products");
+
+ if(!session.superuser && !session.auth_products) {
+ handler_403(server, msg, path, query, client);
+ return;
+ }
+
+ string table = "";
+ string actionTemplate = "";
+ string restockClassTemplate = "hidden";
+ string suppliersTemplate = "";
+ string usersTemplate = "";
+ string successClassTemplate = "hidden";
+ if (msg.method == "POST") {
+ var postdata = Soup.Form.decode((string) msg.request_body.data);
+
+ if (!postdata.contains("apply_inventory")) {
+ // PUT / show changes and request an apply
+ foreach(var e in db.get_stock()) {
+ var realAmountStr = postdata.get(e.id);
+ if (realAmountStr != null && realAmountStr.length > 0) {
+ var realAmount = int.parse(realAmountStr);
+ var amountStyleClass = "success";
+ if (realAmount < e.amount) {
+ amountStyleClass = "error";
+ } else if (realAmount > e.amount) {
+ amountStyleClass = "info";
+ }
+ var diff = realAmount - e.amount;
+ table += @"<tr class='$(amountStyleClass)'><td>$(e.id)</td><td>$(e.name)</td><td>$(e.category)</td><td>$(e.amount)</td><td>"
+ + @"$(realAmount) <strong>[ $(diff) ]</strong><input type=\"hidden\" name=\"$(e.id)\" value=\"$(realAmount)\"></td></tr>";
+ }
+ }
+ actionTemplate = """<input type="hidden" name="apply_inventory" value="true"><button type="submit" class="btn btn-primary">Apply Changes</button>""";
+
+ // a list of suppliers to choose
+ suppliersTemplate = "<option value=\"0\">Unknown</option>";
+ foreach(var e in db.get_supplier_list()) {
+ suppliersTemplate += "<option value=\"%lld\">%s</option>".printf(e.id, e.name);
+ }
+
+ // a list of users to choose
+ foreach(var uId in db.get_system_member_ids()) {
+ var user = db.get_user_info(uId);
+ usersTemplate += "<option value=\"%d\">%s %s (%d)</option>".printf(uId, user.firstname, user.lastname, uId);
+ }
+
+ restockClassTemplate = ""; // this shows the option list
+ } else {
+ // PUT / apply changes
+
+ var supplierId = int.parse(postdata.get("supplierId"));
+ var userId = int.parse(postdata.get("userId"));
+ foreach(var e in db.get_stock()) {
+ var realAmountStr = postdata.get(e.id);
+ if (realAmountStr != null && realAmountStr.length > 0) {
+ var pId = uint64.parse(e.id);
+ var realAmount = int.parse(realAmountStr);
+ if (realAmount < e.amount) {
+ // Loss transaction
+
+ for (int i=0; i< e.amount - realAmount; i++) {
+ db.buy(userId, pId);
+ }
+ } else if (realAmount > e.amount) {
+ // Restock
+
+ var amountDiff = realAmount - e.amount;
+ // find the latest bbd date
+ int64 maxBbd = 0;
+ foreach(var restock in db.get_restocks(pId, true)) {
+ if (restock.best_before_date > maxBbd) {
+ maxBbd = restock.best_before_date;
+ }
+ }
+
+ //stderr.printf("restock %d for %d, diff %d, supplier %d\n", (int)maxBbd, (int)pId, amountDiff, supplierId);
+ db.restock(session.user, pId, amountDiff, 0, supplierId, maxBbd);
+ }
+ }
+ }
+
+ msg.set_redirect(302, "/products/inventory?success=x");
+ return;
+ }
+ } else {
+ // default GET / list products with a form
+ var tabindexCounter = 1;
+ foreach(var e in db.get_stock()) {
+ table += @"<tr><td><a href=\"/products/$(e.id)\">$(e.id)</a></td><td><a href=\"/products/$(e.id)\">$(e.name)</a></td><td>$(e.category)</td><td>$(e.amount)</td><td><input type=\"number\" name=\"$(e.id)\" tabindex=\"$(tabindexCounter)\"></td></tr>";
+ tabindexCounter++;
+ }
+ actionTemplate = """<button type="submit" class="btn btn-primary">Preview</button>""";
+
+ if (query.contains("success")) {
+ successClassTemplate = "";
+ }
+ }
+
+ template.replace("SUCESS_HIDDEN", successClassTemplate);
+ template.replace("USERS", usersTemplate);
+ template.replace("SUPPLIERS", suppliersTemplate);
+ template.replace("RESTOCK_HIDDEN", restockClassTemplate);
+ template.replace("DATA", table);
+ template.replace("ACTION", actionTemplate);
+ msg.set_response("text/html", Soup.MemoryUse.COPY, template.data);
+ msg.set_status(200);
+ return;
+ } catch(TemplateError e) {
+ stderr.printf(e.message+"\n");
+ handler_404(server, msg, path, query, client);
+ } catch(DatabaseError e) {
+ handler_400(server, msg, path, query, client, e.message);
+ } catch(IOError e) {
+ handler_400(server, msg, path, query, client, e.message);
+ }
+ }
+
void handler_products_new(Soup.Server server, Soup.Message msg, string path, GLib.HashTable<string,string>? query, Soup.ClientContext client) {
try {
var session = new WebSession(server, msg, path, query, client);
@@ -1417,6 +1560,8 @@ public class WebServer {
srv.add_handler("/products", handler_products);
srv.add_handler("/products/new", handler_products_new);
srv.add_handler("/products/bestbefore", handler_product_bestbefore);
+ srv.add_handler("/products/inventory", handler_products_inventory);
+ srv.add_handler("/products/inventory-pdf", handler_stock_as_pdf);
srv.add_handler("/aliases", handler_alias_list);
srv.add_handler("/aliases/new", handler_alias_new);