package controllers import ( "context" "log" "net/http" "ordr-api/dto" "ordr-api/queries" "strconv" "time" "github.com/gin-gonic/gin" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) func CreateItem(pool *pgxpool.Pool) gin.HandlerFunc { return func(ctx *gin.Context) { conn, conn_err := pool.Acquire(ctx) if conn_err != nil { log.Printf("CreateItem(): ERROR: Failed to connect... %s", conn_err.Error()) ctx.AbortWithStatus(http.StatusInternalServerError) return } defer conn.Release() item_name := ctx.Query("item_name") in_season := ctx.Query("in_season") == "1" if item_name == "" { ctx.JSON(http.StatusBadRequest, "CreateItem(): ERROR... Item Name not supplied") } _, exec_err := conn.Exec(context.Background(), queries.CREATE_ITEM, item_name, in_season) if exec_err != nil { ctx.JSON(http.StatusInternalServerError, "CreateItem(): ERROR... Failed to create item") log.Printf("CreateItem(): ERROR... Failed to create item... %s", exec_err.Error()) return } var item_id int query_err := conn.QueryRow(context.Background(), "SELECT id FROM item WHERE item_name = $1", item_name).Scan(&item_id) if query_err != nil { ctx.JSON(http.StatusInternalServerError, "CreateItem(): ERROR... Failed to get nwely created item id") log.Printf("CreateItem(): ERROR... Failed to get newly created item... %s", query_err.Error()) return } item_price := ctx.Query("item_price") if item_price == "" { ctx.JSON(http.StatusBadRequest, "CreateItem(): ERROR... item_price not supplied") return } item_price_float, convert_err := strconv.ParseFloat(item_price, 64) if convert_err != nil { ctx.JSON(http.StatusBadRequest, "CreateUser(): ERROR... Failed to create item price: item price invalid format") return } _, exec_price_err := conn.Exec(context.Background(), queries.CREATE_ITEM_PRICE, item_id, item_price) if exec_price_err != nil { ctx.JSON(http.StatusInternalServerError, "CreateItem(): ERROR... Failed to insert price...") log.Printf("CreateItem(): ERROR... Failed to insert price... %s", exec_price_err.Error()) return } var item_price_object dto.ItemPriceResponse item_price_object.ItemId = item_id item_price_object.ItemName = item_name item_price_object.ItemPrice = item_price_float ctx.JSON(http.StatusOK, item_price_object) } } func SetItemPrice(pool *pgxpool.Pool) gin.HandlerFunc { return func(ctx *gin.Context) { conn, conn_err := pool.Acquire(ctx) if conn_err != nil { log.Printf("GetUserTable(): ERROR: Failed to connect... %s", conn_err.Error()) ctx.AbortWithStatus(http.StatusInternalServerError) return } defer conn.Release() item_id_string := ctx.Query("item_id") if item_id_string == "" { ctx.JSON(http.StatusBadRequest, "SetItemPrice(): ERROR... item id not provided") return } _, exec_date_err := conn.Exec(context.Background(), queries.SET_ITEM_PRICE_VALID_TO_DATE, item_id_string) if exec_date_err != nil { ctx.JSON(http.StatusInternalServerError, "SetItemPrice(): ERROR... Failed to set valid_to date") log.Printf("SetItemPrice(): ERROR... Failed to set valid_to date... %s", exec_date_err.Error()) return } item_price_string := ctx.Query("item_price") if item_price_string == "" { ctx.JSON(http.StatusBadRequest, "SetItemPrice(): ERROR... Item Price Not Provided") return } item_price_float, item_price_conv_err := strconv.ParseFloat(item_price_string, 64) if item_price_conv_err != nil { ctx.JSON(http.StatusBadRequest, "SetItemPrice(): ERROR... item price not valid") return } _, exec_new_price_err := conn.Exec(context.Background(), queries.CREATE_ITEM_PRICE, item_id_string, item_price_float) if exec_new_price_err != nil { ctx.JSON(http.StatusInternalServerError, "SetItemPrice(): ERROR... failed to create item price") log.Printf("SetItemPrice(): ERROR... failed to create item price... %s", exec_new_price_err.Error()) return } var item_price_object dto.ItemPriceResponse query_item_price_err := conn.QueryRow(context.Background(), queries.GET_CURRENT_ITEM_PRICE, item_id_string).Scan(&item_price_object.ItemId, &item_price_object.ItemName, &item_price_object.ItemPrice, &item_price_object.InSeason) if query_item_price_err != nil { ctx.JSON(http.StatusInternalServerError, "SetItemPrice(): ERROR... Failed to query item price") log.Printf("SetItemPrice(): ERROR... Failed to query item price... %s", query_item_price_err.Error()) return } ctx.JSON(http.StatusOK, item_price_object) } } func GetCurrentItemPrice(pool *pgxpool.Pool) gin.HandlerFunc { return func(ctx *gin.Context) { conn, conn_err := pool.Acquire(ctx) if conn_err != nil { log.Printf("GetCurrentItemPrice(): ERROR: Failed to connect... %s", conn_err.Error()) ctx.AbortWithStatus(http.StatusInternalServerError) return } defer conn.Release() item_id := ctx.Query("item_id") if item_id == "" { ctx.JSON(http.StatusBadRequest, "GetCurrentItemPrice(): ERROR... item id not provided") return } var item_price dto.ItemPriceResponse query_err := conn.QueryRow(context.Background(), queries.GET_CURRENT_ITEM_PRICE, item_id).Scan(&item_price.ItemId, &item_price.ItemName, &item_price.ItemPrice, &item_price.InSeason) if query_err != nil { if query_err == pgx.ErrNoRows { ctx.JSON(http.StatusBadRequest, "GetCurrentItemPrice(): ERROR... no rows match id") return } ctx.JSON(http.StatusInternalServerError, "GetCurrentItemPrice(): ERROR... failed to query db") log.Printf("GetCurrentItemPrice(): ERROR... failed to query db... %s", query_err.Error()) return } ctx.JSON(http.StatusOK, item_price) } } func AddItemToOrder(pool *pgxpool.Pool) gin.HandlerFunc { return func(ctx *gin.Context) { conn, conn_err := pool.Acquire(ctx) if conn_err != nil { log.Printf("AddItemToOrder(): ERROR: Failed to connect... %s", conn_err.Error()) ctx.AbortWithStatus(http.StatusInternalServerError) return } defer conn.Release() item_id := ctx.Query("item_id") order_id := ctx.Query("order_id") quantity := ctx.Query("quantity") created_at := ctx.Query("created_at") if item_id == "" || order_id == "" || quantity == "" { ctx.JSON(http.StatusBadRequest, "AddItemToOrder(): ERROR... item_id, order_id, or quantity missing") return } if created_at == "" { current_timestamp := time.Now() created_at = current_timestamp.Format(time.RFC3339) } int_item_id, item_id_parse_err := strconv.ParseInt(item_id, 10, 64) if item_id_parse_err != nil { ctx.JSON(http.StatusBadRequest, "AddItemToOrder: ERROR... item id is not an int") return } int_order_id, order_id_parse_err := strconv.ParseInt(order_id, 10, 64) if order_id_parse_err != nil { ctx.JSON(http.StatusBadRequest, "AddItemToOrder: ERROR... order id is not an int") return } int_quantity, quantity_parse_err := strconv.ParseInt(quantity, 10, 64) if quantity_parse_err != nil { ctx.JSON(http.StatusBadRequest, "AddItemToOrder: ERROR... quantity is not an int") return } _, time_parse_err := time.Parse(time.RFC3339, created_at) if time_parse_err != nil { ctx.JSON(http.StatusBadRequest, "AddItemToOrder(): ERROR... time is bad") return } _, exec_err := conn.Exec(context.Background(), queries.ADD_ITEM_TO_ORDER, int_item_id, int_order_id, int_quantity, created_at) if exec_err != nil { ctx.JSON(http.StatusInternalServerError, "AddItemToOrder(): ERROR... failed to insert rows") log.Printf("AddItemToOrder(): ERROR... Failed to insert rows... %s", exec_err.Error()) return } _, update_order_filled_exec_err := conn.Exec(context.Background(), queries.SET_ORDER_FILLED, false, order_id) if update_order_filled_exec_err != nil { ctx.JSON(http.StatusInternalServerError, "AddItemToOrder(): ERROR... failed to set order state") log.Printf("AddItemToOrder(): ERROR... failed to set order state... %s", update_order_filled_exec_err.Error()) return } var order_item_price dto.OrderItemPriceResponse price_data_row := conn.QueryRow(context.Background(), queries.GET_ORDER_ITEM_PRICE, item_id, order_id) price_scan_err := price_data_row.Scan(&order_item_price.ItemId, &order_item_price.OrderId, &order_item_price.ItemName, &order_item_price.Quantity, &order_item_price.Made, &order_item_price.CreatedAt, &order_item_price.TotalPrice, &order_item_price.UnitPrice) if price_scan_err != nil { ctx.JSON(http.StatusInternalServerError, "AddItemToOrder(): ERROR... Failed to scan price data") log.Printf("AddItemToOrder(): ERROR... Failed to scan price data... %s", price_scan_err.Error()) return } ctx.JSON(http.StatusOK, order_item_price) } } func GetOrderItems(pool *pgxpool.Pool) gin.HandlerFunc { return func(ctx *gin.Context) { conn, conn_err := pool.Acquire(ctx) if conn_err != nil { log.Printf("GetOrderItems(): ERROR: Failed to connect... %s", conn_err.Error()) ctx.AbortWithStatus(http.StatusInternalServerError) return } defer conn.Release() order_id := ctx.Query("order_id") if order_id == "" { ctx.JSON(http.StatusBadRequest, "GetOrderItems(): ERROR: order id not supplied") return } _, parse_err := strconv.ParseInt(order_id, 10, 64) if parse_err != nil { ctx.JSON(http.StatusBadRequest, "GetOrderItem(): ERROR... order id not an integer") return } rows, query_err := conn.Query(context.Background(), queries.GET_ORDER_ITEMS, order_id) if query_err != nil { ctx.JSON(http.StatusInternalServerError, "GetOrderItems(): ERROR... failed to query database.") log.Printf("GetOrderItems(): ERROR... Failed to query database... %s", query_err.Error()) return } defer rows.Close() var items []dto.OrderItemPriceResponse for rows.Next() { var item dto.OrderItemPriceResponse scan_err := rows.Scan(&item.ItemId, &item.OrderId, &item.ItemName, &item.Quantity, &item.Made, &item.CreatedAt, &item.TotalPrice, &item.UnitPrice) if scan_err != nil { ctx.JSON(http.StatusInternalServerError, "GetOrderItems(): ERROR... Failed to scan data...") log.Printf("GetOrderItems(): ERROR... failed to scan data... %s", scan_err.Error()) return } items = append(items, item) } ctx.JSON(http.StatusOK, items) } } func SetItemMade(pool *pgxpool.Pool) gin.HandlerFunc { return func(ctx *gin.Context) { conn, conn_err := pool.Acquire(ctx) if conn_err != nil { log.Printf("SetItemMade(): ERROR: Failed to connect... %s", conn_err.Error()) ctx.AbortWithStatus(http.StatusInternalServerError) return } defer conn.Release() var request dto.ItemOrderSetMadeRequest request_read_err := ctx.ShouldBindJSON(&request) if request_read_err != nil { ctx.JSON(http.StatusBadRequest, "SetItemMade(): ERROR... Error Request in bad format") return } _, exec_set_made_err := conn.Exec(context.Background(), queries.SET_MADE, request.Made, request.ItemId, request.OrderId) if exec_set_made_err != nil { ctx.JSON(http.StatusInternalServerError, "SetItemMade(): ERROR... Internal server error") log.Printf("SetItemMade(): ERROR... Failed to set item made... %s", exec_set_made_err.Error()) return } _, exec_update_order_err := conn.Exec(context.Background(), queries.UPDATE_ORDER_FILLED, request.OrderId) if exec_update_order_err != nil { ctx.JSON(http.StatusInternalServerError, "SetItemMade(): ERROR... Failed to update order") log.Printf("SetItemMade(): ERROR... Failed to update order... %s", exec_update_order_err.Error()) return } var order_filled dto.OrderFilledResponse scan_err := conn.QueryRow(context.Background(), queries.GET_ORDER_MADE_DETAILS, request.OrderId).Scan(&order_filled.OrderId, &order_filled.Filled) if scan_err != nil { if scan_err == pgx.ErrNoRows { ctx.JSON(http.StatusBadRequest, "SetItemMade(): Invalid data") return } ctx.JSON(http.StatusInternalServerError, "SetItemMade(): ERROR... Error querying result") log.Printf("SetItemMade(): ERROR... Error querying result... %s", scan_err.Error()) return } ctx.JSON(http.StatusOK, order_filled) } } func SetItemQuantity(pool *pgxpool.Pool) gin.HandlerFunc { return func(ctx *gin.Context) { conn, conn_err := pool.Acquire(ctx) if conn_err != nil { log.Printf("SetItemMade(): ERROR: Failed to connect... %s", conn_err.Error()) ctx.AbortWithStatus(http.StatusInternalServerError) return } defer conn.Release() var request dto.ItemOrderSetQuantityRequest request_read_err := ctx.ShouldBindJSON(&request) if request_read_err != nil { ctx.JSON(http.StatusBadRequest, "SetItemQuantity(): ERROR... Error Request in bad format") return } _, exec_set_quantity_err := conn.Exec(context.Background(), queries.SET_QUANTITY, request.Quantity, request.ItemId, request.OrderId) if exec_set_quantity_err != nil { ctx.JSON(http.StatusInternalServerError, "SetItemMade(): ERROR... Internal server error") log.Printf("SetItemQuantity(): ERROR... Failed to set item quantity... %s", exec_set_quantity_err.Error()) return } _, exec_update_order_err := conn.Exec(context.Background(), queries.UPDATE_ORDER_FILLED, request.OrderId) if exec_update_order_err != nil { ctx.JSON(http.StatusInternalServerError, "SetItemMade(): ERROR... Failed to update order") log.Printf("SetItemQuantity(): ERROR... Failed to update order... %s", exec_update_order_err.Error()) return } var order_filled dto.OrderFilledResponse scan_err := conn.QueryRow(context.Background(), queries.GET_ORDER_MADE_DETAILS, request.OrderId).Scan(&order_filled.OrderId, &order_filled.Filled) if scan_err != nil { if scan_err == pgx.ErrNoRows { ctx.JSON(http.StatusBadRequest, "SetItemQuantity(): Invalid data") return } ctx.JSON(http.StatusInternalServerError, "SetItemQuantity(): ERROR... Error querying result") log.Printf("SetItemQuantity(): ERROR... Error querying result... %s", scan_err.Error()) return } ctx.JSON(http.StatusOK, order_filled) } } func DeleteOrderItem(pool *pgxpool.Pool) gin.HandlerFunc { return func(ctx *gin.Context) { conn, conn_err := pool.Acquire(ctx) if conn_err != nil { log.Printf("DeleteOrderItem(): ERROR: Failed to connect... %s", conn_err.Error()) ctx.AbortWithStatus(http.StatusInternalServerError) return } defer conn.Release() item_id := ctx.Query("item_id") order_id := ctx.Query("order_id") if item_id == "" || order_id == "" { ctx.String(http.StatusBadRequest, "DeleteOrderItem(): Bad Request") return } item_id_int, item_parse_err := strconv.ParseInt(item_id, 10, 64) order_id_int, order_parse_err := strconv.ParseInt(order_id, 10, 64) if item_parse_err != nil || order_parse_err != nil { ctx.String(http.StatusBadRequest, "DeleteOrderItem(): Bad Request") return } _, exec_err := conn.Exec(context.Background(), queries.REMOVE_ITEM_FROM_ORDER, item_id_int, order_id_int) if exec_err != nil { ctx.JSON(http.StatusInternalServerError, "DeleteOrderItem(): ERROR.. Failed to delete item") log.Printf("DeleteOrderItem(): ERROR... Failed to delte item... %s", exec_err.Error()) return } } } func DeleteItem(pool *pgxpool.Pool) gin.HandlerFunc { return func(ctx *gin.Context) { conn, conn_err := pool.Acquire(ctx) if conn_err != nil { log.Printf("DeleteItem(): ERROR: Failed to connect... %s", conn_err.Error()) ctx.AbortWithStatus(http.StatusInternalServerError) return } defer conn.Release() item_id := ctx.Query("item_id") item_id_int, parse_err := strconv.ParseInt(item_id, 10, 64) if parse_err != nil || item_id == "" { ctx.JSON(http.StatusBadRequest, "DeleteItem(): Invalid data entry") return } _, exec_err := conn.Exec(context.Background(), "DELETE FROM item WHERE id = $1", item_id_int) if exec_err != nil { ctx.JSON(http.StatusInternalServerError, "DeleteItem(): Failed to delete item") log.Printf("DeleteItem(): ERROR... Failed to delete item... %s", exec_err.Error()) return } } } func GetItems(pool *pgxpool.Pool) gin.HandlerFunc { return func(ctx *gin.Context) { conn, conn_err := pool.Acquire(ctx) if conn_err != nil { log.Printf("DeleteItem(): ERROR: Failed to connect... %s", conn_err.Error()) ctx.AbortWithStatus(http.StatusInternalServerError) return } defer conn.Release() rows, query_err := conn.Query(context.Background(), queries.GET_CURRENT_ITEMS_PRICE) if query_err != nil { ctx.JSON(http.StatusInternalServerError, "INTERNAL SERVER ERROR") log.Printf("GetItems(): ERROR... Failed to query table... %s", query_err.Error()) return } var items []dto.ItemPriceResponse for rows.Next() { var item dto.ItemPriceResponse scan_err := rows.Scan(&item.ItemId, &item.ItemName, &item.ItemPrice, &item.InSeason) if scan_err != nil { ctx.JSON(http.StatusInternalServerError, "INTERNAL SERVER ERROR") log.Printf("GetItems(): ERROR... failed to scan info...%s", scan_err.Error()) return } items = append(items, item) } ctx.JSON(http.StatusOK, items) } } func GetItemHistory(pool *pgxpool.Pool) gin.HandlerFunc { return func(ctx *gin.Context) { conn, conn_err := pool.Acquire(ctx) if conn_err != nil { log.Printf("DeleteItem(): ERROR: Failed to connect... %s", conn_err.Error()) ctx.AbortWithStatus(http.StatusInternalServerError) return } defer conn.Release() item_id := ctx.Query("item_id") if item_id == "" { ctx.String(http.StatusBadRequest, "Bad Request") return } item_id_int, parse_err := strconv.ParseInt(item_id, 10, 64) if parse_err != nil { ctx.String(http.StatusBadRequest, "Bad Request") return } rows, query_err := conn.Query(ctx, queries.GET_ITEM_PRICE_HISTORY, item_id_int) if query_err != nil { ctx.String(http.StatusInternalServerError, "Internal Server Error") log.Printf("GetItemHistory(): ERROR... Failed to query table... %s", query_err.Error()) return } var item_history_records []dto.ItemHistory for rows.Next() { var item_history_record dto.ItemHistory scan_err := rows.Scan(&item_history_record.ItemId, &item_history_record.ItemName, &item_history_record.ItemPrice, &item_history_record.ValidFrom, &item_history_record.ValidTo) if scan_err != nil { ctx.String(http.StatusInternalServerError, "Internal Server Error") log.Printf("GetItemHistory(): ERROR... Failed to query table... %s", scan_err.Error()) return } item_history_records = append(item_history_records, item_history_record) } ctx.JSON(http.StatusOK, item_history_records) } }