Newer
Older
"log"
"net/http"
"strconv"
"time"
"github.com/gorilla/mux"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type Transaction struct {
gorm.Model
MemberNum int `json:"-" gorm:"column:member"`
Member *Member `json:"member,omitempty" gorm:"foreignKey:MemberNum;references:Num"`
Date time.Time `json:"date"`
Total int `json:"total"`
Type string `json:"type"`
Purchase []Purchase `json:"purchase"`
Topup *Topup `json:"topup"`
Order []OrderPurchase `json:"order"`
Refund *Order `json:"refund"`
}
func (a *api) ListTransactions(w http.ResponseWriter, req *http.Request) {
var transactions []Transaction
err := a.db.Preload("Purchase.Product").
Preload(clause.Associations).
Find(&transactions).Error
if err != nil {
log.Printf("Can't list transactions: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
err = json.NewEncoder(w).Encode(transactions)
if err != nil {
log.Printf("Can't encode transactions: %v", err)
w.WriteHeader(http.StatusInternalServerError)
}
}
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).
First(&transaction, vars["id"]).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
log.Printf("Can't get transaction %s: %v", vars["id"], err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if transaction.MemberNum != num && role != "admin" {
w.WriteHeader(http.StatusUnauthorized)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
err = json.NewEncoder(w).Encode(transaction)
if err != nil {
log.Printf("Can't encode transaction: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
}
func (a *api) GetMemberTransactions(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req)
num, _ := strconv.Atoi(vars["num"])
a.getTransactionsByMember(num, w, req)
}
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).
Find(&transactions).Error
if err != nil {
log.Printf("Can't list transactions: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
err = json.NewEncoder(w).Encode(transactions)
if err != nil {
log.Printf("Can't encode transactions: %v", err)
w.WriteHeader(http.StatusInternalServerError)
}
}
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
func createTransaction(db *gorm.DB, transaction *Transaction) (httpStatus int, err error) {
httpStatus = http.StatusOK
err = db.Transaction(func(tx *gorm.DB) error {
var member Member
err := tx.Where("num = ?", transaction.MemberNum).Find(&member).Error
if err != nil {
httpStatus = http.StatusNotAcceptable
return fmt.Errorf("Can't find member %d: %v", transaction.MemberNum, err)
}
if member.Balance < -transaction.Total {
httpStatus = http.StatusBadRequest
return fmt.Errorf("Member %d don't have enough money (%d-%d)", member.Num, member.Balance, transaction.Total)
}
err = tx.Model(&Member{}).
Where("num = ?", transaction.MemberNum).
Update("balance", gorm.Expr("balance + ?", transaction.Total)).Error
if err != nil {
httpStatus = http.StatusNotAcceptable
fmt.Errorf("Can't update update member balance %d-%d: %v", member.Num, transaction.Total, err)
}
err = tx.Create(&transaction).Error
if err != nil {
httpStatus = http.StatusInternalServerError
return fmt.Errorf("Can't create transaction: %v\n%v", err, transaction)
}
return nil
})
return