2026-07-30 14:16:58 +08:00
|
|
|
|
package delivery
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"bytes"
|
|
|
|
|
|
"encoding/json"
|
|
|
|
|
|
"errors"
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"io"
|
|
|
|
|
|
"math"
|
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
|
"git.apinb.com/bsm-sdk/core/errcode"
|
|
|
|
|
|
"git.apinb.com/bsm-sdk/core/infra"
|
|
|
|
|
|
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
|
|
|
|
|
platformgasorder "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/platform/gasorder"
|
|
|
|
|
|
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
|
"gorm.io/gorm"
|
|
|
|
|
|
"gorm.io/gorm/clause"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
func rewriteJSON(ctx *gin.Context, mutate func(map[string]any) bool) bool {
|
|
|
|
|
|
body, err := io.ReadAll(ctx.Request.Body)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
var values map[string]any
|
|
|
|
|
|
if json.Unmarshal(body, &values) != nil || !mutate(values) {
|
|
|
|
|
|
if !ctx.IsAborted() {
|
|
|
|
|
|
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
|
|
|
|
|
}
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
body, _ = json.Marshal(values)
|
|
|
|
|
|
ctx.Request.Body = io.NopCloser(bytes.NewReader(body))
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func scopedContract(ctx *gin.Context, identity string, pointID uint64) (models.GasorderContract, bool) {
|
|
|
|
|
|
var contract models.GasorderContract
|
|
|
|
|
|
if err := common.ActiveRecords(db()).Where("identity = ? AND delivery_basic_id = ?", identity, pointID).First(&contract).Error; err != nil {
|
|
|
|
|
|
common.RespondRecordError(ctx, err)
|
|
|
|
|
|
return contract, false
|
|
|
|
|
|
}
|
|
|
|
|
|
return contract, true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func ListContract(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if ok {
|
|
|
|
|
|
listScoped(ctx, &models.GasorderContract{}, common.ActiveRecords(db().Model(&models.GasorderContract{})).
|
|
|
|
|
|
Where("gas_basic_id = ? AND delivery_basic_id = ?", point.GasBasicID, point.ID), "gasorder_contract.created_at desc")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func GetContract(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if ok {
|
|
|
|
|
|
if _, valid := scopedContract(ctx, ctx.Param("identity"), point.ID); valid {
|
|
|
|
|
|
platformgasorder.GetGasorderContract(ctx)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func CreateContract(ctx *gin.Context) {
|
|
|
|
|
|
point, station, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if !rewriteJSON(ctx, func(values map[string]any) bool {
|
|
|
|
|
|
userIdentity, _ := values["user_account_identity"].(string)
|
|
|
|
|
|
if _, _, valid := scopedUser(ctx, userIdentity, point.ID); !valid {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
values["gas_basic_identity"] = station.Identity
|
|
|
|
|
|
values["delivery_basic_identity"] = point.Identity
|
|
|
|
|
|
return true
|
|
|
|
|
|
}) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
platformgasorder.CreateGasorderContract(ctx)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func withContract(ctx *gin.Context, handler gin.HandlerFunc) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if ok {
|
|
|
|
|
|
if _, valid := scopedContract(ctx, ctx.Param("identity"), point.ID); valid {
|
|
|
|
|
|
handler(ctx)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func UpdateContract(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if _, valid := scopedContract(ctx, ctx.Param("identity"), point.ID); !valid {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if !rewriteJSON(ctx, func(values map[string]any) bool {
|
|
|
|
|
|
values["delivery_basic_identity"] = point.Identity
|
|
|
|
|
|
return true
|
|
|
|
|
|
}) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
platformgasorder.UpdateGasorderContract(ctx)
|
|
|
|
|
|
}
|
|
|
|
|
|
func ActivateContract(ctx *gin.Context) { withContract(ctx, platformgasorder.ActivateGasorderContract) }
|
|
|
|
|
|
func RenewContract(ctx *gin.Context) { withContract(ctx, platformgasorder.RenewGasorderContract) }
|
|
|
|
|
|
func TerminateContract(ctx *gin.Context) {
|
|
|
|
|
|
withContract(ctx, platformgasorder.TerminateGasorderContract)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func ListContractProduct(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
query := common.ActiveRecords(db().Model(&models.GasorderContractProduct{})).
|
|
|
|
|
|
Joins("JOIN gasorder_contract ON gasorder_contract.id = gasorder_contract_product.gasorder_contract_id").
|
|
|
|
|
|
Where("gasorder_contract.delivery_basic_id = ?", point.ID)
|
|
|
|
|
|
listScoped(ctx, &models.GasorderContractProduct{}, query, "gasorder_contract_product.created_at desc")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func GetContractProduct(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
var item models.GasorderContractProduct
|
|
|
|
|
|
query := common.ActiveRecords(db().Model(&models.GasorderContractProduct{})).
|
|
|
|
|
|
Select("gasorder_contract_product.*").
|
|
|
|
|
|
Joins("JOIN gasorder_contract ON gasorder_contract.id = gasorder_contract_product.gasorder_contract_id").
|
|
|
|
|
|
Where("gasorder_contract_product.identity = ? AND gasorder_contract.delivery_basic_id = ?", ctx.Param("identity"), point.ID)
|
|
|
|
|
|
respondRecord(ctx, query, &item)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func BindContractProduct(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if !rewriteJSON(ctx, func(values map[string]any) bool {
|
|
|
|
|
|
identity, _ := values["gasorder_contract_identity"].(string)
|
|
|
|
|
|
_, valid := scopedContract(ctx, identity, point.ID)
|
|
|
|
|
|
return valid
|
|
|
|
|
|
}) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
platformgasorder.BindGasorderContractProduct(ctx)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func UnbindContractProduct(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
var count int64
|
|
|
|
|
|
err := db().Model(&models.GasorderContractProduct{}).
|
|
|
|
|
|
Joins("JOIN gasorder_contract ON gasorder_contract.id = gasorder_contract_product.gasorder_contract_id").
|
|
|
|
|
|
Where("gasorder_contract_product.identity = ? AND gasorder_contract.delivery_basic_id = ?", ctx.Param("identity"), point.ID).
|
|
|
|
|
|
Count(&count).Error
|
|
|
|
|
|
if err != nil || count != 1 {
|
|
|
|
|
|
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
platformgasorder.UnbindGasorderContractProduct(ctx)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func ListContractRevision(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
query := common.ActiveRecords(db().Model(&models.GasorderContractRevision{})).
|
|
|
|
|
|
Joins("JOIN gasorder_contract ON gasorder_contract.id = gasorder_contract_revision.gasorder_contract_id").
|
|
|
|
|
|
Where("gasorder_contract.delivery_basic_id = ?", point.ID)
|
|
|
|
|
|
listScoped(ctx, &models.GasorderContractRevision{}, query, "gasorder_contract_revision.created_at desc")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func GetContractRevision(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
var item models.GasorderContractRevision
|
|
|
|
|
|
query := common.ActiveRecords(db().Model(&models.GasorderContractRevision{})).
|
|
|
|
|
|
Select("gasorder_contract_revision.*").
|
|
|
|
|
|
Joins("JOIN gasorder_contract ON gasorder_contract.id = gasorder_contract_revision.gasorder_contract_id").
|
|
|
|
|
|
Where("gasorder_contract_revision.identity = ? AND gasorder_contract.delivery_basic_id = ?", ctx.Param("identity"), point.ID)
|
|
|
|
|
|
respondRecord(ctx, query, &item)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func ListProductCandidate(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
query := common.ActiveRecords(db().Model(&models.ProductInfo{})).
|
|
|
|
|
|
Joins("JOIN user_service_relation ON user_service_relation.user_account_id = product_info.user_account_id AND user_service_relation.status <> ?",
|
|
|
|
|
|
common.StatusArchived).Where("user_service_relation.delivery_basic_id = ?", point.ID)
|
|
|
|
|
|
listScoped(ctx, &models.ProductInfo{}, query, "product_info.created_at desc")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func GetProductCandidate(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
var item models.ProductInfo
|
|
|
|
|
|
query := common.ActiveRecords(db().Model(&models.ProductInfo{})).
|
|
|
|
|
|
Select("product_info.*").
|
|
|
|
|
|
Joins("JOIN user_service_relation ON user_service_relation.user_account_id = product_info.user_account_id AND user_service_relation.status <> ?",
|
|
|
|
|
|
common.StatusArchived).
|
|
|
|
|
|
Where("product_info.identity = ? AND user_service_relation.delivery_basic_id = ?", ctx.Param("identity"), point.ID)
|
|
|
|
|
|
respondRecord(ctx, query, &item)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func scopedOrder(ctx *gin.Context, identity string, pointID uint64) (models.GasorderBasic, bool) {
|
|
|
|
|
|
var order models.GasorderBasic
|
|
|
|
|
|
if err := common.ActiveRecords(db()).Where("identity = ? AND delivery_basic_id = ?", identity, pointID).First(&order).Error; err != nil {
|
|
|
|
|
|
common.RespondRecordError(ctx, err)
|
|
|
|
|
|
return order, false
|
|
|
|
|
|
}
|
|
|
|
|
|
return order, true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func ListOrder(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if ok {
|
|
|
|
|
|
listScoped(ctx, &models.GasorderBasic{}, common.ActiveRecords(db().Model(&models.GasorderBasic{})).
|
|
|
|
|
|
Where("delivery_basic_id = ?", point.ID), "gasorder_basic.created_at desc")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func GetOrder(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if ok {
|
|
|
|
|
|
if _, valid := scopedOrder(ctx, ctx.Param("identity"), point.ID); valid {
|
|
|
|
|
|
platformgasorder.GetGasorderBasic(ctx)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func CreateOrder(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if !rewriteJSON(ctx, func(values map[string]any) bool {
|
|
|
|
|
|
identity, _ := values["gasorder_contract_identity"].(string)
|
|
|
|
|
|
if _, valid := scopedContract(ctx, identity, point.ID); !valid {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
values["creator_type"] = "delivery"
|
|
|
|
|
|
values["creator_identity"] = point.Identity
|
|
|
|
|
|
return true
|
|
|
|
|
|
}) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
platformgasorder.CreateGasorderBasic(ctx)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func AssignOrder(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if _, valid := scopedOrder(ctx, ctx.Param("identity"), point.ID); !valid {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if !rewriteJSON(ctx, func(values map[string]any) bool {
|
|
|
|
|
|
staffIdentity, _ := values["staff_account_identity"].(string)
|
|
|
|
|
|
staff, valid := scopedStaff(ctx, staffIdentity, point)
|
|
|
|
|
|
if !valid || staff.WorkStatus != "on_duty" || staff.Status != common.StatusEnable {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
var credentialCount int64
|
|
|
|
|
|
err := common.ActiveRecords(db().Model(&models.StaffCredential{})).
|
|
|
|
|
|
Where("staff_account_id = ? AND (expired_at IS NULL OR expired_at > ?)", staff.ID, time.Now()).
|
|
|
|
|
|
Count(&credentialCount).Error
|
|
|
|
|
|
if err != nil || credentialCount == 0 {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
values["delivery_basic_identity"] = point.Identity
|
|
|
|
|
|
return true
|
|
|
|
|
|
}) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
platformgasorder.AssignGasorderBasic(ctx)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func withOrder(ctx *gin.Context, handler gin.HandlerFunc) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if ok {
|
|
|
|
|
|
if _, valid := scopedOrder(ctx, ctx.Param("identity"), point.ID); valid {
|
|
|
|
|
|
handler(ctx)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func OrderException(ctx *gin.Context) { withOrder(ctx, platformgasorder.GasorderException) }
|
|
|
|
|
|
func OrderRecover(ctx *gin.Context) { withOrder(ctx, platformgasorder.GasorderRecover) }
|
|
|
|
|
|
func OrderCancel(ctx *gin.Context) { withOrder(ctx, platformgasorder.GasorderCancel) }
|
|
|
|
|
|
|
|
|
|
|
|
func ReclaimOrder(ctx *gin.Context) {
|
|
|
|
|
|
account, point, _, ok := CurrentDeliveryAccount(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
var request struct {
|
|
|
|
|
|
Reason string `json:"reason" binding:"required,max=1000"`
|
|
|
|
|
|
}
|
|
|
|
|
|
if err := ctx.ShouldBindJSON(&request); err != nil {
|
|
|
|
|
|
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
err := db().Transaction(func(tx *gorm.DB) error {
|
|
|
|
|
|
var order models.GasorderBasic
|
|
|
|
|
|
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
|
|
|
|
|
|
Where("identity = ? AND delivery_basic_id = ?", ctx.Param("identity"), point.ID).First(&order).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
if order.OrderStatus != common.StatusAssigned {
|
|
|
|
|
|
return errors.New("only assigned order can be reclaimed")
|
|
|
|
|
|
}
|
|
|
|
|
|
if err := tx.Model(&order).Updates(map[string]any{
|
|
|
|
|
|
"staff_account_id": 0, "order_status": common.StatusCreated,
|
|
|
|
|
|
}).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
return tx.Create(&models.GasorderStatus{
|
|
|
|
|
|
Entity: common.NewEntity(common.StatusEnable), GasorderBasicID: order.ID,
|
|
|
|
|
|
FromStatus: common.StatusAssigned, ToStatus: common.StatusCreated,
|
|
|
|
|
|
OperatorIdentity: account.Identity, OperatorName: account.DisplayName,
|
|
|
|
|
|
OccurredAt: time.Now(), Reason: request.Reason,
|
|
|
|
|
|
}).Error
|
|
|
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
infra.Response.Success(ctx, gin.H{"updated": true, "order_status": common.StatusCreated})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func AdjustOrderAmount(ctx *gin.Context) {
|
|
|
|
|
|
point, _, ok := currentScope(ctx)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
var request struct {
|
|
|
|
|
|
DeliveryFee int64 `json:"delivery_fee"`
|
|
|
|
|
|
DiscountAmount int64 `json:"discount_amount"`
|
|
|
|
|
|
Reason string `json:"reason" binding:"required,max=1000"`
|
|
|
|
|
|
}
|
|
|
|
|
|
if err := ctx.ShouldBindJSON(&request); err != nil || request.DeliveryFee < 0 || request.DiscountAmount < 0 {
|
|
|
|
|
|
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
account, _, _, _ := CurrentDeliveryAccount(ctx)
|
|
|
|
|
|
err := db().Transaction(func(tx *gorm.DB) error {
|
|
|
|
|
|
var order models.GasorderBasic
|
|
|
|
|
|
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
|
|
|
|
|
|
Where("identity = ? AND delivery_basic_id = ?", ctx.Param("identity"), point.ID).First(&order).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
if order.OrderStatus != common.StatusCreated && order.OrderStatus != common.StatusAssigned {
|
|
|
|
|
|
return errors.New("order amount cannot be adjusted")
|
|
|
|
|
|
}
|
|
|
|
|
|
var paymentCount int64
|
|
|
|
|
|
if err := tx.Model(&models.GasorderPayment{}).
|
2026-08-02 23:24:32 +08:00
|
|
|
|
Joins("JOIN payment_order ON payment_order.id = gasorder_payment.payment_order_id").
|
|
|
|
|
|
Where("gasorder_payment.gasorder_basic_id = ? AND payment_order.payment_status = ?", order.ID, 23).
|
2026-07-30 14:16:58 +08:00
|
|
|
|
Count(&paymentCount).Error; err != nil || paymentCount > 0 {
|
|
|
|
|
|
return errors.New("paid order cannot be adjusted")
|
|
|
|
|
|
}
|
|
|
|
|
|
if order.ProductAmount > math.MaxInt64-request.DeliveryFee {
|
|
|
|
|
|
return errors.New("payable amount overflow")
|
|
|
|
|
|
}
|
|
|
|
|
|
payable := order.ProductAmount + request.DeliveryFee - request.DiscountAmount
|
|
|
|
|
|
if payable <= 0 {
|
|
|
|
|
|
return errors.New("payable amount must be positive")
|
|
|
|
|
|
}
|
|
|
|
|
|
if err := tx.Model(&order).Updates(map[string]any{
|
|
|
|
|
|
"delivery_fee": request.DeliveryFee, "discount_amount": request.DiscountAmount, "payable_amount": payable,
|
|
|
|
|
|
}).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
record := models.GasorderStatus{
|
|
|
|
|
|
Entity: common.NewEntity(common.StatusEnable), GasorderBasicID: order.ID,
|
|
|
|
|
|
FromStatus: order.OrderStatus, ToStatus: order.OrderStatus,
|
|
|
|
|
|
OperatorIdentity: account.Identity, OperatorName: account.DisplayName, OccurredAt: time.Now(),
|
|
|
|
|
|
Reason: fmt.Sprintf("%s;配送费 %d→%d,优惠金额 %d→%d,应付金额 %d→%d",
|
|
|
|
|
|
request.Reason, order.DeliveryFee, request.DeliveryFee, order.DiscountAmount, request.DiscountAmount,
|
|
|
|
|
|
order.PayableAmount, payable),
|
|
|
|
|
|
}
|
|
|
|
|
|
return tx.Create(&record).Error
|
|
|
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
infra.Response.Success(ctx, gin.H{"updated": true})
|
|
|
|
|
|
}
|