package api import ( "encoding/json" "log" "net/http" "time" "gorm.io/gorm" ) type Purchase struct { gorm.Model `json:"-"` TransactionID int `json:"-" gorm:"column:transaction"` ProductCode int `json:"code" gorm:"column:product"` Product Product `json:"product" gorm:"foreignKey:ProductCode;references:Code"` Price int `json:"price"` Ammount int `json:"ammount"` } func (a *api) AddPurchase(num int, w http.ResponseWriter, req *http.Request) { var purchase []Purchase err := json.NewDecoder(req.Body).Decode(&purchase) if err != nil { log.Printf("Can't create purchase: %v", err) w.WriteHeader(http.StatusInternalServerError) return } total := 0 for i, p := range purchase { var product Product err = a.db.Where("code = ?", p.ProductCode).First(&product).Error if err != nil { log.Printf("Can't get product %d: %v", p.ProductCode, err) w.WriteHeader(http.StatusNotAcceptable) return } total += product.Price * p.Ammount purchase[i].Price = product.Price } if total == 0 { log.Printf("Empty purchase (%d)", num) w.WriteHeader(http.StatusNotAcceptable) return } httpStatus := a.substractMemberBalance(num, total) if httpStatus != http.StatusOK { w.WriteHeader(httpStatus) return } transaction := Transaction{ MemberNum: num, Date: time.Now(), Purchase: purchase, Type: "purchase", Total: total, } err = a.db.Create(&transaction).Error if err != nil { log.Printf("Can't create purchase: %v\n%v", err, purchase) w.WriteHeader(http.StatusInternalServerError) return } for _, p := range purchase { err := a.db.Model(&Product{}). Where("code = ?", p.ProductCode). Update("stock", gorm.Expr("stock - ?", p.Ammount)).Error if err != nil { log.Printf("Can't update product stock %d-%d: %v", p.ProductCode, p.Ammount, err) } } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) err = json.NewEncoder(w).Encode(transaction) if err != nil { log.Printf("Can't encode added purchase: %v", err) w.WriteHeader(http.StatusInternalServerError) } } func (a *api) substractMemberBalance(num int, total int) int { var member Member err := a.db.Where("num = ?", num).Find(&member).Error if err != nil { log.Printf("Can't find member %d: %v", num, err) return http.StatusNotAcceptable } if member.Balance < total { log.Printf("Member %d don't have enough money (%d-%d)", num, member.Balance, total) return http.StatusBadRequest } err = a.db.Model(&Member{}). Where("num = ?", num). Update("balance", gorm.Expr("balance - ?", total)).Error if err != nil { log.Printf("Can't update update member balance %d-%d: %v", num, total, err) return http.StatusNotAcceptable } return http.StatusOK }