Compare commits
4
Commits
5db402c7cf
..
0.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b5b690435 | ||
|
|
c6543cc583 | ||
|
|
05237cc7f1 | ||
|
|
176c2d8be5 |
No files matched your search
@@ -3,9 +3,10 @@ Un gestore di inventario e vendite minimale
|
|||||||
|
|
||||||
## Scaricarlo
|
## Scaricarlo
|
||||||
Disponibile solo per linux.
|
Disponibile solo per linux.
|
||||||
Scarica l'ultima versione da [qui](https://git.lug.uniroma2.it/rexeref/productManager/releases)!
|
Scarica l'ultima versione dalla pagina delle releases!
|
||||||
Avvia l'eseguibile da un terminale.
|
Avvia l'eseguibile da un terminale.
|
||||||
Se non si avvia rendilo prima un eseguibile con chmod +x
|
|
||||||
|
|
||||||
|
|
||||||
***questo codice molto probabilmente NON è sicuro, utilizzarlo a propria indiscrezione***
|
***questo codice molto probabilmente NON è sicuro, utilizzarlo a propria indiscrezione***
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
wip
|
||||||
@@ -7,5 +7,6 @@
|
|||||||
|
|
||||||
extern char productPricesFileLocation[64]; // Dichiarazione extern
|
extern char productPricesFileLocation[64]; // Dichiarazione extern
|
||||||
extern char countFileLocation[64];
|
extern char countFileLocation[64];
|
||||||
|
extern char configFileLocation[64];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef JSONFILE_H
|
||||||
|
#define JSONFILE_H
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
|
|
||||||
|
int existsFile(const char *fname);
|
||||||
|
int createFile(const char *fname);
|
||||||
|
int renameDataFile(const char *oldName, const char *newName);
|
||||||
|
|
||||||
|
json_object *loadJsonArray(const char *fname);
|
||||||
|
int saveJsonArray(const char *fname, json_object *arr);
|
||||||
|
|
||||||
|
json_object *findItemByName(json_object *arr, const char *name);
|
||||||
|
int removeItemByName(json_object *arr, const char *name);
|
||||||
|
int renameItemByName(json_object *arr, const char *oldName, const char *newName);
|
||||||
|
|
||||||
|
#endif
|
||||||
+18
-6
@@ -6,7 +6,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#include <json-c/json.h>
|
#include "jsonFile.h"
|
||||||
|
|
||||||
|
#define PRODUCT_STOCK_UNLIMITED (-1)
|
||||||
|
|
||||||
struct product {
|
struct product {
|
||||||
float cost;
|
float cost;
|
||||||
@@ -14,23 +16,33 @@ struct product {
|
|||||||
char name;
|
char name;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* File */
|
|
||||||
int existsFile(const char *fname);
|
|
||||||
int createFile(const char *fname);
|
|
||||||
int renameDataFile(const char *oldName, const char *newName);
|
|
||||||
|
|
||||||
/* Prodotti */
|
/* Prodotti */
|
||||||
json_object *getProducts(const char *fname);
|
json_object *getProducts(const char *fname);
|
||||||
void listProducts(const char *fname);
|
void listProducts(const char *fname);
|
||||||
int addProduct(const char *fname, const char *name, double price);
|
int addProduct(const char *fname, const char *name, double price);
|
||||||
|
int addProductWithInventory(const char *fname, const char *name, double price, int stock);
|
||||||
|
int addBundleProduct(const char *fname, const char *name, double price, json_object *components);
|
||||||
double getPrice(const char *fname, const char *name);
|
double getPrice(const char *fname, const char *name);
|
||||||
|
int updateProduct(const char *productsFile, const char *soldFile, const char *oldName, const char *newName, double price);
|
||||||
|
int updateProductWithInventory(const char *productsFile, const char *soldFile, const char *oldName, const char *newName, double price, int stock);
|
||||||
|
int getProductInventory(const char *fname, const char *name, int *stock, int *tracked);
|
||||||
|
int setProductInventory(const char *fname, const char *name, int stock, int tracked);
|
||||||
|
int consumeProductInventory(const char *fname, const char *name, int qty);
|
||||||
|
|
||||||
/* Copie vendute */
|
/* Copie vendute */
|
||||||
int getCount(const char *fname, const char *name);
|
int getCount(const char *fname, const char *name);
|
||||||
void listSold(const char *fname);
|
void listSold(const char *fname);
|
||||||
int addSold(const char *fname, const char *name, int qty);
|
int addSold(const char *fname, const char *name, int qty);
|
||||||
|
int updateSold(const char *fname, const char *name, int qty);
|
||||||
|
int deleteSold(const char *fname, const char *name);
|
||||||
|
int recordSale(const char *productsFile, const char *soldFile, const char *name, int qty);
|
||||||
|
|
||||||
/* Entrate */
|
/* Entrate */
|
||||||
double getTotalRevenue(const char *productsFile, const char *soldFile);
|
double getTotalRevenue(const char *productsFile, const char *soldFile);
|
||||||
|
|
||||||
|
/* Config */
|
||||||
|
int ensureAppConfig(const char *fname);
|
||||||
|
int loadAppConfig(const char *fname);
|
||||||
|
int saveAppConfig(const char *fname);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
int runMainMenu();
|
int runMainMenu();
|
||||||
void runOptionsMenu();
|
void runOptionsMenu();
|
||||||
void runSellWindow();
|
void runSellWindow();
|
||||||
|
void runCreateBundleWindow();
|
||||||
void runAboutWindow();
|
void runAboutWindow();
|
||||||
void runViewSalesWindow();
|
void runViewSalesWindow();
|
||||||
void runViewProductsWindow();
|
void runViewProductsWindow();
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ bundle: $(OBJECTS)
|
|||||||
$(CC) $^ -o dist/$(EXEC) $(BUNDLE_LDFLAGS) $(LDLIBS)
|
$(CC) $^ -o dist/$(EXEC) $(BUNDLE_LDFLAGS) $(LDLIBS)
|
||||||
@cp -L $$( $(PKG_CONFIG) --variable=libdir json-c )/libjson-c.so* dist/lib/
|
@cp -L $$( $(PKG_CONFIG) --variable=libdir json-c )/libjson-c.so* dist/lib/
|
||||||
@cp -L $$( $(PKG_CONFIG) --variable=libdir ncurses )/libncurses*.so* dist/lib/
|
@cp -L $$( $(PKG_CONFIG) --variable=libdir ncurses )/libncurses*.so* dist/lib/
|
||||||
@echo "=== Pacchetto portabile creato con successo in ./dist ==="
|
@tar czf productManager.tar.gz --directory dist/ .
|
||||||
|
@echo "=== Pacchetto portabile creato con successo in productManager.tar.gz ==="
|
||||||
|
@rm -fr dist/
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD_DIR) $(EXEC) dist *.json
|
rm -rf $(BUILD_DIR) $(EXEC) dist *.json
|
||||||
|
|||||||
@@ -2,4 +2,5 @@
|
|||||||
|
|
||||||
char productPricesFileLocation[64]="./pm-item-price-default.json";
|
char productPricesFileLocation[64]="./pm-item-price-default.json";
|
||||||
char countFileLocation[64]="./pm-item-sold-count-default.json";
|
char countFileLocation[64]="./pm-item-sold-count-default.json";
|
||||||
|
char configFileLocation[64]=".fpm";
|
||||||
|
|
||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
|
|
||||||
|
#include "../include/jsonFile.h"
|
||||||
|
|
||||||
|
int existsFile(const char *fname) {
|
||||||
|
FILE *file = fopen(fname, "r");
|
||||||
|
if (file) {
|
||||||
|
fclose(file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int createFile(const char *fname) {
|
||||||
|
json_object *arr = json_object_new_array();
|
||||||
|
if (!arr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int res = json_object_to_file_ext(fname, arr, JSON_C_TO_STRING_PRETTY);
|
||||||
|
json_object_put(arr);
|
||||||
|
return (res == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int renameDataFile(const char *oldName, const char *newName) {
|
||||||
|
return (rename(oldName, newName) == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static json_object *loadRawArray(const char *fname) {
|
||||||
|
if (!existsFile(fname) && createFile(fname) != 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
FILE *f = fopen(fname, "r");
|
||||||
|
if (!f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int empty = (fgetc(f) == EOF);
|
||||||
|
fclose(f);
|
||||||
|
if (empty)
|
||||||
|
return json_object_new_array();
|
||||||
|
|
||||||
|
json_object *arr = json_object_from_file(fname);
|
||||||
|
if (!arr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!json_object_is_type(arr, json_type_array)) {
|
||||||
|
json_object_put(arr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object *loadJsonArray(const char *fname) {
|
||||||
|
return loadRawArray(fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int saveJsonArray(const char *fname, json_object *arr) {
|
||||||
|
if (!arr)
|
||||||
|
return -1;
|
||||||
|
return (json_object_to_file_ext(fname, arr, JSON_C_TO_STRING_PRETTY) == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object *findItemByName(json_object *arr, const char *name) {
|
||||||
|
if (!arr || !name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size_t n = json_object_array_length(arr);
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
json_object *item = json_object_array_get_idx(arr, i);
|
||||||
|
json_object *jname = NULL;
|
||||||
|
|
||||||
|
if (json_object_object_get_ex(item, "name", &jname) &&
|
||||||
|
strcmp(json_object_get_string(jname), name) == 0)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int removeItemByName(json_object *arr, const char *name) {
|
||||||
|
if (!arr || !name)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
size_t n = json_object_array_length(arr);
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
json_object *item = json_object_array_get_idx(arr, i);
|
||||||
|
json_object *jname = NULL;
|
||||||
|
|
||||||
|
if (json_object_object_get_ex(item, "name", &jname) &&
|
||||||
|
strcmp(json_object_get_string(jname), name) == 0) {
|
||||||
|
json_object_array_del_idx(arr, (int)i, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int renameItemByName(json_object *arr, const char *oldName, const char *newName) {
|
||||||
|
if (!arr || !oldName || !newName)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
json_object *item = findItemByName(arr, oldName);
|
||||||
|
if (!item)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
json_object_object_add(item, "name", json_object_new_string(newName));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+606
-97
@@ -6,11 +6,327 @@
|
|||||||
|
|
||||||
#include "../include/logic.h"
|
#include "../include/logic.h"
|
||||||
#include "../include/globals.h"
|
#include "../include/globals.h"
|
||||||
|
#include "../include/jsonFile.h"
|
||||||
|
|
||||||
|
static int isBundleItem(json_object *item);
|
||||||
|
|
||||||
|
static int readInventory(json_object *item, int *stock, int *tracked) {
|
||||||
|
json_object *jstock = NULL;
|
||||||
|
|
||||||
|
if (!item || !stock || !tracked)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (isBundleItem(item)) {
|
||||||
|
*stock = PRODUCT_STOCK_UNLIMITED;
|
||||||
|
*tracked = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(item, "stock", &jstock) || !jstock) {
|
||||||
|
*stock = PRODUCT_STOCK_UNLIMITED;
|
||||||
|
*tracked = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*stock = json_object_get_int(jstock);
|
||||||
|
if (*stock < 0) {
|
||||||
|
*stock = PRODUCT_STOCK_UNLIMITED;
|
||||||
|
*tracked = 0;
|
||||||
|
} else {
|
||||||
|
*tracked = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeInventory(json_object *item, int stock, int tracked) {
|
||||||
|
if (!item)
|
||||||
|
return;
|
||||||
|
|
||||||
|
json_object_object_add(item, "stock",
|
||||||
|
json_object_new_int(tracked ? stock : PRODUCT_STOCK_UNLIMITED));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int loadProductItem(const char *fname, const char *name, json_object **arr_out, json_object **item_out) {
|
||||||
|
json_object *arr = loadJsonArray(fname);
|
||||||
|
if (!arr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
json_object *item = findItemByName(arr, name);
|
||||||
|
if (!item) {
|
||||||
|
json_object_put(arr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*arr_out = arr;
|
||||||
|
*item_out = item;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static json_object *buildAppConfigObject(void) {
|
||||||
|
json_object *obj = json_object_new_object();
|
||||||
|
if (!obj)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
json_object_object_add(obj, "productsFile", json_object_new_string(productPricesFileLocation));
|
||||||
|
json_object_object_add(obj, "salesFile", json_object_new_string(countFileLocation));
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int writeAppConfigObject(const char *fname, json_object *obj) {
|
||||||
|
if (!obj)
|
||||||
|
return -1;
|
||||||
|
return (json_object_to_file_ext(fname, obj, JSON_C_TO_STRING_PRETTY) == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int readConfigString(json_object *obj, const char *key, char *out, size_t outSize) {
|
||||||
|
json_object *v = NULL;
|
||||||
|
const char *s = NULL;
|
||||||
|
|
||||||
|
if (!obj || !key || !out || outSize == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (json_object_object_get_ex(obj, key, &v) && v)
|
||||||
|
s = json_object_get_string(v);
|
||||||
|
if (!s || s[0] == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
snprintf(out, outSize, "%s", s);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int isBundleItem(json_object *item) {
|
||||||
|
json_object *v = NULL;
|
||||||
|
return item && json_object_object_get_ex(item, "bundle", &v) && json_object_get_boolean(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getComponentQty(json_object *component) {
|
||||||
|
json_object *v = NULL;
|
||||||
|
|
||||||
|
if (!component)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(component, "qty", &v) || !v)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return json_object_get_int(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static json_object *getBundleComponents(json_object *bundleItem) {
|
||||||
|
json_object *components = NULL;
|
||||||
|
|
||||||
|
if (!bundleItem)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(bundleItem, "components", &components) || !components)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!json_object_is_type(components, json_type_array))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *bundleTagText(json_object *item) {
|
||||||
|
return isBundleItem(item) ? " [BUNDLE]" : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void formatProductLabel(json_object *item, char *buf, size_t size) {
|
||||||
|
json_object *v = NULL;
|
||||||
|
int tracked = 0;
|
||||||
|
int stock = PRODUCT_STOCK_UNLIMITED;
|
||||||
|
|
||||||
|
if (!buf || size == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isBundleItem(item)) {
|
||||||
|
snprintf(buf, size, "X");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_object_object_get_ex(item, "stock", &v) && v) {
|
||||||
|
stock = json_object_get_int(v);
|
||||||
|
tracked = stock >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tracked)
|
||||||
|
snprintf(buf, size, "%d", stock);
|
||||||
|
else
|
||||||
|
snprintf(buf, size, "X");
|
||||||
|
}
|
||||||
|
|
||||||
|
static json_object *findItemByNameExcluding(json_object *arr, const char *name, json_object *exclude) {
|
||||||
|
if (!arr || !name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size_t n = json_object_array_length(arr);
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
json_object *item = json_object_array_get_idx(arr, i);
|
||||||
|
json_object *jname = NULL;
|
||||||
|
|
||||||
|
if (item == exclude)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (json_object_object_get_ex(item, "name", &jname) &&
|
||||||
|
strcmp(json_object_get_string(jname), name) == 0)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int canConsumeTree(json_object *products, json_object *item, int qty) {
|
||||||
|
if (!products || !item || qty <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!isBundleItem(item)) {
|
||||||
|
json_object *jstock = NULL;
|
||||||
|
int stock = PRODUCT_STOCK_UNLIMITED;
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(item, "stock", &jstock) || !jstock)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
stock = json_object_get_int(jstock);
|
||||||
|
if (stock < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (stock >= qty) ? 0 : 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object *components = getBundleComponents(item);
|
||||||
|
if (!components)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
size_t count = json_object_array_length(components);
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
json_object *component = json_object_array_get_idx(components, i);
|
||||||
|
json_object *jname = NULL;
|
||||||
|
json_object *child = NULL;
|
||||||
|
int componentQty = getComponentQty(component);
|
||||||
|
|
||||||
|
if (componentQty <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(component, "name", &jname) || !jname)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
child = findItemByName(products, json_object_get_string(jname));
|
||||||
|
if (!child)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
int res = canConsumeTree(products, child, qty * componentQty);
|
||||||
|
if (res != 0)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int consumeTree(json_object *products, json_object *item, int qty) {
|
||||||
|
if (!products || !item || qty <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!isBundleItem(item)) {
|
||||||
|
json_object *jstock = NULL;
|
||||||
|
int stock = PRODUCT_STOCK_UNLIMITED;
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(item, "stock", &jstock) || !jstock)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
stock = json_object_get_int(jstock);
|
||||||
|
if (stock < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
json_object_object_add(item, "stock", json_object_new_int(stock - qty));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object *components = getBundleComponents(item);
|
||||||
|
if (!components)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
size_t count = json_object_array_length(components);
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
json_object *component = json_object_array_get_idx(components, i);
|
||||||
|
json_object *jname = NULL;
|
||||||
|
json_object *child = NULL;
|
||||||
|
int componentQty = getComponentQty(component);
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(component, "name", &jname) || !jname)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
child = findItemByName(products, json_object_get_string(jname));
|
||||||
|
if (!child)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
int res = consumeTree(products, child, qty * componentQty);
|
||||||
|
if (res != 0)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *loadFileText(const char *fname) {
|
||||||
|
FILE *f = fopen(fname, "rb");
|
||||||
|
long size;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
if (!f)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (fseek(f, 0, SEEK_END) != 0) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = ftell(f);
|
||||||
|
if (size < 0) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind(f);
|
||||||
|
buf = malloc((size_t)size + 1);
|
||||||
|
if (!buf) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size > 0 && fread(buf, 1, (size_t)size, f) != (size_t)size) {
|
||||||
|
free(buf);
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[size] = '\0';
|
||||||
|
fclose(f);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int saveFileText(const char *fname, const char *text) {
|
||||||
|
FILE *f = fopen(fname, "wb");
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (!f)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
len = strlen(text);
|
||||||
|
if (len > 0 && fwrite(text, 1, len, f) != len) {
|
||||||
|
fclose(f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Formato dei file (JSON):
|
* Formato dei file (JSON):
|
||||||
*
|
*
|
||||||
* File prodotti: [ {"name": "Maglietta S", "price": 19.90}, ... ]
|
* File prodotti: [ {"name": "Maglietta S", "price": 19.90, "stock": 12}, ... ]
|
||||||
|
* stock = numero intero, oppure -1 per inventario infinito
|
||||||
|
* bundle = 1, components = [ {"name": "...", "qty": 2}, ... ]
|
||||||
* File vendite: [ {"name": "Maglietta S", "sold": 12}, ... ]
|
* File vendite: [ {"name": "Maglietta S", "sold": 12}, ... ]
|
||||||
*
|
*
|
||||||
* Compilazione: aggiungere -ljson-c (e -lncurses) al linker.
|
* Compilazione: aggiungere -ljson-c (e -lncurses) al linker.
|
||||||
@@ -20,84 +336,6 @@
|
|||||||
* e.g. persona vuole acquistare maglietta S ma non c'è la taglia
|
* e.g. persona vuole acquistare maglietta S ma non c'è la taglia
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
|
||||||
/* Utilità sui file */
|
|
||||||
/* ------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
int existsFile(const char *fname) {
|
|
||||||
FILE *file = fopen(fname, "r");
|
|
||||||
if (file) {
|
|
||||||
fclose(file);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Crea un file JSON contenente un array vuoto. Ritorna 0 se ok, -1 se errore. */
|
|
||||||
int createFile(const char *fname) {
|
|
||||||
json_object *arr = json_object_new_array();
|
|
||||||
if (!arr)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
int res = json_object_to_file_ext(fname, arr, JSON_C_TO_STRING_PRETTY);
|
|
||||||
json_object_put(arr);
|
|
||||||
return (res == 0) ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cambia il nome di un file di dati. Ritorna 0 se ok, -1 se errore. */
|
|
||||||
int renameDataFile(const char *oldName, const char *newName) {
|
|
||||||
return (rename(oldName, newName) == 0) ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
|
||||||
/* Funzioni interne */
|
|
||||||
/* ------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Carica l'array JSON dal file (creandolo se non esiste).
|
|
||||||
* Il chiamante deve liberare il risultato con json_object_put().
|
|
||||||
* Ritorna NULL in caso di errore o se il contenuto non è un array.
|
|
||||||
*/
|
|
||||||
static json_object *loadArray(const char *fname) {
|
|
||||||
if (!existsFile(fname) && createFile(fname) != 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Un file vuoto (e.g. creato a mano o dalla vecchia createFile)
|
|
||||||
* non e' JSON valido: lo trattiamo come un array vuoto. */
|
|
||||||
FILE *f = fopen(fname, "r");
|
|
||||||
if (!f)
|
|
||||||
return NULL;
|
|
||||||
int empty = (fgetc(f) == EOF);
|
|
||||||
fclose(f);
|
|
||||||
if (empty)
|
|
||||||
return json_object_new_array();
|
|
||||||
|
|
||||||
json_object *arr = json_object_from_file(fname);
|
|
||||||
if (!arr)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!json_object_is_type(arr, json_type_array)) {
|
|
||||||
json_object_put(arr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cerca un elemento per nome. Ritorna l'oggetto (non va liberato) o NULL. */
|
|
||||||
static json_object *findByName(json_object *arr, const char *name) {
|
|
||||||
size_t n = json_object_array_length(arr);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
json_object *item = json_object_array_get_idx(arr, i);
|
|
||||||
json_object *jname;
|
|
||||||
|
|
||||||
if (json_object_object_get_ex(item, "name", &jname) &&
|
|
||||||
strcmp(json_object_get_string(jname), name) == 0)
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Prodotti */
|
/* Prodotti */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@@ -107,12 +345,12 @@ static json_object *findByName(json_object *arr, const char *name) {
|
|||||||
* oppure NULL in caso di errore.
|
* oppure NULL in caso di errore.
|
||||||
*/
|
*/
|
||||||
json_object *getProducts(const char *fname) {
|
json_object *getProducts(const char *fname) {
|
||||||
return loadArray(fname);
|
return loadJsonArray(fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stampa a schermo (ncurses) la lista dei prodotti con il relativo prezzo. */
|
/* Stampa a schermo (ncurses) la lista dei prodotti con il relativo prezzo. */
|
||||||
void listProducts(const char *fname) {
|
void listProducts(const char *fname) {
|
||||||
json_object *arr = loadArray(fname);
|
json_object *arr = loadJsonArray(fname);
|
||||||
if (!arr) {
|
if (!arr) {
|
||||||
printw("Errore nella lettura del file %s\n", fname);
|
printw("Errore nella lettura del file %s\n", fname);
|
||||||
refresh();
|
refresh();
|
||||||
@@ -126,12 +364,19 @@ void listProducts(const char *fname) {
|
|||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
json_object *item = json_object_array_get_idx(arr, i);
|
json_object *item = json_object_array_get_idx(arr, i);
|
||||||
json_object *jname, *jprice;
|
json_object *jname, *jprice;
|
||||||
|
char stockBuf[16];
|
||||||
|
|
||||||
if (json_object_object_get_ex(item, "name", &jname) &&
|
if (json_object_object_get_ex(item, "name", &jname) &&
|
||||||
json_object_object_get_ex(item, "price", &jprice))
|
json_object_object_get_ex(item, "price", &jprice))
|
||||||
printw("%zu) %-30s %8.2f\n", i + 1,
|
formatProductLabel(item, stockBuf, sizeof stockBuf);
|
||||||
|
|
||||||
|
if (json_object_object_get_ex(item, "name", &jname) &&
|
||||||
|
json_object_object_get_ex(item, "price", &jprice))
|
||||||
|
printw("%zu) %-30s %8.2f [%s]%s\n", i + 1,
|
||||||
json_object_get_string(jname),
|
json_object_get_string(jname),
|
||||||
json_object_get_double(jprice));
|
json_object_get_double(jprice),
|
||||||
|
stockBuf,
|
||||||
|
bundleTagText(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
@@ -143,11 +388,15 @@ void listProducts(const char *fname) {
|
|||||||
* Ritorna 0 se ok, -1 se errore, 1 se il prodotto esiste già.
|
* Ritorna 0 se ok, -1 se errore, 1 se il prodotto esiste già.
|
||||||
*/
|
*/
|
||||||
int addProduct(const char *fname, const char *name, double price) {
|
int addProduct(const char *fname, const char *name, double price) {
|
||||||
json_object *arr = loadArray(fname);
|
return addProductWithInventory(fname, name, price, PRODUCT_STOCK_UNLIMITED);
|
||||||
|
}
|
||||||
|
|
||||||
|
int addProductWithInventory(const char *fname, const char *name, double price, int stock) {
|
||||||
|
json_object *arr = loadJsonArray(fname);
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (findByName(arr, name)) {
|
if (findItemByName(arr, name)) {
|
||||||
json_object_put(arr);
|
json_object_put(arr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -155,21 +404,50 @@ int addProduct(const char *fname, const char *name, double price) {
|
|||||||
json_object *item = json_object_new_object();
|
json_object *item = json_object_new_object();
|
||||||
json_object_object_add(item, "name", json_object_new_string(name));
|
json_object_object_add(item, "name", json_object_new_string(name));
|
||||||
json_object_object_add(item, "price", json_object_new_double(price));
|
json_object_object_add(item, "price", json_object_new_double(price));
|
||||||
|
writeInventory(item, stock, stock != PRODUCT_STOCK_UNLIMITED);
|
||||||
json_object_array_add(arr, item);
|
json_object_array_add(arr, item);
|
||||||
|
|
||||||
int res = json_object_to_file_ext(fname, arr, JSON_C_TO_STRING_PRETTY);
|
int res = saveJsonArray(fname, arr);
|
||||||
|
json_object_put(arr);
|
||||||
|
return (res == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int addBundleProduct(const char *fname, const char *name, double price, json_object *components) {
|
||||||
|
json_object *arr = loadJsonArray(fname);
|
||||||
|
if (!arr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (findItemByName(arr, name)) {
|
||||||
|
json_object_put(arr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!components || !json_object_is_type(components, json_type_array) || json_object_array_length(components) == 0) {
|
||||||
|
json_object_put(arr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object *item = json_object_new_object();
|
||||||
|
json_object_object_add(item, "name", json_object_new_string(name));
|
||||||
|
json_object_object_add(item, "price", json_object_new_double(price));
|
||||||
|
json_object_object_add(item, "bundle", json_object_new_int(1));
|
||||||
|
json_object_object_add(item, "stock", json_object_new_int(PRODUCT_STOCK_UNLIMITED));
|
||||||
|
json_object_object_add(item, "components", components);
|
||||||
|
json_object_array_add(arr, item);
|
||||||
|
|
||||||
|
int res = saveJsonArray(fname, arr);
|
||||||
json_object_put(arr);
|
json_object_put(arr);
|
||||||
return (res == 0) ? 0 : -1;
|
return (res == 0) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ritorna il prezzo di un prodotto, oppure -1.0 se non trovato/errore. */
|
/* Ritorna il prezzo di un prodotto, oppure -1.0 se non trovato/errore. */
|
||||||
double getPrice(const char *fname, const char *name) {
|
double getPrice(const char *fname, const char *name) {
|
||||||
json_object *arr = loadArray(fname);
|
json_object *arr = loadJsonArray(fname);
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return -1.0;
|
return -1.0;
|
||||||
|
|
||||||
double price = -1.0;
|
double price = -1.0;
|
||||||
json_object *item = findByName(arr, name);
|
json_object *item = findItemByName(arr, name);
|
||||||
json_object *jprice;
|
json_object *jprice;
|
||||||
|
|
||||||
if (item && json_object_object_get_ex(item, "price", &jprice))
|
if (item && json_object_object_get_ex(item, "price", &jprice))
|
||||||
@@ -179,18 +457,142 @@ double getPrice(const char *fname, const char *name) {
|
|||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int updateProduct(const char *productsFile, const char *soldFile, const char *oldName, const char *newName, double price) {
|
||||||
|
json_object *products = NULL;
|
||||||
|
json_object *item = NULL;
|
||||||
|
int stock = PRODUCT_STOCK_UNLIMITED;
|
||||||
|
int tracked = 0;
|
||||||
|
|
||||||
|
if (loadProductItem(productsFile, oldName, &products, &item) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
readInventory(item, &stock, &tracked);
|
||||||
|
json_object_put(products);
|
||||||
|
|
||||||
|
return updateProductWithInventory(productsFile, soldFile, oldName, newName, price,
|
||||||
|
tracked ? stock : PRODUCT_STOCK_UNLIMITED);
|
||||||
|
}
|
||||||
|
|
||||||
|
int updateProductWithInventory(const char *productsFile, const char *soldFile, const char *oldName, const char *newName, double price, int stock) {
|
||||||
|
json_object *products = loadJsonArray(productsFile);
|
||||||
|
if (!products)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
json_object *item = findItemByName(products, oldName);
|
||||||
|
if (!item) {
|
||||||
|
json_object_put(products);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(oldName, newName) != 0 && findItemByNameExcluding(products, newName, item)) {
|
||||||
|
json_object_put(products);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_object_add(item, "name", json_object_new_string(newName));
|
||||||
|
json_object_object_add(item, "price", json_object_new_double(price));
|
||||||
|
writeInventory(item, stock, stock != PRODUCT_STOCK_UNLIMITED);
|
||||||
|
|
||||||
|
if (saveJsonArray(productsFile, products) != 0) {
|
||||||
|
json_object_put(products);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
json_object_put(products);
|
||||||
|
|
||||||
|
if (strcmp(oldName, newName) != 0) {
|
||||||
|
json_object *sales = loadJsonArray(soldFile);
|
||||||
|
if (!sales)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (renameItemByName(sales, oldName, newName) != 0) {
|
||||||
|
json_object_put(sales);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveJsonArray(soldFile, sales) != 0) {
|
||||||
|
json_object_put(sales);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
json_object_put(sales);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getProductInventory(const char *fname, const char *name, int *stock, int *tracked) {
|
||||||
|
json_object *arr = loadJsonArray(fname);
|
||||||
|
if (!arr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
json_object *item = findItemByName(arr, name);
|
||||||
|
if (!item) {
|
||||||
|
json_object_put(arr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res = readInventory(item, stock, tracked);
|
||||||
|
json_object_put(arr);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setProductInventory(const char *fname, const char *name, int stock, int tracked) {
|
||||||
|
json_object *arr = loadJsonArray(fname);
|
||||||
|
if (!arr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
json_object *item = findItemByName(arr, name);
|
||||||
|
if (!item) {
|
||||||
|
json_object_put(arr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeInventory(item, stock, tracked);
|
||||||
|
|
||||||
|
int res = saveJsonArray(fname, arr);
|
||||||
|
json_object_put(arr);
|
||||||
|
return (res == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int consumeProductInventory(const char *fname, const char *name, int qty) {
|
||||||
|
json_object *arr = loadJsonArray(fname);
|
||||||
|
if (!arr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
json_object *item = findItemByName(arr, name);
|
||||||
|
if (!item) {
|
||||||
|
json_object_put(arr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int check = canConsumeTree(arr, item, qty);
|
||||||
|
if (check != 0) {
|
||||||
|
json_object_put(arr);
|
||||||
|
return check;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res = consumeTree(arr, item, qty);
|
||||||
|
if (res != 0) {
|
||||||
|
json_object_put(arr);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = saveJsonArray(fname, arr);
|
||||||
|
json_object_put(arr);
|
||||||
|
return (res == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Copie vendute */
|
/* Copie vendute */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
/* Ritorna le copie vendute di un prodotto (0 se non presente, -1 se errore). */
|
/* Ritorna le copie vendute di un prodotto (0 se non presente, -1 se errore). */
|
||||||
int getCount(const char *fname, const char *name) {
|
int getCount(const char *fname, const char *name) {
|
||||||
json_object *arr = loadArray(fname);
|
json_object *arr = loadJsonArray(fname);
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
json_object *item = findByName(arr, name);
|
json_object *item = findItemByName(arr, name);
|
||||||
json_object *jsold;
|
json_object *jsold;
|
||||||
|
|
||||||
if (item && json_object_object_get_ex(item, "sold", &jsold))
|
if (item && json_object_object_get_ex(item, "sold", &jsold))
|
||||||
@@ -202,7 +604,7 @@ int getCount(const char *fname, const char *name) {
|
|||||||
|
|
||||||
/* Stampa a schermo (ncurses) le copie vendute di ogni prodotto. */
|
/* Stampa a schermo (ncurses) le copie vendute di ogni prodotto. */
|
||||||
void listSold(const char *fname) {
|
void listSold(const char *fname) {
|
||||||
json_object *arr = loadArray(fname);
|
json_object *arr = loadJsonArray(fname);
|
||||||
if (!arr) {
|
if (!arr) {
|
||||||
printw("Errore nella lettura del file %s\n", fname);
|
printw("Errore nella lettura del file %s\n", fname);
|
||||||
refresh();
|
refresh();
|
||||||
@@ -234,11 +636,11 @@ void listSold(const char *fname) {
|
|||||||
* Ritorna 0 se ok, -1 se errore.
|
* Ritorna 0 se ok, -1 se errore.
|
||||||
*/
|
*/
|
||||||
int addSold(const char *fname, const char *name, int qty) {
|
int addSold(const char *fname, const char *name, int qty) {
|
||||||
json_object *arr = loadArray(fname);
|
json_object *arr = loadJsonArray(fname);
|
||||||
if (!arr)
|
if (!arr)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
json_object *item = findByName(arr, name);
|
json_object *item = findItemByName(arr, name);
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
json_object *jsold;
|
json_object *jsold;
|
||||||
@@ -255,7 +657,71 @@ int addSold(const char *fname, const char *name, int qty) {
|
|||||||
json_object_array_add(arr, item);
|
json_object_array_add(arr, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = json_object_to_file_ext(fname, arr, JSON_C_TO_STRING_PRETTY);
|
int res = saveJsonArray(fname, arr);
|
||||||
|
json_object_put(arr);
|
||||||
|
return (res == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int recordSale(const char *productsFile, const char *soldFile, const char *name, int qty) {
|
||||||
|
char *backup = NULL;
|
||||||
|
int consumeRes;
|
||||||
|
|
||||||
|
if (qty <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!existsFile(productsFile) && createFile(productsFile) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
backup = loadFileText(productsFile);
|
||||||
|
if (!backup)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
consumeRes = consumeProductInventory(productsFile, name, qty);
|
||||||
|
if (consumeRes != 0) {
|
||||||
|
free(backup);
|
||||||
|
return consumeRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addSold(soldFile, name, qty) != 0) {
|
||||||
|
saveFileText(productsFile, backup);
|
||||||
|
free(backup);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(backup);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int updateSold(const char *fname, const char *name, int qty) {
|
||||||
|
json_object *arr = loadJsonArray(fname);
|
||||||
|
if (!arr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
json_object *item = findItemByName(arr, name);
|
||||||
|
if (!item) {
|
||||||
|
json_object_put(arr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object_object_add(item, "sold", json_object_new_int(qty));
|
||||||
|
|
||||||
|
int res = saveJsonArray(fname, arr);
|
||||||
|
json_object_put(arr);
|
||||||
|
return (res == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int deleteSold(const char *fname, const char *name) {
|
||||||
|
json_object *arr = loadJsonArray(fname);
|
||||||
|
if (!arr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int res = removeItemByName(arr, name);
|
||||||
|
if (res != 0) {
|
||||||
|
json_object_put(arr);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = saveJsonArray(fname, arr);
|
||||||
json_object_put(arr);
|
json_object_put(arr);
|
||||||
return (res == 0) ? 0 : -1;
|
return (res == 0) ? 0 : -1;
|
||||||
}
|
}
|
||||||
@@ -269,11 +735,11 @@ int addSold(const char *fname, const char *name, int qty) {
|
|||||||
* per ogni prodotto. Ritorna -1.0 in caso di errore.
|
* per ogni prodotto. Ritorna -1.0 in caso di errore.
|
||||||
*/
|
*/
|
||||||
double getTotalRevenue(const char *productsFile, const char *soldFile) {
|
double getTotalRevenue(const char *productsFile, const char *soldFile) {
|
||||||
json_object *products = loadArray(productsFile);
|
json_object *products = loadJsonArray(productsFile);
|
||||||
if (!products)
|
if (!products)
|
||||||
return -1.0;
|
return -1.0;
|
||||||
|
|
||||||
json_object *sales = loadArray(soldFile);
|
json_object *sales = loadJsonArray(soldFile);
|
||||||
if (!sales) {
|
if (!sales) {
|
||||||
json_object_put(products);
|
json_object_put(products);
|
||||||
return -1.0;
|
return -1.0;
|
||||||
@@ -290,7 +756,7 @@ double getTotalRevenue(const char *productsFile, const char *soldFile) {
|
|||||||
!json_object_object_get_ex(sale, "sold", &jsold))
|
!json_object_object_get_ex(sale, "sold", &jsold))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
json_object *prod = findByName(products, json_object_get_string(jname));
|
json_object *prod = findItemByName(products, json_object_get_string(jname));
|
||||||
if (prod && json_object_object_get_ex(prod, "price", &jprice))
|
if (prod && json_object_object_get_ex(prod, "price", &jprice))
|
||||||
total += json_object_get_double(jprice) * json_object_get_int(jsold);
|
total += json_object_get_double(jprice) * json_object_get_int(jsold);
|
||||||
}
|
}
|
||||||
@@ -299,3 +765,46 @@ double getTotalRevenue(const char *productsFile, const char *soldFile) {
|
|||||||
json_object_put(sales);
|
json_object_put(sales);
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int saveAppConfig(const char *fname) {
|
||||||
|
json_object *obj = buildAppConfigObject();
|
||||||
|
if (!obj)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int res = writeAppConfigObject(fname, obj);
|
||||||
|
json_object_put(obj);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ensureAppConfig(const char *fname) {
|
||||||
|
if (!existsFile(fname))
|
||||||
|
return saveAppConfig(fname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int loadAppConfig(const char *fname) {
|
||||||
|
json_object *obj = NULL;
|
||||||
|
json_object *loaded = NULL;
|
||||||
|
|
||||||
|
if (ensureAppConfig(fname) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
loaded = json_object_from_file(fname);
|
||||||
|
if (!loaded || !json_object_is_type(loaded, json_type_object)) {
|
||||||
|
if (loaded)
|
||||||
|
json_object_put(loaded);
|
||||||
|
return saveAppConfig(fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
readConfigString(loaded, "productsFile", productPricesFileLocation, sizeof productPricesFileLocation);
|
||||||
|
readConfigString(loaded, "salesFile", countFileLocation, sizeof countFileLocation);
|
||||||
|
|
||||||
|
obj = buildAppConfigObject();
|
||||||
|
if (!obj) {
|
||||||
|
json_object_put(loaded);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
json_object_put(obj);
|
||||||
|
json_object_put(loaded);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+4
-24
@@ -22,6 +22,7 @@
|
|||||||
#include "../include/windowsDeclaration.h"
|
#include "../include/windowsDeclaration.h"
|
||||||
#include "../include/windowsBack.h"
|
#include "../include/windowsBack.h"
|
||||||
#include "../include/logic.h"
|
#include "../include/logic.h"
|
||||||
|
#include "../include/globals.h"
|
||||||
|
|
||||||
void printLogoBG();
|
void printLogoBG();
|
||||||
|
|
||||||
@@ -43,36 +44,15 @@ int main(){
|
|||||||
noecho();
|
noecho();
|
||||||
curs_set(0);
|
curs_set(0);
|
||||||
raw();
|
raw();
|
||||||
|
if (loadAppConfig(configFileLocation) != 0)
|
||||||
|
warningf("Impossibile caricare la config '%s', uso i valori di default.", configFileLocation);
|
||||||
printLogoBG();
|
printLogoBG();
|
||||||
statusf(" ");
|
statusf(" ");
|
||||||
refresh();
|
refresh();
|
||||||
|
|
||||||
|
while (runMainMenu()) {
|
||||||
int running = 0;
|
|
||||||
while(running != 6){
|
|
||||||
printLogoBG();
|
printLogoBG();
|
||||||
refresh();
|
refresh();
|
||||||
running = runMainMenu();
|
|
||||||
switch(running) {
|
|
||||||
case 1:
|
|
||||||
runSellWindow();
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
runViewSalesWindow();
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
runViewProductsWindow();
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
runAddProductWindow();
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
runAboutWindow();
|
|
||||||
// runOptionsMenu();
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
endwin();
|
endwin();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
|
|
||||||
#include "../include/windowsBack.h"
|
#include "../include/windowsBack.h"
|
||||||
|
|||||||
+844
-194
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user