Skip to content
Snippets Groups Projects
Commit f2fcb2b3 authored by meskio's avatar meskio :tent:
Browse files

Redesign orders in the db

parent 481a01c5
No related branches found
No related tags found
No related merge requests found
......@@ -16,14 +16,14 @@ type Order struct {
gorm.Model
Name string `json:"name"`
Description string `json:"description"`
MemberNum int `json:"-" gorm:"column:member"`
MemberNum int `json:"member_num" gorm:"column:member"`
Member *Member `json:"member,omitempty" gorm:"foreignKey:MemberNum;references:Num"`
Deadline time.Time `json:"deadline"`
Active bool `json:"active" gorm:"index"`
Products []Product `json:"products" gorm:"many2many:order_products;References:Code;JoinReferences:ProductCode"`
Purchases []OrderPurchase `json:"purchases"`
TransactionID *uint `json:"-" gorm:"column:transaction"`
Products []Product `json:"products" gorm:"many2many:order_products;References:Code;JoinReferences:ProductCode"`
Transactions []Transaction `json:"transactions" gorm:"foreignKey:OrderID"`
TransactionID *uint `json:"-" gorm:"column:transaction"`
}
type OrderPurchase struct {
......@@ -31,8 +31,6 @@ type OrderPurchase struct {
TransactionID uint `json:"-"`
ProductCode int `json:"product_code"`
Product *Product `json:"product" gorm:"foreignKey:ProductCode;references:Code"`
OrderID uint `json:"order_id"`
Order *Order `json:"-"`
Price int `json:"price"`
Amount int `json:"amount"`
}
......@@ -42,6 +40,11 @@ type OrderGetResponse struct {
Transaction *Transaction `json:"transaction"`
}
type OrderPurchaseRequest struct {
Purchase []OrderPurchase `json:"purchase"`
OrderID uint `json:"order"`
}
func (a *api) refundOrders() {
const refundSleeptime = 10 * time.Minute
for {
......@@ -55,7 +58,7 @@ func (a *api) deactivateOrders() {
now := time.Now()
t := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
err := a.db.Where("active = ? AND deadline < ?", true, t).
Preload("Purchases").
Preload("Transactions.OrderPurchase").
Find(&orders).Error
if err != nil {
log.Println("Error refunding orders:", err)
......@@ -64,8 +67,10 @@ func (a *api) deactivateOrders() {
for _, order := range orders {
total := 0
for _, purchase := range order.Purchases {
total += purchase.Price * purchase.Amount
for _, transaction := range order.Transactions {
for _, purchase := range transaction.OrderPurchase {
total += purchase.Price * purchase.Amount
}
}
transaction := Transaction{
......@@ -105,7 +110,8 @@ func (a *api) ListActiveOrders(w http.ResponseWriter, req *http.Request) {
func (a *api) listOrders(active bool, w http.ResponseWriter, req *http.Request) {
var orders []Order
query := a.db.Preload(clause.Associations)
query := a.db.Preload(clause.Associations).
Preload("Transactions.OrderPurchase")
if active {
query = query.Where("active = ?", true)
}
......@@ -129,6 +135,8 @@ func (a *api) GetOrder(num int, w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
var order Order
err := a.db.Preload(clause.Associations).
Preload("Transactions.OrderPurchase").
Preload("Transactions.Member").
First(&order, vars["id"]).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
......@@ -143,10 +151,8 @@ func (a *api) GetOrder(num int, w http.ResponseWriter, req *http.Request) {
body.Order = order
var transaction Transaction
err = a.db.Where("member = ? AND type = 'order' AND id IN (?)", num,
a.db.Table("order_purchases").
Where("order_id = ?", order.ID).
Select("transaction_id")).
err = a.db.Where("member = ? AND type = 'order' AND order_id = ?", num, vars["id"]).
Preload("OrderPurchase.Product").
Find(&transaction).Error
if err != nil {
log.Printf("Can't get order transaction %s: %v", vars["id"], err)
......@@ -196,14 +202,14 @@ func (a *api) AddOrder(num int, w http.ResponseWriter, req *http.Request) {
}
func (a *api) AddOrderPurchase(num int, w http.ResponseWriter, req *http.Request) {
var purchase []OrderPurchase
err := json.NewDecoder(req.Body).Decode(&purchase)
var request OrderPurchaseRequest
err := json.NewDecoder(req.Body).Decode(&request)
if err != nil {
log.Printf("Can't parse order: %v", err)
log.Printf("Can't parse order purchase: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if len(purchase) == 0 {
if len(request.Purchase) == 0 {
log.Printf("Empty order purchase")
w.WriteHeader(http.StatusBadRequest)
return
......@@ -211,43 +217,52 @@ func (a *api) AddOrderPurchase(num int, w http.ResponseWriter, req *http.Request
var order Order
err = a.db.Preload("Products").
First(&order, purchase[0].OrderID).Error
Preload("Transactions").
First(&order, request.OrderID).Error
if err != nil {
log.Printf("Can't get order %d: %v", purchase[0].OrderID, err)
log.Printf("Can't get order %d: %v", request.OrderID, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if !order.Active {
log.Printf("Order is not active %d: %v", order.ID, purchase)
log.Printf("Order is not active %d: %v", order.ID, request)
w.WriteHeader(http.StatusBadRequest)
return
}
for _, t := range order.Transactions {
if t.MemberNum == num {
log.Printf("Purchase by %d for %d when there is already one by this member: %v", num, order.ID, request)
w.WriteHeader(http.StatusBadRequest)
return
}
}
total := 0
for i, p := range purchase {
for i, p := range request.Purchase {
found := false
for _, product := range order.Products {
if product.Code == p.ProductCode {
total += product.Price * p.Amount
purchase[i].Price = product.Price
request.Purchase[i].Price = product.Price
found = true
break
}
}
if !found {
log.Printf("Order purchase product %d not in order: %v", p.ProductCode, purchase)
log.Printf("Order purchase product %d not in order: %v", p.ProductCode, request)
w.WriteHeader(http.StatusBadRequest)
return
}
}
transaction := Transaction{
MemberNum: num,
Total: -total,
Type: "order",
Date: time.Now(),
Order: purchase,
MemberNum: num,
Total: -total,
Type: "order",
Date: time.Now(),
OrderPurchase: request.Purchase,
OrderID: &order.ID,
}
httpStatus, err := createTransaction(a.db, &transaction)
if err != nil {
......
......@@ -75,11 +75,13 @@ func TestOrderPurchase(t *testing.T) {
t.Fatal("Can't get orders:", resp.Status)
}
purchase := []OrderPurchase{
{
ProductCode: testProduct.Code,
Amount: 3,
OrderID: orders[0].ID,
purchase := OrderPurchaseRequest{
OrderID: orders[0].ID,
Purchase: []OrderPurchase{
{
ProductCode: testProduct.Code,
Amount: 3,
},
},
}
resp = tapi.do("POST", "/order/purchase", purchase, nil)
......@@ -170,11 +172,13 @@ func TestOrderDeactivation(t *testing.T) {
t.Fatal("Didn't find my new order")
}
purchase := []OrderPurchase{
{
ProductCode: testProduct.Code,
Amount: 3,
OrderID: orders[0].ID,
purchase := OrderPurchaseRequest{
OrderID: orders[0].ID,
Purchase: []OrderPurchase{
{
ProductCode: testProduct.Code,
Amount: 3,
},
},
}
resp = tapi.doAdmin("POST", "/order/purchase", purchase, nil)
......@@ -253,11 +257,13 @@ func TestGetOrder(t *testing.T) {
t.Error("Wrong name:", body.Order.Name)
}
purchase := []OrderPurchase{
{
ProductCode: testProduct.Code,
Amount: 3,
OrderID: orders[0].ID,
purchase := OrderPurchaseRequest{
OrderID: orders[0].ID,
Purchase: []OrderPurchase{
{
ProductCode: testProduct.Code,
Amount: 3,
},
},
}
resp = tapi.do("POST", "/order/purchase", purchase, nil)
......
......@@ -22,16 +22,17 @@ type Transaction struct {
Total int `json:"total"`
Type string `json:"type"`
Purchase []Purchase `json:"purchase"`
Topup *Topup `json:"topup"`
Order []OrderPurchase `json:"order"`
Refund *Order `json:"refund"`
Purchase []Purchase `json:"purchase,omitempty"`
Topup *Topup `json:"topup,omitempty"`
OrderPurchase []OrderPurchase `json:"order_purchase,omitempty" gorm:"foreignKey:TransactionID"`
Order *Order `json:"order,omitempty"`
OrderID *uint `json:"-"`
Refund *Order `json:"refund,omitempty" gorm:"foreignKey:TransactionID"`
}
func (a *api) ListTransactions(w http.ResponseWriter, req *http.Request) {
var transactions []Transaction
err := a.db.Preload("Purchase.Product").
Preload(clause.Associations).
err := a.transactionQuery().
Order("date desc").
Find(&transactions).Error
if err != nil {
......@@ -51,8 +52,7 @@ func (a *api) ListTransactions(w http.ResponseWriter, req *http.Request) {
func (a *api) GetTransaction(num int, role string, w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
var transaction Transaction
err := a.db.Preload("Purchase.Product").
Preload(clause.Associations).
err := a.transactionQuery().
First(&transaction, vars["id"]).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
......@@ -87,9 +87,8 @@ func (a *api) GetMemberTransactions(w http.ResponseWriter, req *http.Request) {
func (a *api) getTransactionsByMember(num int, w http.ResponseWriter, req *http.Request) {
var transactions []Transaction
err := a.db.Where("member = ?", num).
Preload("Purchase.Product").
Preload(clause.Associations).
err := a.transactionQuery().
Where("member = ?", num).
Order("date desc").
Find(&transactions).Error
if err != nil {
......@@ -136,3 +135,10 @@ func createTransaction(db *gorm.DB, transaction *Transaction) (httpStatus int, e
})
return
}
func (a *api) transactionQuery() *gorm.DB {
return a.db.Preload("Purchase.Product").
Preload("Order.Products").
Preload("OrderPurchase.Product").
Preload(clause.Associations)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment