Compare commits
6
Commits
8b5b690435
...
0.2.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fb76ebed6 | ||
|
|
c670aceafb | ||
|
|
fa0e377811 | ||
|
|
defa951e51 | ||
|
|
c088caf03e | ||
|
|
8cd79da5eb |
No files matched your search
@@ -3,15 +3,66 @@
|
||||
|
||||
#include <json-c/json.h>
|
||||
|
||||
/**
|
||||
* @brief Verifica se un file esiste sul disco.
|
||||
* @param fname Percorso del file da controllare.
|
||||
* @return 1 se il file esiste ed è accessibile, 0 altrimenti.
|
||||
*/
|
||||
int existsFile(const char *fname);
|
||||
|
||||
/**
|
||||
* @brief Crea un nuovo file JSON inizializzandolo con un array vuoto ([]).
|
||||
* @param fname Percorso del file da creare.
|
||||
* @return 0 in caso di successo, -1 in caso di errore.
|
||||
*/
|
||||
int createFile(const char *fname);
|
||||
|
||||
/**
|
||||
* @brief Rinomina o sposta un file esistente.
|
||||
* @param oldName Vecchio percorso/nome del file.
|
||||
* @param newName Nuovo percorso/nome del file.
|
||||
* @return 0 in caso di successo, -1 in caso di errore.
|
||||
*/
|
||||
int renameDataFile(const char *oldName, const char *newName);
|
||||
|
||||
/**
|
||||
* @brief Carica un array JSON da file. Se il file non esiste, lo crea automaticamente.
|
||||
* @param fname Percorso del file JSON.
|
||||
* @return Puntatore all'oggetto JSON (array) caricato, oppure NULL in caso di errore.
|
||||
*/
|
||||
json_object *loadJsonArray(const char *fname);
|
||||
|
||||
/**
|
||||
* @brief Salva un array JSON su file formattandolo in modo leggibile (indentato).
|
||||
* @param fname Percorso del file di destinazione.
|
||||
* @param arr L'oggetto JSON (array) da salvare.
|
||||
* @return 0 in caso di successo, -1 in caso di errore.
|
||||
*/
|
||||
int saveJsonArray(const char *fname, json_object *arr);
|
||||
|
||||
/**
|
||||
* @brief Cerca un oggetto all'interno di un array JSON basandosi sul campo "name".
|
||||
* @param arr L'array JSON in cui effettuare la ricerca.
|
||||
* @param name La stringa del nome da cercare.
|
||||
* @return Puntatore all'oggetto JSON trovato, oppure NULL se non esiste.
|
||||
*/
|
||||
json_object *findItemByName(json_object *arr, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Rimuove un oggetto da un array JSON basandosi sul campo "name".
|
||||
* @param arr L'array JSON da cui rimuovere l'elemento.
|
||||
* @param name Il nome dell'elemento da eliminare.
|
||||
* @return 0 in caso di successo, 1 se l'elemento non viene trovato, -1 in caso di errore.
|
||||
*/
|
||||
int removeItemByName(json_object *arr, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Modifica il campo "name" di un elemento all'interno di un array JSON.
|
||||
* @param arr L'array JSON contenente l'elemento.
|
||||
* @param oldName Il nome attuale dell'elemento da rinominare.
|
||||
* @param newName Il nuovo nome da assegnare.
|
||||
* @return 0 in caso di successo, 1 se l'elemento non viene trovato, -1 in caso di errore.
|
||||
*/
|
||||
int renameItemByName(json_object *arr, const char *oldName, const char *newName);
|
||||
|
||||
#endif
|
||||
+148
-15
@@ -1,7 +1,6 @@
|
||||
#ifndef LOGIC_H
|
||||
#define LOGIC_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -16,33 +15,167 @@ struct product {
|
||||
char name;
|
||||
};
|
||||
|
||||
/* Prodotti */
|
||||
json_object *getProducts(const char *fname);
|
||||
void listProducts(const char *fname);
|
||||
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);
|
||||
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);
|
||||
/*
|
||||
* Modello dati: nel file prodotti si salva solo la giacenza INIZIALE ("initial").
|
||||
* Lo stock corrente e' sempre calcolato: initial - copie vendute
|
||||
* (comprese quelle consumate tramite bundle). Le vendite scrivono solo il file vendite.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Prodotti */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* @brief Restituisce l'array JSON contenente tutti i prodotti, cosi' come salvati su file
|
||||
* (quindi con "initial" e senza stock corrente).
|
||||
* @param fname Percorso del file JSON dei prodotti.
|
||||
* @return Array JSON (da liberare con json_object_put()), oppure NULL in caso di errore.
|
||||
*/
|
||||
json_object *getProducts(const char *fname);
|
||||
|
||||
/**
|
||||
* @brief Come getProducts, ma ogni prodotto ha in piu' il campo "stock" calcolato
|
||||
* (-1 = infinito; i bundle hanno sempre -1). E' una vista in memoria: non va salvata.
|
||||
* @param productsFile Percorso del file JSON dei prodotti.
|
||||
* @param soldFile Percorso del file JSON delle vendite (se manca, si assume nessuna vendita).
|
||||
* @return Array JSON (da liberare con json_object_put()), oppure NULL in caso di errore.
|
||||
*/
|
||||
json_object *getProductsWithStock(const char *productsFile, const char *soldFile);
|
||||
|
||||
/**
|
||||
* @brief Aggiunge un nuovo prodotto con prezzo e inventario illimitato.
|
||||
* @return 0 in caso di successo, 1 se il prodotto esiste gia', -1 in caso di errore.
|
||||
*/
|
||||
int addProduct(const char *fname, const char *name, double price);
|
||||
|
||||
/**
|
||||
* @brief Aggiunge un nuovo prodotto specificando prezzo e giacenza iniziale.
|
||||
* @param stock Giacenza iniziale (negativo per inventario illimitato).
|
||||
* @return 0 in caso di successo, 1 se il prodotto esiste gia', -1 in caso di errore.
|
||||
*/
|
||||
int addProductWithInventory(const char *fname, const char *name, double price, int stock);
|
||||
|
||||
/**
|
||||
* @brief Aggiunge un prodotto composto (bundle).
|
||||
* @param components Array JSON di {"name": ..., "qty": ...}; il bundle ne prende possesso in caso di successo.
|
||||
* @return 0 in caso di successo, 1 se il prodotto esiste gia', -1 in caso di errore.
|
||||
*/
|
||||
int addBundleProduct(const char *fname, const char *name, double price, json_object *components);
|
||||
|
||||
/**
|
||||
* @brief Ottiene il prezzo di un prodotto.
|
||||
* @return Il prezzo, oppure -1.0 se non trovato o in caso di errore.
|
||||
*/
|
||||
double getPrice(const char *fname, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Aggiorna nome e prezzo di un prodotto lasciando invariato lo stock corrente.
|
||||
* @return 0 ok, 1 non trovato, 2 nome gia' usato, -1 errore.
|
||||
*/
|
||||
int updateProduct(const char *productsFile, const char *soldFile, const char *oldName, const char *newName, double price);
|
||||
|
||||
/**
|
||||
* @brief Aggiorna nome, prezzo e stock di un prodotto.
|
||||
* Se il nome cambia aggiorna nella stessa operazione file vendite e riferimenti nei bundle.
|
||||
* @param stock Giacenza ATTUALE desiderata (negativo = infinita).
|
||||
* @return 0 ok, 1 non trovato, 2 nome gia' usato, -1 errore.
|
||||
*/
|
||||
int updateProductWithInventory(const char *productsFile, const char *soldFile, const char *oldName, const char *newName, double price, int stock);
|
||||
|
||||
/**
|
||||
* @brief Legge lo stock corrente (calcolato) di un prodotto.
|
||||
* @param productsFile Percorso del file JSON dei prodotti.
|
||||
* @param soldFile Percorso del file JSON delle vendite.
|
||||
* @param name Nome del prodotto.
|
||||
* @param stock Quantita' corrente (PRODUCT_STOCK_UNLIMITED se non tracciato).
|
||||
* @param tracked 1 se l'inventario e' tracciato, 0 altrimenti.
|
||||
* @return 0 ok, 1 prodotto non trovato, -1 errore.
|
||||
*/
|
||||
int getProductInventory(const char *productsFile, const char *soldFile, const char *name, int *stock, int *tracked);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Copie vendute */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* @brief Numero di copie vendute di un prodotto.
|
||||
* @return Copie vendute (0 se non presente, -1 in caso di errore).
|
||||
*/
|
||||
int getCount(const char *fname, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Stampa a schermo (ncurses) le vendite registrate per ciascun prodotto.
|
||||
*/
|
||||
void listSold(const char *fname);
|
||||
|
||||
/**
|
||||
* @brief Aggiunge copie vendute per un prodotto (crea la voce se non esiste).
|
||||
* Non controlla lo stock: per questo usare recordSale().
|
||||
* @return 0 ok, -1 errore.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief Elimina la registrazione delle vendite di un prodotto.
|
||||
* Lo stock si "ripristina" da solo perche' e' derivato.
|
||||
* @param productsFile Non usato, mantenuto per compatibilita'.
|
||||
* @return 0 ok, 1 vendita non presente, -1 errore.
|
||||
*/
|
||||
int deleteSold(const char *productsFile, const char *soldFile, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Imposta le copie vendute di un prodotto; se aumentano controlla la disponibilita'.
|
||||
* @return 0 ok, 1 vendita non presente, 2 scorta insufficiente, -1 errore.
|
||||
*/
|
||||
int updateSold(const char *productsFile, const char *soldFile, const char *name, int qty);
|
||||
|
||||
/**
|
||||
* @brief Registra una vendita dopo aver verificato la disponibilita' (anche dei componenti, se bundle).
|
||||
* Scrive solo il file vendite.
|
||||
* @return 0 ok, 1 prodotto inesistente, 2 scorta insufficiente, -1 errore.
|
||||
*/
|
||||
int recordSale(const char *productsFile, const char *soldFile, const char *name, int qty);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Entrate */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* @brief Entrate totali: somma di prezzo * copie vendute.
|
||||
* @return Il totale, oppure -1.0 in caso di errore.
|
||||
*/
|
||||
double getTotalRevenue(const char *productsFile, const char *soldFile);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Export */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* @brief Esporta prodotti e vendite in CSV (separatore ';').
|
||||
* @return 0 ok, -1 errore di lettura prodotti, -2 errore di apertura del file di destinazione.
|
||||
*/
|
||||
int exportSalesToCsv(const char *productsFile, const char *soldFile, const char *outFile);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Config */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* @brief Crea il file di configurazione se non esiste.
|
||||
* @return 0 ok, altro in caso di errore.
|
||||
*/
|
||||
int ensureAppConfig(const char *fname);
|
||||
|
||||
/**
|
||||
* @brief Carica la configurazione dal file specificato.
|
||||
* @return 0 ok, -1 errore.
|
||||
*/
|
||||
int loadAppConfig(const char *fname);
|
||||
|
||||
/**
|
||||
* @brief Salva la configurazione corrente sul file specificato.
|
||||
* @return 0 ok, -1 errore.
|
||||
*/
|
||||
int saveAppConfig(const char *fname);
|
||||
|
||||
#endif
|
||||
@@ -6,18 +6,95 @@
|
||||
#include <string.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
/**
|
||||
* @brief Crea e restituisce una nuova finestra ncurses con i bordi tracciati.
|
||||
* @param height Altezza della finestra.
|
||||
* @param width Larghezza della finestra.
|
||||
* @param starty Coordinata Y iniziale sullo schermo.
|
||||
* @param startx Coordinata X iniziale sullo schermo.
|
||||
* @return Puntatore all'oggetto WINDOW creato.
|
||||
*/
|
||||
WINDOW *create_newwin(int height, int width, int starty, int startx);
|
||||
|
||||
/**
|
||||
* @brief Distrugge una finestra ncurses creata in precedenza e libera la memoria associata.
|
||||
* @param local_win Puntatore alla finestra da eliminare.
|
||||
*/
|
||||
void destroy_win(WINDOW *local_win);
|
||||
|
||||
/**
|
||||
* @brief Stampa del testo all'interno di una finestra gestendo l'andata a capo automatica (word wrapping) per parola.
|
||||
* @param win Finestra in cui stampare.
|
||||
* @param start_y Coordinata Y iniziale all'interno della finestra.
|
||||
* @param start_x Coordinata X iniziale all'interno della finestra.
|
||||
* @param str Stringa di testo da stampare.
|
||||
*/
|
||||
void wwrap_print(WINDOW *win, int start_y, int start_x, const char *str);
|
||||
|
||||
/**
|
||||
* @brief Gestisce un interruttore grafico interattivo (stato ON/OFF) modificabile da tastiera.
|
||||
* @param win Finestra di visualizzazione.
|
||||
* @param y Coordinata Y dell'interruttore.
|
||||
* @param x Coordinata X dell'interruttore.
|
||||
* @param state Stato iniziale (1 per ON, 0 per OFF).
|
||||
* @return Lo stato finale dell'interruttore dopo l'interazione dell'utente.
|
||||
*/
|
||||
int uiToggleSwitch(WINDOW *win, int y, int x, int state);
|
||||
|
||||
/**
|
||||
* @brief Gestisce un campo di input di testo interattivo all'interno di una finestra ncurses.
|
||||
* @param win Finestra in cui inserire il testo.
|
||||
* @param y Coordinata Y.
|
||||
* @param x Coordinata X.
|
||||
* @param input Buffer contenente l'eventuale testo iniziale e in cui memorizzare il risultato digitato.
|
||||
* @param max_len Lunghezza massima consentita per l'input.
|
||||
*/
|
||||
void uiTextInput(WINDOW *win, int y, int x, char *input, int max_len);
|
||||
|
||||
/**
|
||||
* @brief Mostra un menu di scelta multipla navigabile da tastiera tramite frecce o tasti vim (j/k).
|
||||
* @param win Finestra in cui mostrare il menu.
|
||||
* @param start_y Coordinata Y iniziale.
|
||||
* @param start_x Coordinata X iniziale.
|
||||
* @param options Array di stringhe contenente le opzioni del menu.
|
||||
* @param n_options Numero totale di opzioni disponibili.
|
||||
* @return L'indice (1-based) della voce selezionata dall'utente.
|
||||
*/
|
||||
int uiSelectMenu(WINDOW *win, int start_y, int start_x, char **options, int n_options);
|
||||
|
||||
/**
|
||||
* @brief Stampa un menu all'interno di una finestra evidenziando una voce specifica.
|
||||
* @param menu_win Finestra del menu.
|
||||
* @param y Coordinata Y.
|
||||
* @param x Coordinata X.
|
||||
* @param highlight Indice della voce da evidenziare graficamente.
|
||||
*/
|
||||
void print_menu(WINDOW *menu_win, int y, int x, int highlight);
|
||||
|
||||
/**
|
||||
* @brief Mostra una finestra di avviso (warning) utilizzando una stringa formattata (stile printf).
|
||||
* @param fmt Stringa di formattazione.
|
||||
* @param ... Argomenti variabili da formattare.
|
||||
*/
|
||||
void warningf(const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* @brief Apre una finestra di popup con un messaggio di avviso e attende la pressione di un tasto per chiudersi.
|
||||
* @param string Messaggio di errore o avviso da mostrare.
|
||||
*/
|
||||
void warning(char *string);
|
||||
|
||||
/**
|
||||
* @brief Aggiorna la barra di stato in basso sullo schermo con un messaggio formattato (stile printf).
|
||||
* @param fmt Stringa di formattazione.
|
||||
* @param ... Argomenti variabili da formattare.
|
||||
*/
|
||||
void statusf(const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* @brief Scrive un messaggio direttamente nella barra di stato in basso sullo schermo.
|
||||
* @param msg Messaggio da visualizzare nella status bar.
|
||||
*/
|
||||
void status(char *msg);
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,7 @@ void runAboutWindow();
|
||||
void runViewSalesWindow();
|
||||
void runViewProductsWindow();
|
||||
void runAddProductWindow();
|
||||
void runExportCsvWindow();
|
||||
void example_window();
|
||||
|
||||
#endif
|
||||
@@ -36,6 +36,6 @@ bundle: $(OBJECTS)
|
||||
@rm -fr dist/
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR) $(EXEC) dist *.json
|
||||
rm -rf $(BUILD_DIR) $(EXEC) dist *.json .fpm
|
||||
|
||||
.PHONY: all clean bundle
|
||||
+504
-501
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -61,6 +61,6 @@ int main(){
|
||||
|
||||
|
||||
void printLogoBG(){
|
||||
wwrap_print(stdscr, LINES / 2 - 3, COLS / 2 - 5," ######### \n ################### \n ######## ##### \n ####### ### \n ###### ### \n ###### ### ## \n ############ # ### ## \n ################ ### # \n ############ ##### # \n ############## \n ######### \n ## \n ####### \n ## ## \n ## ## ###### ## ## # ## ## \n ###### ##### ######## #### ## ## ## # ## \n ## ## ## ## ## ## ## ##### ## ## ## # ## ## \n ## ## #### ## ## ## #### ####### ##### ##### ##### ");
|
||||
wwrap_print(stdscr, LINES / 2 - 3, COLS / 2 - 5, " ######### \n ################### \n ######## ##### \n ####### ### \n ###### ### \n ###### ### ## \n ############ # ### ## \n ################ ### # \n ############ ##### # \n ############## \n ######### \n ## \n ####### \n ###### # ## \n ## ## ###### ## ## # ##### \n ###### ##### ######## #### ## ## ## # ## \n ## ## ## ## ## ## ## ## ## ## ## ## # ## ## \n ## ## #### ## ## ## ##### ####### ##### ##### #####");
|
||||
mvprintw(LINES -1, COLS / 2 - 25, "Product Manager by Vincenzo Nikodem Cesqui Podiani");
|
||||
}
|
||||
+78
-23
@@ -11,6 +11,8 @@
|
||||
#define MAX_LEN 64
|
||||
#define LINE_LEN 96
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Helper
|
||||
*/
|
||||
@@ -29,6 +31,15 @@ static void replaceCommaWithDot(char *text) {
|
||||
*p = '.';
|
||||
}
|
||||
|
||||
static int askAction(const char *title, char **opts, int n_opts) {
|
||||
WINDOW *win = create_newwin(8, COLS / 3 + 8, LINES / 2 - 4, COLS / 2);
|
||||
mvwprintw(win, 1, 2, "%s", title);
|
||||
int choice = uiSelectMenu(win, 3, 2, opts, n_opts);
|
||||
werase(win);
|
||||
destroy_win(win);
|
||||
return choice;
|
||||
}
|
||||
|
||||
static int parseIntValue(const char *text, int *value) {
|
||||
char *end = NULL;
|
||||
long parsed = strtol(text, &end, 10);
|
||||
@@ -216,6 +227,51 @@ static int promptDataFilesForm(char *productsFile, size_t productsFileSize, char
|
||||
return choice;
|
||||
}
|
||||
|
||||
static int promptExportFileName(char *outFile, size_t outFileSize) {
|
||||
WINDOW *win = create_newwin(9, COLS / 2, 0, COLS / 2);
|
||||
char *opts[] = {"Esporta", "Annulla"};
|
||||
|
||||
mvwprintw(win, 1, 2, "Esporta vendite a CSV");
|
||||
mvwprintw(win, 3, 2, "File di destinazione:");
|
||||
if (outFile && outFile[0])
|
||||
uiTextInput(win, 4, 2, outFile, (int)outFileSize - 1);
|
||||
else {
|
||||
snprintf(outFile, outFileSize, "export.csv");
|
||||
uiTextInput(win, 4, 2, outFile, (int)outFileSize - 1);
|
||||
}
|
||||
|
||||
int choice = uiSelectMenu(win, 6, 4, opts, 2);
|
||||
werase(win);
|
||||
destroy_win(win);
|
||||
return choice;
|
||||
}
|
||||
|
||||
void runExportCsvWindow() {
|
||||
char outFile[MAX_LEN + 1];
|
||||
snprintf(outFile, sizeof outFile, "export.csv");
|
||||
|
||||
int choice = promptExportFileName(outFile, sizeof outFile);
|
||||
if (choice != 1) {
|
||||
statusf("Operazione annullata");
|
||||
return;
|
||||
}
|
||||
|
||||
char title[128];
|
||||
char *opts[] = {"Conferma", "Annulla"};
|
||||
snprintf(title, sizeof title, "Esportare le vendite in '%s' ?", outFile);
|
||||
int ok = askAction(title, opts, 2);
|
||||
if (ok != 1) {
|
||||
statusf("Operazione annullata");
|
||||
return;
|
||||
}
|
||||
|
||||
int res = exportSalesToCsv(productPricesFileLocation, countFileLocation, outFile);
|
||||
if (res == 0)
|
||||
statusf("Export CSV salvato in '%s'", outFile);
|
||||
else
|
||||
warningf("Errore nell'esportazione (codice %d)", res);
|
||||
}
|
||||
|
||||
static char **buildSalesLines(json_object *sales, int *n) {
|
||||
int count = (int)json_object_array_length(sales);
|
||||
char **lines = malloc((count > 0 ? count : 1) * sizeof *lines);
|
||||
@@ -316,15 +372,6 @@ static int listWindow(const char *title, char **lines, int n, const char *footer
|
||||
return result;
|
||||
}
|
||||
|
||||
static int askAction(const char *title, char **opts, int n_opts) {
|
||||
WINDOW *win = create_newwin(8, COLS / 3 + 8, LINES / 2 - 4, COLS / 2);
|
||||
mvwprintw(win, 1, 2, "%s", title);
|
||||
int choice = uiSelectMenu(win, 3, 2, opts, n_opts);
|
||||
werase(win);
|
||||
destroy_win(win);
|
||||
return choice;
|
||||
}
|
||||
|
||||
static int confirmDeletion(const char *subject) {
|
||||
char *opts[] = {"Elimina", "Annulla"};
|
||||
char title[128];
|
||||
@@ -593,13 +640,16 @@ static void showSaleEditWindow(const char *name, int sold) {
|
||||
return;
|
||||
}
|
||||
|
||||
int res = updateSold(countFileLocation, name, qty);
|
||||
int res = updateSold(productPricesFileLocation, countFileLocation, name, qty);
|
||||
if (res == 0)
|
||||
statusf("Vendita aggiornata: '%s' = %d", name, qty);
|
||||
else if (res == 1)
|
||||
warningf("La vendita '%s' non esiste piu'.", name);
|
||||
else if (res == 2)
|
||||
warningf("Stock insufficiente per portare '%s' a %d vendite.", name, qty);
|
||||
else
|
||||
warningf("Errore nella scrittura del file '%s'.", countFileLocation);
|
||||
warningf("Errore nell'aggiornamento di vendite/inventario ('%s', '%s').",
|
||||
countFileLocation, productPricesFileLocation);
|
||||
}
|
||||
|
||||
static void deleteSaleByName(const char *name) {
|
||||
@@ -608,13 +658,14 @@ static void deleteSaleByName(const char *name) {
|
||||
return;
|
||||
}
|
||||
|
||||
int res = deleteSold(countFileLocation, name);
|
||||
int res = deleteSold(productPricesFileLocation, countFileLocation, name);
|
||||
if (res == 0)
|
||||
statusf("Vendita eliminata: '%s'", name);
|
||||
statusf("Vendita eliminata: '%s' (inventario ripristinato)", name);
|
||||
else if (res == 1)
|
||||
warningf("La vendita '%s' non esiste piu'.", name);
|
||||
else
|
||||
warningf("Errore nella scrittura del file '%s'.", countFileLocation);
|
||||
warningf("Errore nell'aggiornamento di vendite/inventario ('%s', '%s').",
|
||||
countFileLocation, productPricesFileLocation);
|
||||
}
|
||||
|
||||
static void showSaleActionWindow(const char *name, int sold) {
|
||||
@@ -713,7 +764,7 @@ static void showCreateBundleWindow(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
json_object *products = getProducts(productPricesFileLocation);
|
||||
json_object *products = getProductsWithStock(productPricesFileLocation, countFileLocation);
|
||||
if (!products) {
|
||||
warningf("Impossibile leggere il file '%s'.", productPricesFileLocation);
|
||||
return;
|
||||
@@ -826,6 +877,9 @@ static void runMainMenuChoice(int choice) {
|
||||
runOptionsMenu();
|
||||
break;
|
||||
case 7:
|
||||
runExportCsvWindow();
|
||||
break;
|
||||
case 8:
|
||||
runAboutWindow();
|
||||
break;
|
||||
}
|
||||
@@ -836,9 +890,10 @@ int runMainMenu() {
|
||||
"Segna vendita",
|
||||
"Vedi vendite",
|
||||
"Vedi prodotti",
|
||||
"Aggiungi prodotti",
|
||||
"Crea nuovo bundle",
|
||||
"Aggiungi nuovo prodotto",
|
||||
"Aggiungi nuovo bundle",
|
||||
"Opzioni",
|
||||
"Esporta CSV",
|
||||
"About",
|
||||
"Exit"
|
||||
};
|
||||
@@ -861,18 +916,18 @@ int runMainMenu() {
|
||||
clrtoeol();
|
||||
refresh();
|
||||
|
||||
if (choice >= 1 && choice <= 7)
|
||||
if (choice >= 1 && choice <= 8)
|
||||
runMainMenuChoice(choice);
|
||||
|
||||
destroy_win(mainWin);
|
||||
return choice != 8;
|
||||
return choice != 9;
|
||||
}
|
||||
|
||||
void runAboutWindow() {
|
||||
WINDOW *aboutWin;
|
||||
aboutWin = create_newwin(LINES / 2 - 2, COLS / 2, LINES / 2, 0);
|
||||
|
||||
wwrap_print(aboutWin, 1, 1, "Questo e' un software fatto per Roma2LUG, il codice verra' pubblicato sul gitea del lug in futuro. La parte logica e' fatta con Claude Code, non avevo voglia di scrivere quei pezzi e volevo effettivamente rendere utile il codice che avevo scritto per gestire ncurses. Oh well, spero vi possa essere comunque utile. Buon lavoro / Divertimento!");
|
||||
wwrap_print(aboutWin, 1, 1, "Questo e' un software fatto per Roma2LUG, il codice verra' pubblicato sul gitea del lug in futuro.\nLa parte logica e' fatta con Claude Code, non avevo voglia di scrivere quei pezzi e volevo effettivamente rendere utile il codice che avevo scritto per gestire ncurses.\nOh well, spero vi possa essere comunque utile.\nBuon lavoro / Divertimento!");
|
||||
statusf("Uovo di pasqua ()");
|
||||
wrefresh(aboutWin);
|
||||
getch();
|
||||
@@ -921,7 +976,7 @@ void runOptionsMenu() {
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
void runSellWindow() {
|
||||
json_object *products = getProducts(productPricesFileLocation);
|
||||
json_object *products = getProductsWithStock(productPricesFileLocation, countFileLocation);
|
||||
if (!products) {
|
||||
warningf("Impossibile leggere il file '%s'.", productPricesFileLocation);
|
||||
return;
|
||||
@@ -976,7 +1031,7 @@ void runSellWindow() {
|
||||
if (res == 0) {
|
||||
int stock = 0;
|
||||
int tracked = 0;
|
||||
if (getProductInventory(productPricesFileLocation, name, &stock, &tracked) == 0 && tracked)
|
||||
if (getProductInventory(productPricesFileLocation, countFileLocation, name, &stock, &tracked) == 0 && tracked)
|
||||
statusf("Registrata vendita: %d x '%s' = %.2f (rimasti: %d)", qty, name, qty * price, stock);
|
||||
else
|
||||
statusf("Registrata vendita: %d x '%s' = %.2f", qty, name, qty * price);
|
||||
@@ -1048,7 +1103,7 @@ void runViewSalesWindow() {
|
||||
|
||||
void runViewProductsWindow() {
|
||||
while (1) {
|
||||
json_object *products = getProducts(productPricesFileLocation);
|
||||
json_object *products = getProductsWithStock(productPricesFileLocation, countFileLocation);
|
||||
if (!products) {
|
||||
warningf("Impossibile leggere il file '%s'.", productPricesFileLocation);
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user