fix(wallet): enforce consistent withdrawal accounting
This commit is contained in:
@@ -7,8 +7,7 @@ import (
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
clientcommon "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/client/common"
|
||||
base "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
||||
common "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
@@ -16,21 +15,21 @@ import (
|
||||
|
||||
// ListAddresses 返回当前用户未归档地址。
|
||||
func ListAddresses(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var list []models.UserAddress
|
||||
if err := impl.DBService.Where("user_account_id = ? AND status <> ?", account.ID, base.StatusArchived).Order("is_default desc, created_at desc").Find(&list).Error; err != nil {
|
||||
if err := impl.DBService.Where("user_account_id = ? AND status <> ?", account.ID, common.StatusArchived).Order("is_default desc, created_at desc").Find(&list).Error; err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, base.ResourceResponse(list))
|
||||
infra.Response.Success(ctx, common.ResourceResponse(list))
|
||||
}
|
||||
|
||||
// SaveAddress 新增地址,设为默认时原默认地址会在同一事务取消默认。
|
||||
func SaveAddress(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -45,7 +44,7 @@ func SaveAddress(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
address := models.UserAddress{
|
||||
Entity: base.NewEntity(base.StatusEnable), UserAccountID: account.ID, Address: request.Address,
|
||||
Entity: common.NewEntity(common.StatusEnable), UserAccountID: account.ID, Address: request.Address,
|
||||
Longitude: request.Longitude, Latitude: request.Latitude, IsDefault: request.IsDefault,
|
||||
}
|
||||
err := impl.DBService.Transaction(func(tx *gorm.DB) error {
|
||||
@@ -69,7 +68,7 @@ var userTicketCategories = map[string]bool{
|
||||
|
||||
// CreateTicket 创建工单,服务人员只能由后台分派。
|
||||
func CreateTicket(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -85,18 +84,18 @@ func CreateTicket(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
var relation models.UserServiceRelation
|
||||
_ = impl.DBService.Where("user_account_id = ? AND status = ?", account.ID, base.StatusEnable).First(&relation).Error
|
||||
_ = impl.DBService.Where("user_account_id = ? AND status = ?", account.ID, common.StatusEnable).First(&relation).Error
|
||||
addressText := ""
|
||||
if request.AddressIdentity != "" {
|
||||
var address models.UserAddress
|
||||
if impl.DBService.Where("identity = ? AND user_account_id = ? AND status <> ?", request.AddressIdentity, account.ID, base.StatusArchived).First(&address).Error != nil {
|
||||
if impl.DBService.Where("identity = ? AND user_account_id = ? AND status <> ?", request.AddressIdentity, account.ID, common.StatusArchived).First(&address).Error != nil {
|
||||
infra.Response.Error(ctx, errcode.ErrRecordNotFound)
|
||||
return
|
||||
}
|
||||
addressText = address.Address
|
||||
}
|
||||
ticket := models.CsTicket{
|
||||
Entity: base.NewEntity(base.StatusEnable), TicketStatus: 32, TicketNo: clientcommon.RecordNo("TK"),
|
||||
Entity: common.NewEntity(common.StatusEnable), TicketStatus: 32, TicketNo: common.RecordNo("TK"),
|
||||
RequestNo: request.RequestNo,
|
||||
UserAccountID: account.ID, GasBasicID: relation.GasBasicID, DeliveryBasicID: relation.DeliveryBasicID,
|
||||
Category: request.Category, Priority: "normal", Description: strings.TrimSpace(request.Description),
|
||||
@@ -111,21 +110,21 @@ func CreateTicket(ctx *gin.Context) {
|
||||
|
||||
// ListTickets 仅返回当前用户自己的工单。
|
||||
func ListTickets(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var list []models.CsTicket
|
||||
if err := impl.DBService.Where("user_account_id = ? AND status <> ?", account.ID, base.StatusArchived).Order("created_at desc").Find(&list).Error; err != nil {
|
||||
if err := impl.DBService.Where("user_account_id = ? AND status <> ?", account.ID, common.StatusArchived).Order("created_at desc").Find(&list).Error; err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, base.ResourceResponse(list))
|
||||
infra.Response.Success(ctx, common.ResourceResponse(list))
|
||||
}
|
||||
|
||||
// ConfirmTicket 用户确认工作人员提交的处理结果。
|
||||
func ConfirmTicket(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -146,7 +145,7 @@ func ConfirmTicket(ctx *gin.Context) {
|
||||
|
||||
// CancelTicket 取消尚未完成的本人工单。
|
||||
func CancelTicket(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ import (
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
clientcommon "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/client/common"
|
||||
base "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
||||
common "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@@ -26,24 +25,24 @@ type loginRequest struct {
|
||||
// Login 支持密码和一次性验证码两种登录模式。
|
||||
func Login(ctx *gin.Context) {
|
||||
var request loginRequest
|
||||
if ctx.ShouldBindJSON(&request) != nil || !clientcommon.ValidPhone(request.Phone) {
|
||||
if ctx.ShouldBindJSON(&request) != nil || !common.ValidPhone(request.Phone) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
var account models.UserAccount
|
||||
if impl.DBService.Where("phone = ? AND status = ?", strings.TrimSpace(request.Phone), base.StatusEnable).First(&account).Error != nil {
|
||||
if impl.DBService.Where("phone = ? AND status = ?", strings.TrimSpace(request.Phone), common.StatusEnable).First(&account).Error != nil {
|
||||
infra.Response.Error(ctx, errcode.ErrPassword)
|
||||
return
|
||||
}
|
||||
valid := request.Mode == "password" && bcrypt.CompareHashAndPassword([]byte(account.PasswordHash), []byte(request.Password)) == nil
|
||||
if request.Mode == "verification_code" {
|
||||
valid = clientcommon.VerifyCode("user_app", account.Phone, "login", request.RequestIdentity, request.Code)
|
||||
valid = common.VerifyCode("user_app", account.Phone, "login", request.RequestIdentity, request.Code)
|
||||
}
|
||||
if !valid {
|
||||
infra.Response.Error(ctx, errcode.ErrPassword)
|
||||
return
|
||||
}
|
||||
accessToken, err := clientcommon.IssueToken(account.Identity, "user_app", "user", map[string]string{"phone": account.Phone})
|
||||
accessToken, err := common.IssueToken(account.Identity, "user_app", "user", map[string]string{"phone": account.Phone})
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
@@ -65,19 +64,19 @@ func Register(ctx *gin.Context) {
|
||||
Code string `json:"code" binding:"required"`
|
||||
RequestIdentity string `json:"request_identity" binding:"required"`
|
||||
}
|
||||
if ctx.ShouldBindJSON(&request) != nil || !clientcommon.ValidPhone(request.Phone) ||
|
||||
!base.IsValidAccountPassword(request.Password) ||
|
||||
!clientcommon.VerifyCode("user_app", request.Phone, "register", request.RequestIdentity, request.Code) {
|
||||
if ctx.ShouldBindJSON(&request) != nil || !common.ValidPhone(request.Phone) ||
|
||||
!common.IsValidAccountPassword(request.Password) ||
|
||||
!common.VerifyCode("user_app", request.Phone, "register", request.RequestIdentity, request.Code) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
hash, err := base.PasswordHash(request.Password)
|
||||
hash, err := common.PasswordHash(request.Password)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
account := models.UserAccount{
|
||||
Entity: base.NewEntity(base.StatusEnable), Username: strings.TrimSpace(request.Phone),
|
||||
Entity: common.NewEntity(common.StatusEnable), Username: strings.TrimSpace(request.Phone),
|
||||
Phone: strings.TrimSpace(request.Phone), PasswordHash: hash, Name: strings.TrimSpace(request.Name),
|
||||
}
|
||||
err = impl.DBService.Transaction(func(tx *gorm.DB) error {
|
||||
@@ -85,7 +84,7 @@ func Register(ctx *gin.Context) {
|
||||
return err
|
||||
}
|
||||
address := models.UserAddress{
|
||||
Entity: base.NewEntity(base.StatusEnable), UserAccountID: account.ID, Address: request.Address,
|
||||
Entity: common.NewEntity(common.StatusEnable), UserAccountID: account.ID, Address: request.Address,
|
||||
Longitude: request.Longitude, Latitude: request.Latitude, IsDefault: true,
|
||||
}
|
||||
if err := tx.Create(&address).Error; err != nil {
|
||||
@@ -98,19 +97,19 @@ func Register(ctx *gin.Context) {
|
||||
return nil
|
||||
}
|
||||
var gas models.GasBasic
|
||||
if err := tx.Where("identity = ? AND status = ?", request.GasIdentity, base.StatusEnable).First(&gas).Error; err != nil {
|
||||
if err := tx.Where("identity = ? AND status = ?", request.GasIdentity, common.StatusEnable).First(&gas).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
var deliveryID uint64
|
||||
if request.DeliveryIdentity != "" {
|
||||
var delivery models.DeliveryBasic
|
||||
if err := tx.Where("identity = ? AND gas_basic_id = ? AND status = ?", request.DeliveryIdentity, gas.ID, base.StatusEnable).First(&delivery).Error; err != nil {
|
||||
if err := tx.Where("identity = ? AND gas_basic_id = ? AND status = ?", request.DeliveryIdentity, gas.ID, common.StatusEnable).First(&delivery).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
deliveryID = delivery.ID
|
||||
}
|
||||
return tx.Create(&models.UserServiceRelation{
|
||||
Entity: base.NewEntity(base.StatusEnable), UserAccountID: account.ID,
|
||||
Entity: common.NewEntity(common.StatusEnable), UserAccountID: account.ID,
|
||||
GasBasicID: gas.ID, DeliveryBasicID: deliveryID,
|
||||
}).Error
|
||||
})
|
||||
@@ -123,7 +122,7 @@ func Register(ctx *gin.Context) {
|
||||
|
||||
// Profile 返回当前用户的脱敏资料。
|
||||
func Profile(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -132,7 +131,7 @@ func Profile(ctx *gin.Context) {
|
||||
|
||||
// UpdateProfile 只允许修改非认证资料。
|
||||
func UpdateProfile(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -153,7 +152,7 @@ func UpdateProfile(ctx *gin.Context) {
|
||||
|
||||
// ChangePassword 使用当前密码修改登录密码。
|
||||
func ChangePassword(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -161,12 +160,12 @@ func ChangePassword(ctx *gin.Context) {
|
||||
CurrentPassword string `json:"current_password" binding:"required"`
|
||||
NewPassword string `json:"new_password" binding:"required"`
|
||||
}
|
||||
if ctx.ShouldBindJSON(&request) != nil || !base.IsValidAccountPassword(request.NewPassword) ||
|
||||
if ctx.ShouldBindJSON(&request) != nil || !common.IsValidAccountPassword(request.NewPassword) ||
|
||||
bcrypt.CompareHashAndPassword([]byte(account.PasswordHash), []byte(request.CurrentPassword)) != nil {
|
||||
infra.Response.Error(ctx, errcode.ErrPassword)
|
||||
return
|
||||
}
|
||||
hash, err := base.PasswordHash(request.NewPassword)
|
||||
hash, err := common.PasswordHash(request.NewPassword)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
@@ -186,18 +185,18 @@ func ResetPassword(ctx *gin.Context) {
|
||||
Code string `json:"code" binding:"required"`
|
||||
RequestIdentity string `json:"request_identity" binding:"required"`
|
||||
}
|
||||
if ctx.ShouldBindJSON(&request) != nil || !base.IsValidAccountPassword(request.NewPassword) ||
|
||||
!clientcommon.VerifyCode("user_app", request.Phone, "reset_login_password", request.RequestIdentity, request.Code) {
|
||||
if ctx.ShouldBindJSON(&request) != nil || !common.IsValidAccountPassword(request.NewPassword) ||
|
||||
!common.VerifyCode("user_app", request.Phone, "reset_login_password", request.RequestIdentity, request.Code) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
hash, err := base.PasswordHash(request.NewPassword)
|
||||
hash, err := common.PasswordHash(request.NewPassword)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
result := impl.DBService.Model(&models.UserAccount{}).
|
||||
Where("phone = ? AND status = ?", strings.TrimSpace(request.Phone), base.StatusEnable).
|
||||
Where("phone = ? AND status = ?", strings.TrimSpace(request.Phone), common.StatusEnable).
|
||||
Update("password_hash", hash)
|
||||
if result.Error != nil {
|
||||
infra.Response.Error(ctx, result.Error)
|
||||
|
||||
@@ -7,8 +7,7 @@ import (
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
clientcommon "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/client/common"
|
||||
base "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
||||
common "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -16,31 +15,31 @@ import (
|
||||
// PublicGasStations 提供注册页所需的最小启用气站数据。
|
||||
func PublicGasStations(ctx *gin.Context) {
|
||||
var list []models.GasBasic
|
||||
if err := impl.DBService.Select("identity", "name", "address").Where("status = ?", base.StatusEnable).Order("name").Find(&list).Error; err != nil {
|
||||
if err := impl.DBService.Select("identity", "name", "address").Where("status = ?", common.StatusEnable).Order("name").Find(&list).Error; err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, base.ResourceResponse(list))
|
||||
infra.Response.Success(ctx, common.ResourceResponse(list))
|
||||
}
|
||||
|
||||
// PublicDeliveryPoints 提供指定气站下的启用配送点。
|
||||
func PublicDeliveryPoints(ctx *gin.Context) {
|
||||
var gas models.GasBasic
|
||||
if impl.DBService.Where("identity = ? AND status = ?", ctx.Query("gas_identity"), base.StatusEnable).First(&gas).Error != nil {
|
||||
if impl.DBService.Where("identity = ? AND status = ?", ctx.Query("gas_identity"), common.StatusEnable).First(&gas).Error != nil {
|
||||
infra.Response.Error(ctx, errcode.ErrRecordNotFound)
|
||||
return
|
||||
}
|
||||
var list []models.DeliveryBasic
|
||||
if err := impl.DBService.Select("identity", "name", "address").Where("gas_basic_id = ? AND status = ?", gas.ID, base.StatusEnable).Order("name").Find(&list).Error; err != nil {
|
||||
if err := impl.DBService.Select("identity", "name", "address").Where("gas_basic_id = ? AND status = ?", gas.ID, common.StatusEnable).Order("name").Find(&list).Error; err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, base.ResourceResponse(list))
|
||||
infra.Response.Success(ctx, common.ResourceResponse(list))
|
||||
}
|
||||
|
||||
// PublicContents 返回已发布内容,支持内容类型筛选。
|
||||
func PublicContents(ctx *gin.Context) {
|
||||
query := impl.DBService.Where("status = ? AND publish_status = ?", base.StatusEnable, "published")
|
||||
query := impl.DBService.Where("status = ? AND publish_status = ?", common.StatusEnable, "published")
|
||||
if contentType := strings.TrimSpace(ctx.Query("content_type")); contentType != "" {
|
||||
query = query.Where("content_type = ?", contentType)
|
||||
}
|
||||
@@ -49,12 +48,12 @@ func PublicContents(ctx *gin.Context) {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, base.ResourceResponse(list))
|
||||
infra.Response.Success(ctx, common.ResourceResponse(list))
|
||||
}
|
||||
|
||||
// ConfirmContentRead 记录用户对特定内容版本的确认,幂等号全局唯一。
|
||||
func ConfirmContentRead(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -74,7 +73,7 @@ func ConfirmContentRead(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
record := models.CmsContentRead{
|
||||
Entity: base.NewEntity(base.StatusEnable), UserAccountID: account.ID, CmsContentID: content.ID,
|
||||
Entity: common.NewEntity(common.StatusEnable), UserAccountID: account.ID, CmsContentID: content.ID,
|
||||
VersionNo: content.VersionNo, ShownAt: time.Now(), ConfirmedAt: timePointer(time.Now()),
|
||||
ClientVersion: request.ClientVersion, DeviceIdentity: request.DeviceIdentity, RequestNo: request.RequestNo,
|
||||
}
|
||||
|
||||
@@ -4,20 +4,19 @@ import (
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
clientcommon "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/client/common"
|
||||
base "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
||||
common "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ServiceRelation 返回当前唯一有效服务归属的公开 identity。
|
||||
func ServiceRelation(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var relation models.UserServiceRelation
|
||||
if impl.DBService.Where("user_account_id = ? AND status = ?", account.ID, base.StatusEnable).First(&relation).Error != nil {
|
||||
if impl.DBService.Where("user_account_id = ? AND status = ?", account.ID, common.StatusEnable).First(&relation).Error != nil {
|
||||
infra.Response.Success(ctx, nil)
|
||||
return
|
||||
}
|
||||
@@ -39,41 +38,41 @@ func ServiceRelation(ctx *gin.Context) {
|
||||
|
||||
// ListGasContracts 返回用户自己的供气合同。
|
||||
func ListGasContracts(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var list []models.GasorderContract
|
||||
if err := impl.DBService.Where("user_account_id = ? AND status <> ?", account.ID, base.StatusArchived).Order("created_at desc").Find(&list).Error; err != nil {
|
||||
if err := impl.DBService.Where("user_account_id = ? AND status <> ?", account.ID, common.StatusArchived).Order("created_at desc").Find(&list).Error; err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, base.ResourceResponse(list))
|
||||
infra.Response.Success(ctx, common.ResourceResponse(list))
|
||||
}
|
||||
|
||||
// ListGasOrders 返回用户自己的供气订单。
|
||||
func ListGasOrders(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var list []models.GasorderBasic
|
||||
if err := impl.DBService.Where("user_account_id = ? AND status <> ?", account.ID, base.StatusArchived).Order("created_at desc").Find(&list).Error; err != nil {
|
||||
if err := impl.DBService.Where("user_account_id = ? AND status <> ?", account.ID, common.StatusArchived).Order("created_at desc").Find(&list).Error; err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, base.ResourceResponse(list))
|
||||
infra.Response.Success(ctx, common.ResourceResponse(list))
|
||||
}
|
||||
|
||||
// CancelGasOrder 仅允许取消已创建或已分派的本人订单。
|
||||
func CancelGasOrder(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
result := impl.DBService.Model(&models.GasorderBasic{}).
|
||||
Where("identity = ? AND user_account_id = ? AND order_status IN ?", ctx.Param("identity"), account.ID, []int{base.StatusCreated, base.StatusAssigned}).
|
||||
Updates(map[string]any{"order_status": base.StatusCancelled, "operator_identity": account.Identity})
|
||||
Where("identity = ? AND user_account_id = ? AND order_status IN ?", ctx.Param("identity"), account.ID, []int{common.StatusCreated, common.StatusAssigned}).
|
||||
Updates(map[string]any{"order_status": common.StatusCancelled, "operator_identity": account.Identity})
|
||||
if result.Error != nil {
|
||||
infra.Response.Error(ctx, result.Error)
|
||||
return
|
||||
|
||||
@@ -7,8 +7,7 @@ import (
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
clientcommon "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/client/common"
|
||||
base "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
||||
common "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
@@ -18,16 +17,16 @@ import (
|
||||
// PublicProducts 返回上架且有库存的商品。
|
||||
func PublicProducts(ctx *gin.Context) {
|
||||
var list []models.EcProduct
|
||||
if err := impl.DBService.Where("status = ? AND stock_quantity > 0", base.StatusEnable).Order("created_at desc").Find(&list).Error; err != nil {
|
||||
if err := impl.DBService.Where("status = ? AND stock_quantity > 0", common.StatusEnable).Order("created_at desc").Find(&list).Error; err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, base.ResourceResponse(list))
|
||||
infra.Response.Success(ctx, common.ResourceResponse(list))
|
||||
}
|
||||
|
||||
// CreateShopOrder 按服务端价格创建订单并原子扣减库存。
|
||||
func CreateShopOrder(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -42,17 +41,17 @@ func CreateShopOrder(ctx *gin.Context) {
|
||||
Quantity int `json:"quantity" binding:"required,gt=0"`
|
||||
} `json:"items" binding:"required,min=1"`
|
||||
}
|
||||
if ctx.ShouldBindJSON(&request) != nil || !clientcommon.ValidPhone(request.ContactPhone) {
|
||||
if ctx.ShouldBindJSON(&request) != nil || !common.ValidPhone(request.ContactPhone) {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
var address models.UserAddress
|
||||
if impl.DBService.Where("identity = ? AND user_account_id = ? AND status <> ?", request.AddressIdentity, account.ID, base.StatusArchived).First(&address).Error != nil {
|
||||
if impl.DBService.Where("identity = ? AND user_account_id = ? AND status <> ?", request.AddressIdentity, account.ID, common.StatusArchived).First(&address).Error != nil {
|
||||
infra.Response.Error(ctx, errcode.ErrRecordNotFound)
|
||||
return
|
||||
}
|
||||
order := models.EcOrder{
|
||||
Entity: base.NewEntity(base.StatusEnable), OrderStatus: 16, OrderNo: clientcommon.RecordNo("EC"),
|
||||
Entity: common.NewEntity(common.StatusEnable), OrderStatus: 16, OrderNo: common.RecordNo("EC"),
|
||||
RequestNo: request.RequestNo, UserAccountID: account.ID, UserAddressID: address.ID,
|
||||
Address: address.Address, Longitude: address.Longitude, Latitude: address.Latitude,
|
||||
ContactName: request.ContactName, ContactPhone: request.ContactPhone, Remark: request.Remark, LogisticsStatus: 10,
|
||||
@@ -63,7 +62,7 @@ func CreateShopOrder(ctx *gin.Context) {
|
||||
for _, requested := range request.Items {
|
||||
var product models.EcProduct
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
|
||||
Where("identity = ? AND status = ? AND stock_quantity >= ?", requested.ProductIdentity, base.StatusEnable, requested.Quantity).
|
||||
Where("identity = ? AND status = ? AND stock_quantity >= ?", requested.ProductIdentity, common.StatusEnable, requested.Quantity).
|
||||
First(&product).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -72,7 +71,7 @@ func CreateShopOrder(ctx *gin.Context) {
|
||||
}
|
||||
snapshot, _ := json.Marshal(gin.H{"identity": product.Identity, "name": product.Name, "product_code": product.ProductCode})
|
||||
items = append(items, models.EcOrderItem{
|
||||
Entity: base.NewEntity(base.StatusEnable), EcProductID: product.ID, ProductSnapshot: string(snapshot),
|
||||
Entity: common.NewEntity(common.StatusEnable), EcProductID: product.ID, ProductSnapshot: string(snapshot),
|
||||
Quantity: requested.Quantity, SaleAmount: product.PriceAmount,
|
||||
})
|
||||
amount += product.PriceAmount * int64(requested.Quantity)
|
||||
@@ -97,26 +96,26 @@ func CreateShopOrder(ctx *gin.Context) {
|
||||
}
|
||||
order = existing
|
||||
}
|
||||
infra.Response.Success(ctx, base.ResourceResponse(order))
|
||||
infra.Response.Success(ctx, common.ResourceResponse(order))
|
||||
}
|
||||
|
||||
// ListShopOrders 返回本人的商城订单。
|
||||
func ListShopOrders(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var list []models.EcOrder
|
||||
if err := impl.DBService.Where("user_account_id = ? AND status <> ?", account.ID, base.StatusArchived).Order("created_at desc").Find(&list).Error; err != nil {
|
||||
if err := impl.DBService.Where("user_account_id = ? AND status <> ?", account.ID, common.StatusArchived).Order("created_at desc").Find(&list).Error; err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, base.ResourceResponse(list))
|
||||
infra.Response.Success(ctx, common.ResourceResponse(list))
|
||||
}
|
||||
|
||||
// CancelShopOrder 取消未支付订单并恢复库存。
|
||||
func CancelShopOrder(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -146,7 +145,7 @@ func CancelShopOrder(ctx *gin.Context) {
|
||||
|
||||
// PayShopOrder 使用用户钱包余额支付,金额和订单状态由服务端锁定校验。
|
||||
func PayShopOrder(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@@ -169,12 +168,13 @@ func PayShopOrder(ctx *gin.Context) {
|
||||
Where("owner_type = ? AND owner_identity = ?", "user", account.Identity).First(&wallet).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if !clientcommon.VerifyPaymentPassword(account.Identity, wallet, request.PaymentPassword) ||
|
||||
wallet.Balance < order.PayableAmount {
|
||||
if !common.VerifyPaymentPassword(account.Identity, wallet, request.PaymentPassword) {
|
||||
return gorm.ErrInvalidData
|
||||
}
|
||||
wallet.Balance -= order.PayableAmount
|
||||
if err := tx.Model(&wallet).Update("balance", wallet.Balance).Error; err != nil {
|
||||
if err := common.SpendWalletBalance(&wallet, order.PayableAmount); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := common.SaveWalletBalances(tx, wallet); err != nil {
|
||||
return err
|
||||
}
|
||||
now := time.Now()
|
||||
@@ -183,7 +183,7 @@ func PayShopOrder(ctx *gin.Context) {
|
||||
}
|
||||
date := now.In(time.Local)
|
||||
return tx.Create(&models.WalletRecord{
|
||||
Entity: base.NewEntity(base.StatusEnable), WalletBasicID: wallet.ID, RecordNo: clientcommon.RecordNo("WR"),
|
||||
Entity: common.NewEntity(common.StatusEnable), WalletBasicID: wallet.ID, RecordNo: common.RecordNo("WR"),
|
||||
RequestNo: request.RequestNo, Direction: "expense", TradeType: "ec_order",
|
||||
Amount: order.PayableAmount, BalanceAfter: wallet.Balance, WithdrawalBalanceAfter: wallet.WithdrawalBalance,
|
||||
OutTradeNo: order.OrderNo, PayChannel: "wallet", OperatorIdentity: account.Identity,
|
||||
@@ -199,7 +199,7 @@ func PayShopOrder(ctx *gin.Context) {
|
||||
|
||||
// ConfirmShopReceipt 只推进独立物流状态,不伪造支付状态。
|
||||
func ConfirmShopReceipt(ctx *gin.Context) {
|
||||
account, ok := clientcommon.UserAccount(ctx)
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user