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:"-" 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"`
gorm.Model `json:"-"`
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"`
Ammount int `json:"ammount"`
type OrderGetResponse struct {
Order Order `json:"order"`
Transaction *Transaction `json:"transaction"`
}
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 _, purchase := range order.Purchases {
total += purchase.Price * purchase.Ammount
}
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
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) {
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 id IN (?)", num,
a.db.Table("order_purchases").
Where("order_id = ?", order.ID).
Select("transaction_id")).
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)
163
164
165
166
167
168
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
205
206
207
208
209
210
211
212
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 purchase []OrderPurchase
err := json.NewDecoder(req.Body).Decode(&purchase)
if err != nil {
log.Printf("Can't parse order: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if len(purchase) == 0 {
log.Printf("Empty order purchase")
w.WriteHeader(http.StatusBadRequest)
return
}
var order Order
err = a.db.Preload("Products").
First(&order, purchase[0].OrderID).Error
log.Printf("Can't get order %d: %v", purchase[0].OrderID, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if !order.Active {
log.Printf("Order is not active %d: %v", order.ID, purchase)
w.WriteHeader(http.StatusBadRequest)
return
}
total := 0
log.Printf("Order purchase product %d not in order: %v", p.ProductCode, purchase)
w.WriteHeader(http.StatusBadRequest)
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
return
}
}
transaction := Transaction{
MemberNum: num,
Total: -total,
Type: "order",
Date: time.Now(),
Order: purchase,
}
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
}
}