feat(charge):基本完成所有用户服务延期记录部分的功能,待测。
This commit is contained in:
parent
68c34f540f
commit
f033691aa4
|
@ -1,13 +1,17 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"electricity_bill_calc/model"
|
||||
"electricity_bill_calc/repository"
|
||||
"electricity_bill_calc/response"
|
||||
"electricity_bill_calc/security"
|
||||
"electricity_bill_calc/service"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type _ChargesController struct {
|
||||
|
@ -22,7 +26,8 @@ func InitializeChargesController(router *gin.Engine) {
|
|||
}
|
||||
|
||||
ChargesController.Router.GET("/charges", security.OPSAuthorize, listAllCharges)
|
||||
|
||||
ChargesController.Router.POST("/charge", security.OPSAuthorize, recordNewCharge)
|
||||
ChargesController.Router.PUT("/charge/:uid/:seq", security.OPSAuthorize, modifyChargeState)
|
||||
}
|
||||
|
||||
func listAllCharges(c *gin.Context) {
|
||||
|
@ -46,3 +51,55 @@ func listAllCharges(c *gin.Context) {
|
|||
gin.H{"records": charges},
|
||||
)
|
||||
}
|
||||
|
||||
type _NewChargeFormData struct {
|
||||
UserId string `json:"userId" form:"userId"`
|
||||
Fee decimal.NullDecimal `json:"fee" form:"fee"`
|
||||
Discount decimal.NullDecimal `json:"discount" form:"discount"`
|
||||
Amount decimal.NullDecimal `json:"amount" form:"amount"`
|
||||
ChargeTo time.Time `json:"chargeTo" form:"chargeTo" time_format:"simple_date" time_location:"shanghai"`
|
||||
}
|
||||
|
||||
func recordNewCharge(c *gin.Context) {
|
||||
result := response.NewResult(c)
|
||||
formData := new(_NewChargeFormData)
|
||||
c.BindJSON(formData)
|
||||
currentTime := time.Now()
|
||||
newRecord := &model.UserCharge{
|
||||
UserId: formData.UserId,
|
||||
Fee: formData.Fee,
|
||||
Discount: formData.Discount,
|
||||
Amount: formData.Amount,
|
||||
Settled: true,
|
||||
SettledAt: ¤tTime,
|
||||
ChargeTo: formData.ChargeTo,
|
||||
}
|
||||
err := service.ChargeService.CreateChargeRecord(newRecord, true)
|
||||
if err != nil {
|
||||
result.Error(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
result.Success("指定用户的服务已延期。")
|
||||
}
|
||||
|
||||
type _StateChangeFormData struct {
|
||||
Cancelled bool `json:"cancelled"`
|
||||
}
|
||||
|
||||
func modifyChargeState(c *gin.Context) {
|
||||
result := response.NewResult(c)
|
||||
formData := new(_StateChangeFormData)
|
||||
c.BindJSON(formData)
|
||||
requestUserID := c.Param("uid")
|
||||
requestChargeSeq, err := strconv.Atoi(c.Param("seq"))
|
||||
if err != nil {
|
||||
result.Error(http.StatusNotAcceptable, "参数[记录流水号]解析错误。")
|
||||
return
|
||||
}
|
||||
err = service.ChargeService.CancelCharge(int64(requestChargeSeq), requestUserID)
|
||||
if err != nil {
|
||||
result.Error(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
result.Success("指定用户服务延期记录状态已经更新。")
|
||||
}
|
||||
|
|
|
@ -8,13 +8,16 @@ import (
|
|||
|
||||
type UserCharge struct {
|
||||
Created `xorm:"extends"`
|
||||
Seq int64 `xorm:"bigint pk not null " json:"seq"`
|
||||
Seq int64 `xorm:"bigint pk not null autoincr" json:"seq"`
|
||||
UserId string `xorm:"varchar(120) not null" json:"userId"`
|
||||
Fee decimal.Decimal `xorm:"numeric(12,2) not null" json:"fee"`
|
||||
Discount decimal.Decimal `xorm:"numeric(5,4) not null" json:"discount"`
|
||||
Amount decimal.Decimal `xorm:"numeric(12,2) not null" json:"amount"`
|
||||
Fee decimal.NullDecimal `xorm:"numeric(12,2)" json:"fee"`
|
||||
Discount decimal.NullDecimal `xorm:"numeric(5,4)" json:"discount"`
|
||||
Amount decimal.NullDecimal `xorm:"numeric(12,2)" json:"amount"`
|
||||
ChargeTo time.Time `xorm:"date not null" json:"chargeTo" time_format:"simple_date" time_location:"shanghai"`
|
||||
Settled bool `xorm:"bool not null default false" json:"settled"`
|
||||
SettledAt *time.Time `xorm:"timestampz" json:"settledAt" time_format:"simple_datetime" time_location:"shanghai"`
|
||||
Cancelled bool `xorm:"bool not null default false" json:"cancelled"`
|
||||
CancelledAt *time.Time `xorm:"timestampz" json:"cancelledAt" time_format:"simple_datetime" time_location:"shanghai"`
|
||||
Refunded bool `xorm:"bool not null default false" json:"refunded"`
|
||||
RefundedAt *time.Time `xorm:"timestampz" json:"refundedAt" time_format:"simple_datetime" time_location:"shanghai"`
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"electricity_bill_calc/config"
|
||||
"electricity_bill_calc/global"
|
||||
"electricity_bill_calc/model"
|
||||
"electricity_bill_calc/utils"
|
||||
"time"
|
||||
|
||||
"xorm.io/builder"
|
||||
|
@ -50,3 +51,20 @@ func (_ChargeRepository) ListPagedChargeRecord(keyword, beginDate, endDate strin
|
|||
Find(&charges)
|
||||
return charges, total, err
|
||||
}
|
||||
|
||||
func (_ChargeRepository) LastValidChargeTo(uid string) (time.Time, error) {
|
||||
veryBlankTime, _ := time.Parse("2006-01-02 15:04:05", "0001-01-01 00:00:00")
|
||||
var records = make([]time.Time, 0)
|
||||
err := global.DBConn.Where(builder.Eq{"settled": true, "cancelled": false, "refunded": false}).Cols("charged_to").Find(&records)
|
||||
if err != nil {
|
||||
return veryBlankTime, nil
|
||||
}
|
||||
lastValid := utils.Reduce(records, veryBlankTime, func(acc, elem time.Time) time.Time {
|
||||
if elem.After(acc) {
|
||||
return elem
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
})
|
||||
return lastValid, nil
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ func Router() *gin.Engine {
|
|||
|
||||
controller.InitializeUserController(router)
|
||||
controller.InitializeRegionController(router)
|
||||
controller.InitializeChargesController(router)
|
||||
|
||||
return router
|
||||
}
|
||||
|
|
|
@ -1,5 +1,147 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"electricity_bill_calc/exceptions"
|
||||
"electricity_bill_calc/global"
|
||||
"electricity_bill_calc/model"
|
||||
"electricity_bill_calc/repository"
|
||||
"time"
|
||||
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type _ChargeService struct{}
|
||||
|
||||
var ChargeService _ChargeService
|
||||
|
||||
func (c _ChargeService) CreateChargeRecord(charge *model.UserCharge, extendWithIgnoreSettle bool) error {
|
||||
tx := global.DBConn.NewSession()
|
||||
defer tx.Close()
|
||||
if err := tx.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := tx.Insert(charge)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
if extendWithIgnoreSettle {
|
||||
err := c.updateUserExpiration(tx, charge.UserId, charge.ChargeTo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c _ChargeService) SettleCharge(seq int64, uid string) error {
|
||||
var record *model.UserCharge
|
||||
has, err := global.DBConn.Where(builder.Eq{"seq": seq, "user_id": uid}).NoAutoCondition().Get(record)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if !has {
|
||||
return exceptions.NewNotFoundError("未找到匹配指定条件的计费记录。")
|
||||
}
|
||||
tx := global.DBConn.NewSession()
|
||||
defer tx.Close()
|
||||
if err := tx.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
currentTime := time.Now()
|
||||
_, err = tx.Table(new(model.UserCharge)).Where(builder.Eq{"seq": seq, "user_id": uid}).Cols("settled", "settled_at").Update(&model.UserCharge{Settled: true, SettledAt: ¤tTime})
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
err = c.updateUserExpiration(tx, uid, record.ChargeTo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c _ChargeService) RefundCharge(seq int64, uid string) error {
|
||||
tx := global.DBConn.NewSession()
|
||||
defer tx.Close()
|
||||
if err := tx.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
currentTime := time.Now()
|
||||
rows, err := tx.Table(new(model.UserCharge)).Where(builder.Eq{"seq": seq, "user_id": uid}).Cols("refunded", "refunded_at").Update(&model.UserCharge{Refunded: true, RefundedAt: ¤tTime})
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
if rows == 0 {
|
||||
tx.Rollback()
|
||||
return exceptions.NewNotFoundError("未找到匹配指定条件的计费记录。")
|
||||
}
|
||||
lastValidExpriation, err := repository.ChargeRepo.LastValidChargeTo(uid)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return exceptions.NewNotFoundError("未找到最后合法的计费时间。")
|
||||
}
|
||||
err = c.updateUserExpiration(tx, uid, lastValidExpriation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c _ChargeService) CancelCharge(seq int64, uid string) error {
|
||||
tx := global.DBConn.NewSession()
|
||||
defer tx.Close()
|
||||
if err := tx.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
currentTime := time.Now()
|
||||
rows, err := tx.Table(new(model.UserCharge)).Where(builder.Eq{"seq": seq, "user_id": uid}).Cols("cancelled", "cancelled_at").Update(&model.UserCharge{Cancelled: true, CancelledAt: ¤tTime})
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
if rows == 0 {
|
||||
tx.Rollback()
|
||||
return exceptions.NewNotFoundError("未找到匹配指定条件的计费记录。")
|
||||
}
|
||||
lastValidExpriation, err := repository.ChargeRepo.LastValidChargeTo(uid)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return exceptions.NewNotFoundError("未找到最后合法的计费时间。")
|
||||
}
|
||||
err = c.updateUserExpiration(tx, uid, lastValidExpriation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_ChargeService) updateUserExpiration(tx *xorm.Session, uid string, expiration time.Time) error {
|
||||
_, err := tx.ID(uid).Cols("service_expiration").Update(&model.UserDetail{ServiceExpiration: expiration})
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user