Skip to content
Snippets Groups Projects
purchase.go 4.71 KiB
Newer Older
  • Learn to ignore specific revisions
  • meskio's avatar
    meskio committed
    package api
    
    import (
    	"encoding/json"
    	"log"
    	"net/http"
    	"strconv"
    	"time"
    
    	"github.com/gorilla/mux"
    	"gorm.io/gorm"
    )
    
    type Purchase struct {
    
    	gorm.Model
    	MemberNum int                `json:"member" gorm:"column:member"`
    	Member    Member             `json:"-" gorm:"foreignKey:MemberNum;references:Num"`
    	Date      time.Time          `json:"date"`
    	Total     int                `json:"total"`
    	Products  []PurchasedProduct `json:"products"`
    
    meskio's avatar
    meskio committed
    }
    
    type PurchasedProduct struct {
    	gorm.Model  `json:"-"`
    	PurchaseID  int     `json:"-" gorm:"column:purchase"`
    	ProductCode int     `json:"product" gorm:"column:product"`
    	Product     Product `gorm:"foreignKey:ProductCode;references:Code"`
    	Price       int     `json:"price"`
    	Ammount     int     `json:"ammount"`
    }
    
    func (a *api) ListPurchases(w http.ResponseWriter, req *http.Request) {
    	var purchases []Purchase
    	err := a.db.Preload("Products.Product").Find(&purchases).Error
    	if err != nil {
    		log.Printf("Can't list purchases: %v", err)
    		w.WriteHeader(http.StatusInternalServerError)
    		return
    	}
    	w.Header().Set("Content-Type", "application/json")
    	w.WriteHeader(http.StatusOK)
    	err = json.NewEncoder(w).Encode(purchases)
    	if err != nil {
    		log.Printf("Can't encode purchases: %v", err)
    		w.WriteHeader(http.StatusInternalServerError)
    	}
    }
    
    func (a *api) AddPurchase(num int, w http.ResponseWriter, req *http.Request) {
    	var products []PurchasedProduct
    	err := json.NewDecoder(req.Body).Decode(&products)
    	if err != nil {
    		log.Printf("Can't create purchase: %v", err)
    		w.WriteHeader(http.StatusInternalServerError)
    		return
    	}
    	total := 0
    	for i, p := range products {
    		var product Product
    
    		err = a.db.Where("code = ?", p.ProductCode).First(&product).Error
    
    meskio's avatar
    meskio committed
    		if err != nil {
    			log.Printf("Can't get product %d: %v", p.ProductCode, err)
    
    			w.WriteHeader(http.StatusBadRequest)
    
    meskio's avatar
    meskio committed
    			return
    		}
    
    		total += product.Price * p.Ammount
    		products[i].Price = product.Price
    	}
    
    
    	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)
    		w.WriteHeader(http.StatusBadRequest)
    		return
    	}
    	if member.Balance < total {
    		log.Printf("Member %d don't have enough money (%d-%d): %v", num, member.Balance, total, err)
    		w.WriteHeader(http.StatusBadRequest)
    		return
    	}
    
    	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)
    		w.WriteHeader(http.StatusBadRequest)
    		return
    	}
    
    meskio's avatar
    meskio committed
    	purchase := Purchase{
    		MemberNum: num,
    		Date:      time.Now(),
    		Products:  products,
    		Total:     total,
    	}
    	err = a.db.Create(&purchase).Error
    	if err != nil {
    		log.Printf("Can't create purchase: %v\n%v", err, purchase)
    		w.WriteHeader(http.StatusInternalServerError)
    		return
    	}
    
    	for _, p := range products {
    		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)
    
    meskio's avatar
    meskio committed
    		}
    	}
    
    	w.Header().Set("Content-Type", "application/json")
    	w.WriteHeader(http.StatusCreated)
    	err = json.NewEncoder(w).Encode(purchase)
    	if err != nil {
    		log.Printf("Can't encode added purchase: %v", err)
    		w.WriteHeader(http.StatusInternalServerError)
    	}
    
    }
    
    func (a *api) GetPurchase(w http.ResponseWriter, req *http.Request) {
    	vars := mux.Vars(req)
    	var purchase Purchase
    
    	err := a.db.Where("id = ?", vars["id"]).
    		Preload("Products.Product").
    		First(&purchase).Error
    
    meskio's avatar
    meskio committed
    	if err != nil {
    		if err.Error() == "record not found" {
    			w.WriteHeader(http.StatusNotFound)
    			return
    		}
    		log.Printf("Can't get purchase %s: %v", vars["code"], err)
    		w.WriteHeader(http.StatusInternalServerError)
    		return
    	}
    	w.Header().Set("Content-Type", "application/json")
    	w.WriteHeader(http.StatusOK)
    	err = json.NewEncoder(w).Encode(purchase)
    	if err != nil {
    		log.Printf("Can't encode purchase: %v", err)
    		w.WriteHeader(http.StatusInternalServerError)
    		return
    	}
    }
    
    func (a *api) GetMemberPurchases(w http.ResponseWriter, req *http.Request) {
    	vars := mux.Vars(req)
    	num, _ := strconv.Atoi(vars["num"])
    	a.getPurchasesByMember(num, w, req)
    }
    
    func (a *api) getPurchasesByMember(num int, w http.ResponseWriter, req *http.Request) {
    	var purchases []Purchase
    	err := a.db.Where("member = ?", num).
    		Preload("Products.Product").
    		Find(&purchases).Error
    	if err != nil {
    		log.Printf("Can't list purchases: %v", err)
    		w.WriteHeader(http.StatusInternalServerError)
    		return
    	}
    	w.Header().Set("Content-Type", "application/json")
    	w.WriteHeader(http.StatusOK)
    	err = json.NewEncoder(w).Encode(purchases)
    	if err != nil {
    		log.Printf("Can't encode purchases: %v", err)
    		w.WriteHeader(http.StatusInternalServerError)
    	}
    }