Restructure project
This commit is contained in:
parent
e44e7caa11
commit
16b2f17301
46 changed files with 1744 additions and 1265 deletions
124
internal/controller/bill.go
Normal file
124
internal/controller/bill.go
Normal file
|
@ -0,0 +1,124 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"gitlab.unjx.de/flohoss/cafe-plaetschwiesle/internal/types"
|
||||
)
|
||||
|
||||
type (
|
||||
Bill struct {
|
||||
ID uint64 `gorm:"primaryKey" json:"id" validate:"optional"`
|
||||
TableID uint64 `json:"table_id" validate:"required"`
|
||||
Total float32 `json:"total" validate:"required"`
|
||||
CreatedAt int64 `json:"created_at" validate:"optional"`
|
||||
}
|
||||
|
||||
BillItem struct {
|
||||
ID uint64 `gorm:"primaryKey" json:"id" validate:"optional"`
|
||||
BillID uint64 `json:"bill_id" validate:"required"`
|
||||
Description string `json:"description" validate:"required"`
|
||||
Total float32 `json:"total" validate:"required"`
|
||||
Price float32 `json:"price" validate:"required"`
|
||||
Amount uint64 `json:"amount" validate:"required"`
|
||||
ItemType types.ItemType `json:"item_type" validate:"required"`
|
||||
}
|
||||
)
|
||||
|
||||
func (c *Controller) DoesBillExist(id string) (Bill, error) {
|
||||
var bill Bill
|
||||
result := c.orm.Limit(1).Find(&bill, id)
|
||||
if result.RowsAffected == 0 {
|
||||
return bill, fmt.Errorf(types.CannotFind.String())
|
||||
}
|
||||
return bill, nil
|
||||
}
|
||||
|
||||
func (c *Controller) GetAllBillItems(billId uint64) ([]BillItem, error) {
|
||||
var billItems []BillItem
|
||||
result := c.orm.Where("bill_id = ?", billId).Find(&billItems)
|
||||
if result.RowsAffected == 0 {
|
||||
return billItems, fmt.Errorf(types.CannotFind.String())
|
||||
}
|
||||
return billItems, nil
|
||||
}
|
||||
|
||||
func getDate(year string, month string, day string) (time.Time, error) {
|
||||
yearI, yearErr := strconv.Atoi(year)
|
||||
if yearErr != nil {
|
||||
return time.Time{}, fmt.Errorf("jahr " + types.CannotParse.String())
|
||||
}
|
||||
monthI, monthErr := strconv.Atoi(month)
|
||||
if monthErr != nil {
|
||||
return time.Time{}, fmt.Errorf("monat " + types.CannotParse.String())
|
||||
}
|
||||
dayI, dayErr := strconv.Atoi(day)
|
||||
if dayErr != nil {
|
||||
return time.Time{}, fmt.Errorf("tag " + types.CannotParse.String())
|
||||
}
|
||||
loc, locErr := time.LoadLocation("Local")
|
||||
if locErr != nil {
|
||||
return time.Time{}, fmt.Errorf("timezone " + types.CannotParse.String())
|
||||
}
|
||||
return time.Date(yearI, time.Month(monthI), dayI, 0, 0, 0, 0, loc), nil
|
||||
}
|
||||
|
||||
func (c *Controller) GetAllBills(year string, month string, day string) ([]Bill, error) {
|
||||
var bills []Bill
|
||||
today, err := getDate(year, month, day)
|
||||
if err != nil {
|
||||
return bills, err
|
||||
}
|
||||
beginningOfDay := today.Unix()
|
||||
endOfDay := today.Add(23 * time.Hour).Add(59 * time.Minute).Add(59 * time.Second).Unix()
|
||||
c.orm.Where("created_at BETWEEN ? AND ?", beginningOfDay, endOfDay).Order("created_at").Find(&bills)
|
||||
return bills, nil
|
||||
}
|
||||
|
||||
func (c *Controller) createBill(options GetOrderOptions) (Bill, error) {
|
||||
orders := c.getAllOrdersForTable(options)
|
||||
var bill Bill
|
||||
var total float32 = 0
|
||||
for _, order := range orders {
|
||||
total += order.Total
|
||||
}
|
||||
bill.TableID = options.TableId
|
||||
bill.Total = total
|
||||
err := c.orm.Create(&bill).Error
|
||||
if err != nil {
|
||||
return bill, fmt.Errorf(types.CannotCreate.String())
|
||||
}
|
||||
for _, order := range orders {
|
||||
billItem := BillItem{
|
||||
BillID: bill.ID,
|
||||
Description: order.OrderItem.Description,
|
||||
Total: order.Total,
|
||||
Price: order.OrderItem.Price,
|
||||
Amount: order.OrderCount,
|
||||
ItemType: order.OrderItem.ItemType,
|
||||
}
|
||||
c.orm.Create(&billItem)
|
||||
}
|
||||
ordersToDelete := c.getAllOrdersForTable(GetOrderOptions{TableId: options.TableId, Grouped: false, Filter: options.Filter})
|
||||
err = c.orm.Delete(&ordersToDelete).Error
|
||||
if err != nil {
|
||||
return bill, fmt.Errorf(types.CannotDelete.String())
|
||||
}
|
||||
c.publishMessage(StatusMessage{
|
||||
Type: types.DeleteAll,
|
||||
Payload: ordersToDelete,
|
||||
})
|
||||
return bill, nil
|
||||
}
|
||||
|
||||
func (c *Controller) deleteBill(bill *Bill) error {
|
||||
err := c.orm.Delete(bill).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf(types.CannotDelete.String())
|
||||
}
|
||||
billItemsToDelete, _ := c.GetAllBillItems(bill.ID)
|
||||
c.orm.Delete(&billItemsToDelete)
|
||||
return nil
|
||||
}
|
34
internal/controller/controller.go
Normal file
34
internal/controller/controller.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"github.com/r3labs/sse/v2"
|
||||
"gitlab.unjx.de/flohoss/cafe-plaetschwiesle/internal/database"
|
||||
"gitlab.unjx.de/flohoss/cafe-plaetschwiesle/internal/env"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
orm *gorm.DB
|
||||
env *env.Config
|
||||
SSE *sse.Server
|
||||
}
|
||||
|
||||
func NewController(env *env.Config) *Controller {
|
||||
db := database.NewDatabaseConnection(&database.Database{
|
||||
Host: env.DB_Host,
|
||||
User: env.DB_User,
|
||||
Password: env.DB_Password,
|
||||
Database: env.DB_Database,
|
||||
})
|
||||
|
||||
db.AutoMigrate(&Table{})
|
||||
db.AutoMigrate(&Order{})
|
||||
db.AutoMigrate(&OrderItem{})
|
||||
db.AutoMigrate(&Bill{})
|
||||
db.AutoMigrate(&BillItem{})
|
||||
db.AutoMigrate(&User{})
|
||||
|
||||
ctrl := Controller{orm: db, env: env, SSE: sse.New()}
|
||||
ctrl.setupEventChannel()
|
||||
return &ctrl
|
||||
}
|
25
internal/controller/events.go
Normal file
25
internal/controller/events.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/r3labs/sse/v2"
|
||||
"gitlab.unjx.de/flohoss/cafe-plaetschwiesle/internal/types"
|
||||
)
|
||||
|
||||
const ServerSideEvent = "sse"
|
||||
|
||||
type StatusMessage struct {
|
||||
Type types.NotifierType `json:"type"`
|
||||
Payload []Order `json:"payload"`
|
||||
}
|
||||
|
||||
func (c *Controller) setupEventChannel() {
|
||||
c.SSE.AutoReplay = false
|
||||
c.SSE.CreateStream(ServerSideEvent)
|
||||
}
|
||||
|
||||
func (c *Controller) publishMessage(msg StatusMessage) {
|
||||
json, _ := json.Marshal(msg)
|
||||
c.SSE.Publish(ServerSideEvent, &sse.Event{Data: json})
|
||||
}
|
168
internal/controller/order.go
Normal file
168
internal/controller/order.go
Normal file
|
@ -0,0 +1,168 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gitlab.unjx.de/flohoss/cafe-plaetschwiesle/internal/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type (
|
||||
Order struct {
|
||||
ID uint64 `gorm:"primaryKey" json:"id" validate:"optional"`
|
||||
TableID uint64 `json:"table_id" validate:"required"`
|
||||
OrderItemID uint64 `json:"order_item_id" validate:"required"`
|
||||
OrderItem OrderItem `json:"order_item" validate:"required"`
|
||||
UpdatedAt int64 `json:"updated_at" validate:"optional"`
|
||||
IsServed bool `json:"is_served" default:"false" validate:"required"`
|
||||
Total float32 `json:"total" validate:"required"`
|
||||
OrderCount uint64 `json:"order_count" validate:"required"`
|
||||
}
|
||||
|
||||
OrderItem struct {
|
||||
ID uint64 `gorm:"primaryKey" json:"id" validate:"optional"`
|
||||
ItemType types.ItemType `json:"item_type" validate:"required"`
|
||||
Description string `json:"description" validate:"required"`
|
||||
Price float32 `json:"price" validate:"required"`
|
||||
}
|
||||
|
||||
GetOrderOptions struct {
|
||||
TableId uint64 `json:"table_id"`
|
||||
Grouped bool `json:"grouped"`
|
||||
Filter []string `json:"filter"`
|
||||
}
|
||||
)
|
||||
|
||||
func updateTableUpdatedAt(tx *gorm.DB, o *Order) {
|
||||
var table Table
|
||||
tx.Where("id = ?", o.TableID).First(&table)
|
||||
table.UpdatedAt = time.Now().Unix()
|
||||
tx.Save(&table)
|
||||
}
|
||||
|
||||
func (o *Order) AfterCreate(tx *gorm.DB) (err error) {
|
||||
updateTableUpdatedAt(tx, o)
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Order) AfterDelete(tx *gorm.DB) (err error) {
|
||||
updateTableUpdatedAt(tx, o)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Controller) doesOrderItemExist(id string) (OrderItem, error) {
|
||||
var orderItem OrderItem
|
||||
result := c.orm.Limit(1).Find(&orderItem, id)
|
||||
if result.RowsAffected == 0 {
|
||||
return orderItem, fmt.Errorf(types.CannotFind.String())
|
||||
}
|
||||
return orderItem, nil
|
||||
}
|
||||
|
||||
func (c *Controller) doesOrderExist(id string) (Order, error) {
|
||||
var order Order
|
||||
result := c.orm.Limit(1).Find(&order, id)
|
||||
if result.RowsAffected == 0 {
|
||||
return order, fmt.Errorf(types.CannotFind.String())
|
||||
}
|
||||
return order, nil
|
||||
}
|
||||
|
||||
func (c *Controller) getAllActiveOrders() []Order {
|
||||
var orders []Order
|
||||
c.orm.Model(&Order{}).Joins("OrderItem").Where("is_served = ?", 0).Order("updated_at").Find(&orders)
|
||||
return orders
|
||||
}
|
||||
|
||||
func (c *Controller) getAllOrdersForTable(options GetOrderOptions) []Order {
|
||||
var orders []Order
|
||||
if options.Grouped {
|
||||
if len(options.Filter) == 0 {
|
||||
c.orm.Model(&Order{}).Joins("OrderItem").Select("table_id, order_item_id, sum(price) as total, count(order_item_id) as order_count").Group("order_item_id").Where("table_id = ?", options.TableId).Order("item_type, description").Find(&orders)
|
||||
} else {
|
||||
c.orm.Model(&Order{}).Find(&orders, options.Filter).Joins("OrderItem").Select("table_id, order_item_id, sum(price) as total, count(order_item_id) as order_count").Group("order_item_id").Where("table_id = ?", options.TableId).Order("item_type, description").Find(&orders)
|
||||
}
|
||||
} else {
|
||||
if len(options.Filter) == 0 {
|
||||
c.orm.Model(&Order{}).Joins("OrderItem").Where("table_id = ?", options.TableId).Order("item_type, description").Find(&orders)
|
||||
} else {
|
||||
c.orm.Model(&Order{}).Find(&orders, options.Filter).Where("table_id = ?", options.TableId).Find(&orders)
|
||||
}
|
||||
}
|
||||
return orders
|
||||
}
|
||||
|
||||
func (c *Controller) createOrder(order *Order) error {
|
||||
err := c.orm.Create(order).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf(types.CannotCreate.String())
|
||||
}
|
||||
c.orm.Model(&Order{}).Joins("OrderItem").First(order)
|
||||
c.publishMessage(StatusMessage{
|
||||
Type: types.Create,
|
||||
Payload: []Order{*order},
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) updateOrder(old *Order, new *Order) error {
|
||||
err := c.orm.First(old).Updates(new).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf(types.CannotUpdate.String())
|
||||
}
|
||||
if new.IsServed {
|
||||
c.publishMessage(StatusMessage{
|
||||
Type: types.Delete,
|
||||
Payload: []Order{*new},
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) deleteOrder(tableId string, orderItemId string) error {
|
||||
var order Order
|
||||
err := c.orm.Where("table_id = ? AND order_item_id = ?", tableId, orderItemId).Last(&order).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf(types.CannotFind.String())
|
||||
}
|
||||
err = c.orm.Delete(&order).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf(types.CannotDelete.String())
|
||||
}
|
||||
c.publishMessage(StatusMessage{
|
||||
Type: types.Delete,
|
||||
Payload: []Order{order},
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) getOrderItemsForType(itemType string) []OrderItem {
|
||||
var orderItems []OrderItem
|
||||
c.orm.Order("description").Where("item_type = ?", types.ParseItemType(itemType)).Find(&orderItems)
|
||||
return orderItems
|
||||
}
|
||||
|
||||
func (c *Controller) createOrderItem(oderItem *OrderItem) error {
|
||||
err := c.orm.Create(oderItem).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf(types.CannotCreate.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) updateOrderItem(old *OrderItem, new *OrderItem) error {
|
||||
err := c.orm.First(old).Updates(new).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf(types.CannotUpdate.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) deleteOrderItem(oderItem *OrderItem) error {
|
||||
err := c.orm.Delete(oderItem).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf(types.CannotDelete.String())
|
||||
}
|
||||
return nil
|
||||
}
|
105
internal/controller/routesBill.go
Normal file
105
internal/controller/routesBill.go
Normal file
|
@ -0,0 +1,105 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitlab.unjx.de/flohoss/cafe-plaetschwiesle/internal/types"
|
||||
)
|
||||
|
||||
// @Schemes
|
||||
// @Summary get all bills
|
||||
// @Description gets all bills as array
|
||||
// @Tags bills
|
||||
// @Produce json
|
||||
// @Param year query int true "year"
|
||||
// @Param month query int true "month (1-12)"
|
||||
// @Param day query int true "day (1-31)"
|
||||
// @Success 200 {array} Bill
|
||||
// @Router /bills [get]
|
||||
func (c *Controller) GetBills(ctx echo.Context) error {
|
||||
year := ctx.QueryParam("year")
|
||||
month := ctx.QueryParam("month")
|
||||
day := ctx.QueryParam("day")
|
||||
if year == "" || month == "" || day == "" {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, types.MissingInformation.String())
|
||||
}
|
||||
bills, err := c.GetAllBills(year, month, day)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.JSON(http.StatusOK, bills)
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary get all billItems
|
||||
// @Description gets all billItems for bill
|
||||
// @Tags bills
|
||||
// @Produce json
|
||||
// @Param bill query int true "Bill ID"
|
||||
// @Success 200 {array} BillItem
|
||||
// @Router /bills/items [get]
|
||||
func (c *Controller) GetBillItems(ctx echo.Context) error {
|
||||
bill, err := c.DoesBillExist(ctx.QueryParam("bill"))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusNotFound, err.Error())
|
||||
}
|
||||
billItems, err := c.GetAllBillItems(bill.ID)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.JSON(http.StatusOK, billItems)
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary create new bill
|
||||
// @Description creates a new bill and returns it
|
||||
// @Tags bills
|
||||
// @Produce json
|
||||
// @Param table query int true "Table ID"
|
||||
// @Param filter query string false "filter"
|
||||
// @Success 201 {object} Bill
|
||||
// @Failure 404 "Not Found"
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /bills [post]
|
||||
func (c *Controller) CreateBill(ctx echo.Context) error {
|
||||
table, tableErr := strconv.ParseUint(ctx.QueryParam("table"), 10, 64)
|
||||
if tableErr != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, types.MissingInformation.String())
|
||||
}
|
||||
stringFiler := ctx.QueryParam("filter")
|
||||
var filter []string
|
||||
if stringFiler != "" {
|
||||
filter = strings.Split(stringFiler, ",")
|
||||
}
|
||||
bill, err := c.createBill(GetOrderOptions{TableId: table, Grouped: true, Filter: filter})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.JSON(http.StatusCreated, bill)
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary delete a bill
|
||||
// @Description deletes a bill
|
||||
// @Tags bills
|
||||
// @Produce json
|
||||
// @Param id path int true "Bill ID"
|
||||
// @Success 200 "OK"
|
||||
// @Failure 404 "Not Found"
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /bills/{id} [delete]
|
||||
func (c *Controller) DeleteBill(ctx echo.Context) error {
|
||||
id := ctx.Param("id")
|
||||
bill, err := c.DoesBillExist(id)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusNotFound, err.Error())
|
||||
}
|
||||
err = c.deleteBill(&bill)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.NoContent(http.StatusOK)
|
||||
}
|
209
internal/controller/routesOrder.go
Normal file
209
internal/controller/routesOrder.go
Normal file
|
@ -0,0 +1,209 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitlab.unjx.de/flohoss/cafe-plaetschwiesle/internal/types"
|
||||
)
|
||||
|
||||
// @Schemes
|
||||
// @Summary get all orders
|
||||
// @Description gets all orders as array
|
||||
// @Tags orders
|
||||
// @Produce json
|
||||
// @Param table query int false "Table ID"
|
||||
// @Param grouping query bool false "grouping"
|
||||
// @Param filter query string false "filter"
|
||||
// @Success 200 {array} Order
|
||||
// @Router /orders [get]
|
||||
func (c *Controller) GetOrders(ctx echo.Context) error {
|
||||
table, _ := strconv.ParseUint(ctx.QueryParam("table"), 10, 64)
|
||||
grouping, _ := strconv.ParseBool(ctx.QueryParam("grouping"))
|
||||
stringFiler := ctx.QueryParam("filter")
|
||||
var filter []string
|
||||
if stringFiler != "" {
|
||||
filter = strings.Split(stringFiler, ",")
|
||||
}
|
||||
options := GetOrderOptions{TableId: table, Grouped: grouping, Filter: filter}
|
||||
var orders []Order
|
||||
if options.TableId == 0 {
|
||||
orders = c.getAllActiveOrders()
|
||||
} else {
|
||||
orders = c.getAllOrdersForTable(options)
|
||||
}
|
||||
return ctx.JSON(http.StatusOK, orders)
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary create new order
|
||||
// @Description creates a new order and returns it
|
||||
// @Tags orders
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param item query int true "OrderItem ID"
|
||||
// @Param table query int true "Table ID"
|
||||
// @Success 201 {object} Order
|
||||
// @Failure 400
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /orders [post]
|
||||
func (c *Controller) CreateOrder(ctx echo.Context) error {
|
||||
table, err1 := strconv.ParseUint(ctx.QueryParam("table"), 10, 64)
|
||||
item, err2 := strconv.ParseUint(ctx.QueryParam("item"), 10, 64)
|
||||
if err1 != nil || err2 != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, types.MissingInformation.String())
|
||||
}
|
||||
order := Order{TableID: table, OrderItemID: item, IsServed: false}
|
||||
err := c.createOrder(&order)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.JSON(http.StatusCreated, order)
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary delete an order
|
||||
// @Description deletes an order from the database
|
||||
// @Tags orders
|
||||
// @Produce json
|
||||
// @Param item query int true "OrderItem ID"
|
||||
// @Param table query int true "Table ID"
|
||||
// @Success 200 "OK"
|
||||
// @Failure 400 "Bad Request"
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /orders [delete]
|
||||
func (c *Controller) DeleteOrder(ctx echo.Context) error {
|
||||
item := ctx.QueryParam("item")
|
||||
table := ctx.QueryParam("table")
|
||||
if table == "" || item == "" {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, types.MissingInformation.String())
|
||||
}
|
||||
err := c.deleteOrder(table, item)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.NoContent(http.StatusOK)
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary update an order
|
||||
// @Description updates an order with provided information
|
||||
// @Tags orders
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param order body Order true "updated Order"
|
||||
// @Success 200 {object} Order
|
||||
// @Failure 400 "Bad Request"
|
||||
// @Failure 404 "Not Found"
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /orders [put]
|
||||
func (c *Controller) UpdateOrder(ctx echo.Context) error {
|
||||
var newOrder Order
|
||||
err := ctx.Bind(&newOrder)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
oldOrder, err := c.doesOrderExist(strconv.Itoa(int(newOrder.ID)))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusNotFound, err.Error())
|
||||
}
|
||||
err = c.updateOrder(&oldOrder, &newOrder)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.JSON(http.StatusOK, newOrder)
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary get all orderItems
|
||||
// @Description gets all orderItems as array
|
||||
// @Tags orderItems
|
||||
// @Produce json
|
||||
// @Param type query int true "ItemType"
|
||||
// @Success 200 {array} OrderItem
|
||||
// @Router /orders/items [get]
|
||||
func (c *Controller) GetOrderItems(ctx echo.Context) error {
|
||||
orderType := ctx.QueryParam("type")
|
||||
if orderType == "" {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, types.MissingInformation.String())
|
||||
}
|
||||
return ctx.JSON(http.StatusOK, c.getOrderItemsForType(orderType))
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary create new orderItem
|
||||
// @Description creates a new orderItem and returns it
|
||||
// @Tags orderItems
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param order body OrderItem true "OrderItem ID"
|
||||
// @Success 201 {object} OrderItem
|
||||
// @Failure 400 "Bad Request"
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /orders/items [post]
|
||||
func (c *Controller) CreateOrderItem(ctx echo.Context) error {
|
||||
var orderItem OrderItem
|
||||
err := ctx.Bind(&orderItem)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
err = c.createOrderItem(&orderItem)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.JSON(http.StatusCreated, orderItem)
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary update a orderItem
|
||||
// @Description updates a orderItem with provided information
|
||||
// @Tags orderItems
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param orderItem body OrderItem true "updated OrderItem"
|
||||
// @Success 200 {object} OrderItem
|
||||
// @Failure 400 "Bad Request"
|
||||
// @Failure 404 "Not Found"
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /orders/items [put]
|
||||
func (c *Controller) UpdateOrderItem(ctx echo.Context) error {
|
||||
var newOrderItem OrderItem
|
||||
err := ctx.Bind(&newOrderItem)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
oldOrderItem, err := c.doesOrderItemExist(strconv.Itoa(int(newOrderItem.ID)))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusNotFound, err.Error())
|
||||
}
|
||||
err = c.updateOrderItem(&oldOrderItem, &newOrderItem)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.JSON(http.StatusOK, newOrderItem)
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary delete an orderItem
|
||||
// @Description deletes an orderItem from the database
|
||||
// @Tags orderItems
|
||||
// @Produce json
|
||||
// @Param id path int true "OrderItem ID"
|
||||
// @Success 200 "OK"
|
||||
// @Failure 404 "Not Found"
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /orders/items/{id} [delete]
|
||||
func (c *Controller) DeleteOrderItem(ctx echo.Context) error {
|
||||
id := ctx.Param("id")
|
||||
orderItem, err := c.doesOrderItemExist(id)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusNotFound, err.Error())
|
||||
}
|
||||
err = c.deleteOrderItem(&orderItem)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.NoContent(http.StatusOK)
|
||||
}
|
51
internal/controller/routesTable.go
Normal file
51
internal/controller/routesTable.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// @Schemes
|
||||
// @Summary get all active tables
|
||||
// @Description gets all active tables as array
|
||||
// @Tags tables
|
||||
// @Produce json
|
||||
// @Success 200 {array} Table
|
||||
// @Router /tables [get]
|
||||
func (c *Controller) GetTables(ctx echo.Context) error {
|
||||
return ctx.JSON(http.StatusOK, c.GetAllTables())
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary create new table
|
||||
// @Description creates a new table and returns it
|
||||
// @Tags tables
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 201 {object} Table "Table has been created"
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /tables [post]
|
||||
func (c *Controller) CreateTable(ctx echo.Context) error {
|
||||
table, err := c.CreateNewTable()
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.JSON(http.StatusCreated, table)
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary delete the latest table
|
||||
// @Description deletes the latest table from the database
|
||||
// @Tags tables
|
||||
// @Produce json
|
||||
// @Success 200 "OK"
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /tables [delete]
|
||||
func (c *Controller) DeleteTable(ctx echo.Context) error {
|
||||
err := c.DeleteLatestTable()
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.NoContent(http.StatusOK)
|
||||
}
|
54
internal/controller/routesUser.go
Normal file
54
internal/controller/routesUser.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// @Schemes
|
||||
// @Summary get a user
|
||||
// @Description gets a user
|
||||
// @Tags users
|
||||
// @Produce json
|
||||
// @Param username path string true "Username"
|
||||
// @Success 200 {object} User
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /users/{username} [get]
|
||||
func (c *Controller) GetUser(ctx echo.Context) error {
|
||||
username := ctx.Param("username")
|
||||
u, err := c.getUserOrCreate(username)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
return ctx.JSON(http.StatusOK, u)
|
||||
}
|
||||
|
||||
// @Schemes
|
||||
// @Summary update a user
|
||||
// @Description updates a user with provided information
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param user body User true "updated User"
|
||||
// @Success 200 {object} User
|
||||
// @Failure 400 "Bad Request"
|
||||
// @Failure 404 "Not Found"
|
||||
// @Failure 500 "Internal Server Error"
|
||||
// @Router /users [put]
|
||||
func (c *Controller) UpdateUser(ctx echo.Context) error {
|
||||
var newUser User
|
||||
err := ctx.Bind(&newUser)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
oldUser, err := c.doesUserExist(newUser.Username)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusNotFound, err.Error())
|
||||
}
|
||||
err = c.updateUser(&oldUser, &newUser)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return ctx.JSON(http.StatusOK, newUser)
|
||||
}
|
74
internal/controller/table.go
Normal file
74
internal/controller/table.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gitlab.unjx.de/flohoss/cafe-plaetschwiesle/internal/types"
|
||||
"gorm.io/plugin/soft_delete"
|
||||
)
|
||||
|
||||
type Table struct {
|
||||
ID uint64 `gorm:"primaryKey" json:"id" validate:"optional"`
|
||||
OrderCount uint64 `json:"order_count" validate:"required"`
|
||||
Total float32 `json:"total" validate:"required"`
|
||||
UpdatedAt int64 `json:"updated_at" validate:"optional"`
|
||||
IsDeleted soft_delete.DeletedAt `gorm:"softDelete:flag" json:"is_deleted" swaggerignore:"true"`
|
||||
}
|
||||
|
||||
func (c *Controller) GetAllTables() []Table {
|
||||
var tables []Table
|
||||
c.orm.Model(
|
||||
&Table{},
|
||||
).Joins(
|
||||
"left join orders on tables.id = orders.table_id",
|
||||
).Joins(
|
||||
"left join order_items on orders.order_item_id = order_items.id",
|
||||
).Select(
|
||||
"tables.id, tables.updated_at, sum(order_items.price) as total, count(orders.id) as order_count",
|
||||
).Group(
|
||||
"tables.id",
|
||||
).Order("tables.id").Find(&tables)
|
||||
return tables
|
||||
}
|
||||
|
||||
func (c *Controller) CreateNewTable() (Table, error) {
|
||||
var table Table
|
||||
var err error
|
||||
result := c.orm.Unscoped().Where("is_deleted = ?", 1).Limit(1).Find(&table)
|
||||
if result.RowsAffected == 0 {
|
||||
err = c.orm.Create(&table).Error
|
||||
} else {
|
||||
table.IsDeleted = 0
|
||||
err = c.orm.Unscoped().Save(&table).Error
|
||||
}
|
||||
if err != nil {
|
||||
return table, fmt.Errorf(types.CannotCreate.String())
|
||||
}
|
||||
return table, nil
|
||||
}
|
||||
|
||||
func (c *Controller) DeleteLatestTable() error {
|
||||
var table Table
|
||||
err := c.orm.Model(
|
||||
&Table{},
|
||||
).Joins(
|
||||
"left join orders on tables.id = orders.table_id",
|
||||
).Joins(
|
||||
"left join order_items on orders.order_item_id = order_items.id",
|
||||
).Select(
|
||||
"tables.id, count(orders.id) as order_count",
|
||||
).Group(
|
||||
"tables.id",
|
||||
).Last(&table).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf(types.CannotFind.String())
|
||||
}
|
||||
if table.OrderCount != 0 {
|
||||
return fmt.Errorf(types.StillInUse.String())
|
||||
}
|
||||
err = c.orm.Delete(&table).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf(types.CannotDelete.String())
|
||||
}
|
||||
return nil
|
||||
}
|
42
internal/controller/user.go
Normal file
42
internal/controller/user.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gitlab.unjx.de/flohoss/cafe-plaetschwiesle/internal/types"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Username string `gorm:"primaryKey" json:"username" validate:"required"`
|
||||
ShowColdDrinks bool `json:"show_cold_drinks" validate:"required"`
|
||||
ShowHotDrinks bool `json:"show_hot_drinks" validate:"required"`
|
||||
}
|
||||
|
||||
func (c *Controller) doesUserExist(username string) (User, error) {
|
||||
var user User
|
||||
result := c.orm.Limit(1).Find(&user, "username = ?", username)
|
||||
if result.RowsAffected == 0 {
|
||||
return user, fmt.Errorf(types.CannotFind.String())
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (c *Controller) getUserOrCreate(username string) (User, error) {
|
||||
var user User
|
||||
err := c.orm.Where(User{Username: username}).Attrs(User{ShowHotDrinks: true, ShowColdDrinks: true}).FirstOrCreate(&user).Error
|
||||
if err != nil {
|
||||
return user, fmt.Errorf(types.CannotCreate.String())
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (c *Controller) updateUser(old *User, new *User) error {
|
||||
err := c.orm.First(old).Updates(map[string]interface{}{
|
||||
"Username": new.Username,
|
||||
"ShowColdDrinks": new.ShowColdDrinks,
|
||||
"ShowHotDrinks": new.ShowHotDrinks}).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf(types.CannotUpdate.String())
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue