Newer
Older
"log"
"net/http"
"time"
"github.com/gorilla/mux"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type Order struct {
gorm.Model
Name string `json:"name"`
Description string `json:"description"`
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"`
Transactions []Transaction `json:"transactions" gorm:"foreignKey:OrderID"`
TransactionID *uint `json:"-" gorm:"column:transaction"`
gorm.Model `json:"-"`
TransactionID uint `json:"-"`
ProductCode int `json:"product_code"`
Product *Product `json:"product" gorm:"foreignKey:ProductCode;references:Code"`
Price int `json:"price"`
type OrderGetResponse struct {
Order Order `json:"order"`
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 {
time.Sleep(refundSleeptime)
a.deactivateOrders()
}
}
func (a *api) deactivateOrders() {
var orders []Order
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).
Find(&orders).Error
if err != nil {
log.Println("Error refunding orders:", err)
return
}
for _, order := range orders {
total := 0
for _, transaction := range order.Transactions {
for _, purchase := range transaction.OrderPurchase {
total += purchase.Price * purchase.Amount
}
}
transaction := Transaction{
MemberNum: order.MemberNum,
Date: time.Now(),
Type: "refund",
Total: total,
}
err = a.db.Transaction(func(tx *gorm.DB) error {
_, err := createTransaction(tx, &transaction)
if err != nil {
return err
}
return tx.Model(&Order{}).
Where("id = ?", order.ID).
Updates(map[string]interface{}{
"active": false,
"transaction": transaction.ID}).
Error
})
if err != nil {
log.Printf("Can't create refund: %v\n%v", err, order)
continue
}
log.Println("Refund order", order.Name, total)
}
}
func (a *api) ListOrders(w http.ResponseWriter, req *http.Request) {
a.listOrders(false, w, req)
}
func (a *api) ListActiveOrders(w http.ResponseWriter, req *http.Request) {
a.listOrders(true, w, req)
}
func (a *api) listOrders(active bool, w http.ResponseWriter, req *http.Request) {
var orders []Order
query := a.db.Preload(clause.Associations).
Preload("Transactions.OrderPurchase")
if active {
query = query.Where("active = ?", true)
}
err := query.Order("deadline desc").
Find(&orders).Error
if err != nil {
log.Printf("Can't list orders: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
err = json.NewEncoder(w).Encode(orders)
if err != nil {
log.Printf("Can't encode orders: %v", err)
w.WriteHeader(http.StatusInternalServerError)
}
}
func (a *api) GetOrder(num int, w http.ResponseWriter, req *http.Request) {
Preload("Transactions.OrderPurchase").
Preload("Transactions.Member").
if errors.Is(err, gorm.ErrRecordNotFound) {
w.WriteHeader(http.StatusNotFound)
return
}
log.Printf("Can't get order %s: %v", vars["id"], err)
w.WriteHeader(http.StatusInternalServerError)
return
}
body.Order = order
var transaction Transaction
err = a.db.Where("member = ? AND type = 'order' AND order_id = ?", num, vars["id"]).
Preload("OrderPurchase.Product").
log.Printf("Can't get order transaction %s: %v", vars["id"], err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if transaction.ID != 0 {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
if err != nil {
log.Printf("Can't encode order: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
}
func (a *api) AddOrder(num int, w http.ResponseWriter, req *http.Request) {
var order Order
err := json.NewDecoder(req.Body).Decode(&order)
if err != nil {
log.Printf("Can't parse order: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
order.MemberNum = num
order.Active = true
err = a.db.Create(&order).Error
if err != nil {
log.Printf("Can't create order: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
err = json.NewEncoder(w).Encode(order)
if err != nil {
log.Printf("Can't encode order: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
}
func (a *api) AddOrderPurchase(num int, w http.ResponseWriter, req *http.Request) {
var request OrderPurchaseRequest
err := json.NewDecoder(req.Body).Decode(&request)
log.Printf("Empty order purchase")
w.WriteHeader(http.StatusBadRequest)
return
}
var order Order
Preload("Transactions").
First(&order, request.OrderID).Error
log.Printf("Can't get order %d: %v", request.OrderID, err)
log.Printf("Order is not active %d: %v", order.ID, request)
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
}
}
log.Printf("Order purchase product %d not in order: %v", p.ProductCode, request)
MemberNum: num,
Total: -total,
Type: "order",
Date: time.Now(),
OrderPurchase: request.Purchase,
OrderID: &order.ID,
}
httpStatus, err := createTransaction(a.db, &transaction)
if err != nil {
log.Println(err)
w.WriteHeader(httpStatus)
return
}
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 order transaction: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
}