680 lines
19 KiB
C
680 lines
19 KiB
C
//include std lib if they havent been included
|
|
#ifndef STD_LIB_H
|
|
#define STD_LIB_H
|
|
#include<stdio.h>
|
|
#include<stdlib.h>
|
|
#include<string.h>
|
|
#include<stdbool.h>
|
|
#include<math.h>
|
|
#include<time.h>
|
|
#include<ctype.h>
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef SORT_H
|
|
#define SORT_H
|
|
#include "sorting.h"
|
|
#endif // !SORT_H
|
|
#define PAGE_SIZE 20
|
|
#ifndef Utils
|
|
#define Utils
|
|
#include "utils.h"
|
|
#endif // !Utils
|
|
//fucntions for menu
|
|
void list_items();
|
|
void search_item();
|
|
void self_help_sale_system();
|
|
void print_page(struct inventory db, int cur, int end,struct Map* map);
|
|
|
|
//main of normal user
|
|
void normal_menu(){
|
|
int choice = 0;
|
|
do{
|
|
char * items[] = {
|
|
"List items",
|
|
"Search item",
|
|
"Self help sale system"
|
|
};
|
|
choice = choices_selecter(items,3,"><Welcome to the Student Union POS system><\nNormal User Menu");
|
|
switch (choice)
|
|
{
|
|
case 1://List items
|
|
list_items();
|
|
break;
|
|
case 2://Search item
|
|
search_item();
|
|
break;
|
|
case 3://self help sale system
|
|
self_help_sale_system();
|
|
break;
|
|
default://invalid input ,should not happen,as it is already catch in above function
|
|
break;
|
|
}
|
|
}while(choice != 4);
|
|
}
|
|
|
|
//universal functions for normal user
|
|
struct Map* sortItems(struct inventory db, int sort);
|
|
struct inventory show_item(struct inventory db,int index){
|
|
system("cls");
|
|
printf("Product: %s\n", db.row[index].product);
|
|
printf("Catergory: %s\n", db.row[index].category);
|
|
printf("Brand: %s\n", db.row[index].brand);
|
|
printf("Price: $%lf\n", db.row[index].price);
|
|
printf("Stock: %d\n", db.row[index].stock);
|
|
printf("Barcode: %ld\n",db.row[index].barcode);
|
|
printf("Press any key to return to the list\n");
|
|
fflush(stdin);
|
|
getchar();
|
|
return db;
|
|
}
|
|
|
|
//user for showing list result and search result
|
|
void list_page(struct inventory db,struct Map* map,int row,struct inventory (*showitem)(struct inventory,int)){//showitem is a function pointer for showing item,allow customization for better flexibilty
|
|
int choice = -1;
|
|
int page = 0;
|
|
int page_size = PAGE_SIZE;
|
|
int total_pages = ceil((double)row / page_size);
|
|
do{
|
|
|
|
//options
|
|
system("cls");
|
|
printf("0 exit\n");
|
|
printf("1 sort name decending\n");
|
|
printf("2 sort name ascending\n");
|
|
printf("3 sort price decending\n");
|
|
printf("4 sort price ascending\n");
|
|
printf("5 sort brand decending\n");
|
|
printf("6 sort brand ascending\n");
|
|
printf("7 sort category decending\n");
|
|
printf("8 sort category ascending\n");
|
|
printf("List of items:\n");
|
|
|
|
//print items
|
|
if(page + 1 >= total_pages){
|
|
print_page(db, page * page_size, row,map);
|
|
}else{
|
|
print_page(db, page * page_size, (page + 1) * page_size,map);
|
|
}
|
|
|
|
//page control
|
|
int current_page_size = 8 + page_size;
|
|
if(page + 1 >= total_pages){
|
|
current_page_size = row - page * page_size+8;
|
|
}
|
|
printf("%d next page\n", current_page_size+1);
|
|
printf("%d previous page\n", current_page_size+2);
|
|
printf("%d set page size\n", current_page_size+3);
|
|
printf("%d/%d/%d(page size/page number/total)\n",page_size, page+1,total_pages);
|
|
|
|
//prompt user to select an item
|
|
bool valid = true;
|
|
do{
|
|
valid = true;
|
|
printf("Enter your choice: ");
|
|
fflush(stdin);
|
|
scanf("%d", &choice);
|
|
if(choice <=8 && choice > 0){
|
|
printf("sorting...\n");
|
|
map = sortItems(db,choice);
|
|
}else if(choice == current_page_size+1 ){
|
|
if(page + 1 < total_pages){
|
|
page++;
|
|
}else{
|
|
printf("Already at last page\n");
|
|
valid = false;
|
|
}
|
|
}else if(choice == current_page_size+2){
|
|
if(page > 0){
|
|
page--;
|
|
}else{
|
|
printf("Already at first page\n");
|
|
valid = false;
|
|
}
|
|
}else if(choice == current_page_size+3){
|
|
printf("Enter page size: ");
|
|
fflush(stdin);
|
|
scanf("%d", &page_size);
|
|
total_pages = ceil(row / page_size);
|
|
}else if(choice >= 9 && choice <= current_page_size){
|
|
if(map == NULL){
|
|
db = (*showitem)(db,choice - 9 + page_size*page);
|
|
}else{
|
|
db = (*showitem)(db,map[choice - 9 + page_size*page].key);
|
|
}
|
|
}else if(choice != 0){
|
|
printf("Invalid choice\n");
|
|
valid = false;
|
|
}
|
|
}while(!valid);
|
|
|
|
}while(choice != 0);
|
|
}
|
|
//print the list for the page
|
|
void print_page(struct inventory db, int cur, int end,struct Map* map){
|
|
for (int i = cur; i < end; i++)
|
|
{
|
|
if(map != NULL){
|
|
printf("%d item %d: %s\n", i + 9,i, db.row[map[i].key].product);
|
|
}
|
|
else{
|
|
printf("%d item %d: %s\n", i + 9,i, db.row[i].product);
|
|
}
|
|
}
|
|
}
|
|
//list items
|
|
|
|
|
|
void list_items(){
|
|
system("cls");
|
|
welcome_message();
|
|
//get the list of items from the database
|
|
//print the list of items
|
|
//prompt user to select an item
|
|
//if user selects an item, display the item's details
|
|
|
|
struct inventory db = read_db_invt();
|
|
struct Map* map = NULL;
|
|
// char * SortItems[] = {
|
|
// "Name",
|
|
// "Price",
|
|
// "Brand",
|
|
// "Category",
|
|
// };
|
|
// FIXME:function for normal list page
|
|
// lister(&db,map,db.db.row_count,"List of items",SortItems,4,print_page,sortItems,item_control);
|
|
list_page(db,map,db.db.row_count,show_item);
|
|
}
|
|
|
|
//for sorting
|
|
struct Map* sortItems(struct inventory db, int sort){
|
|
// struct Map* sortItems(void * ddb, int sort){
|
|
// struct inventory db = *((struct inventory*)ddb);
|
|
struct Map *map = malloc(sizeof(struct Map) * db.db.row_count-1);
|
|
for (int i = 0; i < db.db.row_count-1; i++){
|
|
map[i].key = i;
|
|
|
|
switch(sort){
|
|
case 1:
|
|
case 2:
|
|
map[i].value = (void*)db.row[i].product;
|
|
break;
|
|
|
|
case 3:
|
|
case 4:;
|
|
double price = db.row[i].price * 100;
|
|
double * price_star = malloc(sizeof(long));
|
|
*price_star = price;
|
|
map[i].value = (void*)price_star;//presume there is no price contain 0.001
|
|
break;
|
|
case 5:
|
|
case 6:
|
|
map[i].value = (void*)db.row[i].brand;
|
|
break;
|
|
case 7:
|
|
case 8:
|
|
map[i].value = (void*)db.row[i].category;
|
|
break;
|
|
}
|
|
}
|
|
switch (sort){
|
|
case 1:
|
|
case 5:
|
|
case 7:
|
|
qsort(map, db.db.row_count-1, sizeof(struct Map), compare_decending_str);
|
|
break;
|
|
case 2:
|
|
case 6:
|
|
case 8:
|
|
qsort(map, db.db.row_count-1, sizeof(struct Map), compare_ascending_str);
|
|
break;
|
|
case 3:
|
|
qsort(map, db.db.row_count-1, sizeof(struct Map), compare_decending);
|
|
break;
|
|
case 4:
|
|
qsort(map, db.db.row_count-1, sizeof(struct Map), compare_ascending);
|
|
break;
|
|
}
|
|
map = realloc(map, sizeof(struct Map) * db.db.row_count);
|
|
map[db.db.row_count-1].key = db.db.row_count-1;
|
|
return map;
|
|
}
|
|
|
|
|
|
|
|
//search items
|
|
char* prompt_search();
|
|
struct Map* searchItems(struct inventory db, char* searchstr);
|
|
void search_item(){
|
|
|
|
//search for item
|
|
//prompt user to select an item
|
|
//if user selects an item, display the item's details
|
|
struct inventory db = read_db_invt();
|
|
struct Map* map = NULL;
|
|
do{
|
|
|
|
//options
|
|
int breakout = 0;
|
|
char * items[] = {
|
|
"search"
|
|
};
|
|
breakout = choices_selecter(items,1,"><Welcome to the Student Union POS system><");
|
|
if(breakout == 2){
|
|
break;
|
|
}
|
|
char* searchstr = prompt_search();
|
|
printf("searching...\n");
|
|
map = searchItems(db,searchstr);
|
|
if(map[0].value > 0){
|
|
int temp_row = *((int*)map[0].value);
|
|
// char * SortItems[] = {
|
|
// "Name",
|
|
// "Price",
|
|
// "Brand",
|
|
// "Category",
|
|
// };
|
|
//FIXME
|
|
// lister(&db,map+1,temp_row,"List of items",SortItems,4,print_page,sortItems,item_control);//ofset map, as it is use to store the size
|
|
list_page(db,map+1,temp_row,show_item);//ofset map, as it is use to store the size
|
|
}else{//empty search
|
|
printf("No result found\n");
|
|
printf("Press any key to continue\n");
|
|
fflush(stdin);
|
|
getchar();
|
|
|
|
}
|
|
}while(true);//break on top
|
|
|
|
}
|
|
|
|
|
|
char* prompt_search(){
|
|
printf("Enter search string:(largest length 100)(case insesitive)\n");
|
|
char* searchstr = malloc(sizeof(char) * 100);
|
|
fflush(stdin);
|
|
scanf("%s", searchstr);
|
|
return searchstr;
|
|
}
|
|
|
|
|
|
|
|
struct Map* searchItems(struct inventory db, char* searchstr){
|
|
struct Map* map = malloc(sizeof(struct Map) * (db.db.row_count+1));
|
|
int k = 1;
|
|
for (int i = 0; i < db.db.row_count; i++){
|
|
map[k].key = i;
|
|
if(strcasestr(db.row[i].product,searchstr) != NULL){
|
|
|
|
map[k].value = (void*)db.row[i].product;
|
|
k++;
|
|
}
|
|
}
|
|
int* k_star = malloc(sizeof(int));
|
|
*k_star = --k;//decrement and assign to k star;don't use k-- as it will decrement after the assignment
|
|
map[0].value = (void*)k_star;
|
|
map[0].key = -1;
|
|
return map;
|
|
}
|
|
|
|
//self help
|
|
|
|
struct cart* scan_barcode(struct cart* cart,struct inventory db);
|
|
struct cart* list_cart(struct cart* cart);
|
|
void self_help_sale_system(){
|
|
|
|
//scan barcode
|
|
struct inventory db = read_db_invt();
|
|
struct cart* cart = NULL;
|
|
int choice = 0;
|
|
do{
|
|
|
|
//options
|
|
int breakout = 0;
|
|
char * items[] = {
|
|
"scan barcode",
|
|
"cart/checkout"
|
|
};
|
|
choice = choices_selecter(items,2,"><Welcome to the Student Union POS system><");
|
|
switch (choice)
|
|
{
|
|
case 1:
|
|
cart = scan_barcode(cart,db);
|
|
break;
|
|
case 2:
|
|
cart = list_cart(cart);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}while(choice!=3);
|
|
}
|
|
|
|
//support for the linked list
|
|
struct cart* Cartappend(struct cart* cart,struct inventory_row* row,int quantity){
|
|
if(cart == NULL){
|
|
cart = malloc(sizeof(struct cart));
|
|
cart->row = row;
|
|
cart->quantity = quantity;
|
|
cart->next = NULL;
|
|
}else{
|
|
struct cart* temp = cart;
|
|
while(temp->next != NULL){
|
|
temp = temp->next;
|
|
}
|
|
temp->next = malloc(sizeof(struct cart));
|
|
temp->next->row = row;
|
|
temp->next->quantity = quantity;
|
|
temp->next->next = NULL;
|
|
}
|
|
|
|
return cart;
|
|
}
|
|
|
|
struct cart* Cartremove(struct cart* cart,int index){
|
|
if (cart == NULL){
|
|
return cart;
|
|
}else{
|
|
struct cart* temp = cart;
|
|
if (index == 0){
|
|
cart = cart->next;
|
|
free(temp);
|
|
return cart;
|
|
}else{
|
|
for (int i = 0; i < index-1; i++){
|
|
temp = temp->next;
|
|
}
|
|
struct cart* new = temp->next->next;
|
|
free(temp->next);
|
|
temp->next = new;
|
|
return cart;
|
|
}
|
|
}
|
|
}
|
|
struct cart* Cartupdate(struct cart* cart,int index,int quantity){
|
|
if (cart == NULL){
|
|
return cart;
|
|
}else{
|
|
struct cart* temp = cart;
|
|
if (index == 0){
|
|
cart->quantity = quantity;
|
|
return cart;
|
|
}else{
|
|
for (int i = 0; i < index-1; i++){
|
|
temp = temp->next;
|
|
}
|
|
temp->next->quantity = quantity;
|
|
return cart;
|
|
}
|
|
}
|
|
}
|
|
|
|
struct inventory_row* Cartget(struct cart* cart,int index){
|
|
if (cart == NULL){
|
|
return NULL;
|
|
}else{
|
|
struct cart* temp = cart;
|
|
if (index == 0){
|
|
return cart->row;
|
|
}else{
|
|
for (int i = 0; i < index-1; i++){
|
|
temp = temp->next;
|
|
}
|
|
return temp->next->row;
|
|
}
|
|
}
|
|
}
|
|
|
|
int Cartqty(struct cart* cart,int index){
|
|
if (cart == NULL){
|
|
return 0;
|
|
}else{
|
|
struct cart* temp = cart;
|
|
if (index == 0){
|
|
return cart->quantity;
|
|
}else{
|
|
for (int i = 0; i < index-1; i++){
|
|
temp = temp->next;
|
|
}
|
|
return temp->next->quantity;
|
|
}
|
|
}
|
|
}
|
|
|
|
//scan barcode
|
|
struct inventory_row* find_barcode(struct inventory db,long barcode);
|
|
long prompt_barcode();
|
|
struct cart* scan_barcode(struct cart* cart,struct inventory db){
|
|
|
|
long barcode = prompt_barcode();
|
|
printf("matching...\n");
|
|
struct inventory_row* row = find_barcode(db,barcode);
|
|
if(row != NULL){
|
|
int quantity = 0;
|
|
char choice = 'n';
|
|
do{
|
|
system("cls");
|
|
printf("product: %s\n",row->product);
|
|
printf("price: %.1f\n",row->price);
|
|
printf("Enter quantity(0 to cancel)\n>");\
|
|
fflush(stdin);
|
|
scanf("%d", &quantity);
|
|
fflush(stdin);
|
|
if(quantity == 0){
|
|
printf("cancelled\n");
|
|
printf("press any key to continue\n");
|
|
fflush(stdin);
|
|
getchar();
|
|
return cart;
|
|
}
|
|
printf("Are you sure you want to add this item to cart?(y/n)\n>");
|
|
fflush(stdin);
|
|
scanf("%c", &choice);
|
|
if(row->stock - quantity < 0 && choice == 'y'){
|
|
printf("WARNING:not enough stock\n");
|
|
printf("Are you sure the quantity is correct?\n(y to ignore and continue/n)\n>");
|
|
fflush(stdin);
|
|
scanf("%c", &choice);
|
|
}
|
|
}while(choice != 'y');
|
|
if(quantity != 0){
|
|
cart = Cartappend(cart,row,quantity);
|
|
printf("added to cart\n");
|
|
}
|
|
}else{//empty search
|
|
printf("Unable to match or invalid input\n");
|
|
|
|
}
|
|
printf("press any key to continue\n");
|
|
fflush(stdin);
|
|
getchar();
|
|
return cart;
|
|
}
|
|
|
|
|
|
long prompt_barcode(){
|
|
printf("Please scan the qr code(or input the barcode ) ");
|
|
long barcode;
|
|
fflush(stdin);
|
|
scanf("%ld", &barcode);
|
|
return barcode;
|
|
}
|
|
|
|
struct inventory_row* find_barcode(struct inventory db,long barcode){
|
|
struct inventory_row row;
|
|
for (int i = 0; i < db.db.row_count; i++){
|
|
if(db.row[i].barcode == barcode){
|
|
|
|
return &db.row[i];
|
|
}
|
|
}
|
|
return (struct inventory_row*)NULL;
|
|
}
|
|
|
|
|
|
//list cart
|
|
struct cart* cart_control(struct cart* cart,int index);
|
|
struct cart* checkout(struct cart* cart);
|
|
struct cart* list_cart(struct cart* cart){
|
|
int choice = 0;
|
|
do{
|
|
system("cls");
|
|
welcome_message();
|
|
double total_price = 0;
|
|
int i=1;
|
|
printf("0 exit\n");
|
|
if(cart == NULL){
|
|
printf("Cart is empty\n");
|
|
}else{
|
|
struct cart* temp = cart;
|
|
while(temp != NULL){//show cart
|
|
int qty = temp->quantity;
|
|
double price = temp->row->price * qty;
|
|
total_price += price;
|
|
printf("%d product:%s\n",i,temp->row->product);
|
|
printf(" price(per qty): %.1f\n",temp->row->price);//space to align
|
|
printf(" price(total): %.1f\n",price);
|
|
printf(" quantity: %d\n",qty);
|
|
printf("<------------------------>\n");
|
|
temp = temp->next;
|
|
i++;
|
|
}
|
|
printf("\n<------------------------>\n");
|
|
printf("Total price: $%.1f\n",total_price);
|
|
printf("<------------------------>\n");
|
|
|
|
printf("\n%d CHECKOUT\n",i);
|
|
}
|
|
do{
|
|
printf("input the corresponding value for more action\n>");
|
|
fflush(stdin);
|
|
scanf("%d", &choice);
|
|
if(choice >0 && choice < i){
|
|
cart = cart_control(cart,choice);
|
|
}else if(choice == i && cart != NULL){
|
|
cart = checkout(cart);
|
|
|
|
}
|
|
}while(choice <0 || choice > i);
|
|
}while(choice != 0);
|
|
return cart;
|
|
}
|
|
struct cart* update_cart(struct cart* cart,int index);
|
|
struct cart* cart_control(struct cart* cart,int index){
|
|
int choice = 0;
|
|
struct inventory_row* row = Cartget(cart,index-1);
|
|
int quantity = Cartqty(cart,index-1);
|
|
do{
|
|
char welcome[256];
|
|
sprintf(welcome,"><Welcome to the Student Union POS system><\n");
|
|
sprintf(welcome,"product: %s\n",row->product);
|
|
sprintf(welcome,"price: %.1f\n",row->price);
|
|
sprintf(welcome,"quantity: %d\n",quantity);
|
|
char * items[] = {
|
|
"remove",
|
|
"edit quantity"
|
|
};
|
|
choice = choices_selecter(items,2,welcome);
|
|
|
|
if(choice == 1){
|
|
cart = Cartremove(cart,index-1);
|
|
printf("Remove successful\n");
|
|
printf("press any key to continue\n");
|
|
fflush(stdin);
|
|
getchar();
|
|
}else if(choice == 2){
|
|
cart = update_cart(cart,index);
|
|
printf("Update successful\n");
|
|
printf("press any key to continue");
|
|
fflush(stdin);
|
|
getchar();
|
|
}
|
|
}while(choice != 1 || choice != 2 || choice !=3 );
|
|
return cart;
|
|
}
|
|
|
|
struct cart* update_cart(struct cart* cart,int index){
|
|
system("cls");
|
|
welcome_message();
|
|
char choice;
|
|
do{
|
|
int quantity = 0;
|
|
printf("enter the new quantity: ");
|
|
fflush(stdin);
|
|
scanf("%d", &quantity);
|
|
printf("Are you sure you want to update this item?(y/n/e to exit)");
|
|
fflush(stdin);
|
|
scanf("%c", &choice);
|
|
if(choice == 'y'){
|
|
|
|
if(quantity != 0){
|
|
cart = Cartupdate(cart,index-1,quantity);
|
|
}else if (quantity == 0){
|
|
cart = Cartremove(cart,index-1);
|
|
}
|
|
}
|
|
}while(choice != 'y' && choice != 'e');
|
|
return cart;
|
|
}
|
|
|
|
|
|
|
|
//Checkout
|
|
|
|
struct cart* checkout(struct cart* cart){
|
|
system("cls");
|
|
welcome_message();
|
|
|
|
long user_id = 0;
|
|
printf("Please tap your card(student card, staff card,etc)(or input the id)(0 to cancel)\n>");
|
|
scanf("%ld", &user_id);
|
|
if(user_id == 0){
|
|
printf("cancelled\n");
|
|
printf("press any key to continue\n");
|
|
fflush(stdin);
|
|
getchar();
|
|
return cart;
|
|
}
|
|
struct user_row* user = get_user(user_id);
|
|
|
|
|
|
if(user == NULL){
|
|
printf("Fail to indentify your card or error occurs\n");
|
|
printf("press any key to continue\n");
|
|
fflush(stdin);
|
|
getchar();
|
|
return cart;
|
|
}else{
|
|
printf("Welcome %s(%s)\n",user->name,user->role);
|
|
printf("Are you sure you want to checkout?(y/n)\n>");
|
|
char choice;
|
|
fflush(stdin);
|
|
scanf("%c", &choice);
|
|
if(choice == 'y'){
|
|
if(update_stock_N_checkout(cart,user)){//catch err
|
|
printf("Checkout successful\n");
|
|
printf("press any key to continue\n");
|
|
fflush(stdin);
|
|
getchar();
|
|
return NULL;
|
|
}else{
|
|
printf("Checkout failed(files maybe corrputed)\n");
|
|
printf("press any key to continue\n");
|
|
fflush(stdin);
|
|
getchar();
|
|
return cart;
|
|
}
|
|
}else{
|
|
printf("cancelled\n");
|
|
printf("press any key to continue\n");
|
|
fflush(stdin);
|
|
getchar();
|
|
return cart;
|
|
}
|
|
}
|
|
|
|
|
|
return cart;
|
|
}
|