This commit is contained in:
599
internal/exporter/order_scene.go
Normal file
599
internal/exporter/order_scene.go
Normal file
@@ -0,0 +1,599 @@
|
||||
package exporter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
)
|
||||
|
||||
const (
|
||||
orderExportBaseHeaderCount = 11
|
||||
orderExportCardGroupSize = 2
|
||||
orderExportMinCardGroups = 1
|
||||
)
|
||||
|
||||
// OrderDataSource 订单导出数据源。
|
||||
type OrderDataSource struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewOrderDataSource 创建订单导出数据源。
|
||||
func NewOrderDataSource(db *gorm.DB) *OrderDataSource {
|
||||
return &OrderDataSource{db: db}
|
||||
}
|
||||
|
||||
// Scene 返回导出场景编码。
|
||||
func (s *OrderDataSource) Scene() string {
|
||||
return constants.ExportTaskSceneOrder
|
||||
}
|
||||
|
||||
// Count 统计订单导出行数。
|
||||
func (s *OrderDataSource) Count(ctx context.Context, params ExportParams) (int, error) {
|
||||
query, err := s.applyFilters(ctx, s.baseQuery(ctx), params)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var total int64
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(total), nil
|
||||
}
|
||||
|
||||
// Headers 返回订单导出表头。
|
||||
func (s *OrderDataSource) Headers(ctx context.Context, params ExportParams) ([]string, error) {
|
||||
cardGroups, err := s.resolveCardGroupCount(ctx, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buildOrderExportHeaders(cardGroups), nil
|
||||
}
|
||||
|
||||
// Fetch 按 offset/limit 查询订单导出数据。
|
||||
func (s *OrderDataSource) Fetch(ctx context.Context, params ExportParams, offset, limit int) ([][]string, error) {
|
||||
if limit <= 0 {
|
||||
return [][]string{}, nil
|
||||
}
|
||||
|
||||
cardGroups := orderCardGroupCountFromHeaders(params.ResolvedHeaders)
|
||||
if cardGroups <= 0 {
|
||||
resolved, err := s.resolveCardGroupCount(ctx, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cardGroups = resolved
|
||||
}
|
||||
|
||||
orders, err := s.fetchOrders(ctx, params, offset, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(orders) == 0 {
|
||||
return [][]string{}, nil
|
||||
}
|
||||
|
||||
orderIDs := make([]uint, 0, len(orders))
|
||||
deviceIDs := make([]uint, 0, len(orders))
|
||||
for _, item := range orders {
|
||||
orderIDs = append(orderIDs, item.ID)
|
||||
if item.DeviceID != nil {
|
||||
deviceIDs = append(deviceIDs, *item.DeviceID)
|
||||
}
|
||||
}
|
||||
|
||||
itemMap, err := s.fetchOrderItems(ctx, orderIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cardMap, err := s.fetchBoundCards(ctx, deviceIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
paymentMap, err := s.fetchPreferredPayments(ctx, orderIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows := make([][]string, 0, len(orders))
|
||||
for _, item := range orders {
|
||||
var cards []orderExportCardRow
|
||||
if item.DeviceID != nil {
|
||||
cards = cardMap[*item.DeviceID]
|
||||
}
|
||||
rows = append(rows, buildOrderExportRow(item, itemMap[item.ID], paymentMap[item.ID], cards, cardGroups))
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
func (s *OrderDataSource) baseQuery(ctx context.Context) *gorm.DB {
|
||||
return s.db.WithContext(ctx).
|
||||
Table("tb_order AS o").
|
||||
Where("o.deleted_at IS NULL")
|
||||
}
|
||||
|
||||
// applyFilters 应用与 /api/admin/orders 当前实际行为一致的筛选条件。
|
||||
// is_expired 在接口 Service 中未进入 Store 筛选,这里按当前接口行为忽略。
|
||||
func (s *OrderDataSource) applyFilters(ctx context.Context, query *gorm.DB, params ExportParams) (*gorm.DB, error) {
|
||||
query = s.applyOrderScope(query, params)
|
||||
|
||||
if params.UserType == constants.UserTypeAgent {
|
||||
if params.CreatorShopID != nil {
|
||||
query = query.Where("o.buyer_type = ? AND o.buyer_id = ?", model.BuyerTypeAgent, *params.CreatorShopID)
|
||||
} else {
|
||||
query = query.Where("o.buyer_type = ?", model.BuyerTypeAgent)
|
||||
}
|
||||
}
|
||||
if paymentStatus, ok := filterInt(params.Filters, "payment_status"); ok {
|
||||
query = query.Where("o.payment_status = ?", paymentStatus)
|
||||
}
|
||||
if paymentMethod, ok := filterString(params.Filters, "payment_method"); ok {
|
||||
query = query.Where("o.payment_method = ?", paymentMethod)
|
||||
}
|
||||
if orderType, ok := filterString(params.Filters, "order_type"); ok {
|
||||
query = query.Where("o.order_type = ?", orderType)
|
||||
}
|
||||
if orderNo, ok := filterString(params.Filters, "order_no"); ok {
|
||||
query = query.Where("o.order_no = ?", orderNo)
|
||||
}
|
||||
if purchaseRole, ok := filterString(params.Filters, "purchase_role"); ok {
|
||||
query = query.Where("o.purchase_role = ?", purchaseRole)
|
||||
}
|
||||
if sellerShopID, ok := filterUint(params.Filters, "seller_shop_id"); ok {
|
||||
query = query.Where("o.seller_shop_id = ?", sellerShopID)
|
||||
}
|
||||
if start, ok := filterTime(params.Filters, "start_time"); ok {
|
||||
query = query.Where("o.created_at >= ?", start)
|
||||
}
|
||||
if end, ok := filterTime(params.Filters, "end_time"); ok {
|
||||
query = query.Where("o.created_at <= ?", end)
|
||||
}
|
||||
if buyerPhone, ok := filterString(params.Filters, "buyer_phone"); ok {
|
||||
query = query.Where("o.buyer_phone = ?", buyerPhone)
|
||||
}
|
||||
if identifier, ok := filterString(params.Filters, "identifier"); ok {
|
||||
iotCardID, deviceID, err := s.resolveOrderListAssetIdentifier(ctx, params, identifier)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
assetQuery := s.db.Where("o.asset_identifier = ?", identifier)
|
||||
if iotCardID != nil {
|
||||
assetQuery = assetQuery.Or("o.iot_card_id = ?", *iotCardID)
|
||||
}
|
||||
if deviceID != nil {
|
||||
assetQuery = assetQuery.Or("o.device_id = ?", *deviceID)
|
||||
}
|
||||
query = query.Where(assetQuery)
|
||||
}
|
||||
return query, nil
|
||||
}
|
||||
|
||||
func (s *OrderDataSource) applyOrderScope(query *gorm.DB, params ExportParams) *gorm.DB {
|
||||
switch params.UserType {
|
||||
case constants.UserTypeSuperAdmin, constants.UserTypePlatform:
|
||||
return query
|
||||
case constants.UserTypeAgent:
|
||||
if len(params.ScopeShopIDs) == 0 {
|
||||
return query.Where("1 = 0")
|
||||
}
|
||||
return query.Where(
|
||||
s.db.Where("o.buyer_type = ? AND o.buyer_id IN ?", model.BuyerTypeAgent, params.ScopeShopIDs).
|
||||
Or("o.seller_shop_id IN ?", params.ScopeShopIDs).
|
||||
Or(s.db.Where("o.seller_shop_id IS NULL AND o.operator_type = ? AND o.operator_id IN ?", model.OperatorAccountTypeAgent, params.ScopeShopIDs)),
|
||||
)
|
||||
default:
|
||||
return query.Where("1 = 0")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *OrderDataSource) resolveCardGroupCount(ctx context.Context, params ExportParams) (int, error) {
|
||||
filtered, err := s.applyFilters(ctx, s.baseQuery(ctx), params)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var count int64
|
||||
query := filtered.
|
||||
Select("COALESCE(MAX(bound_cards.card_count), 0)").
|
||||
Joins(`
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT COUNT(*) AS card_count
|
||||
FROM tb_device_sim_binding AS b
|
||||
WHERE b.device_id = o.device_id
|
||||
AND b.bind_status = ?
|
||||
AND b.deleted_at IS NULL
|
||||
) AS bound_cards ON TRUE
|
||||
`, constants.BindStatusBound)
|
||||
if err := query.Scan(&count).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if count < orderExportMinCardGroups {
|
||||
return orderExportMinCardGroups, nil
|
||||
}
|
||||
return int(count), nil
|
||||
}
|
||||
|
||||
func (s *OrderDataSource) fetchOrders(ctx context.Context, params ExportParams, offset, limit int) ([]orderExportRow, error) {
|
||||
var orders []orderExportRow
|
||||
filtered, err := s.applyFilters(ctx, s.baseQuery(ctx), params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := filtered.
|
||||
Joins("LEFT JOIN tb_shop AS sh ON sh.id = o.seller_shop_id").
|
||||
Select(`
|
||||
o.id,
|
||||
o.order_no,
|
||||
o.asset_identifier,
|
||||
o.seller_cost_price,
|
||||
o.total_amount,
|
||||
o.actual_paid_amount,
|
||||
o.payment_status,
|
||||
o.payment_method,
|
||||
o.created_at,
|
||||
o.device_id,
|
||||
COALESCE(sh.shop_name, '') AS shop_name
|
||||
`).
|
||||
Order("o.id DESC").
|
||||
Limit(limit).
|
||||
Offset(offset)
|
||||
if err := query.Scan(&orders).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return orders, nil
|
||||
}
|
||||
|
||||
func (s *OrderDataSource) fetchOrderItems(ctx context.Context, orderIDs []uint) (map[uint][]orderExportItemRow, error) {
|
||||
result := make(map[uint][]orderExportItemRow, len(orderIDs))
|
||||
if len(orderIDs) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
var items []orderExportItemRow
|
||||
if err := s.db.WithContext(ctx).
|
||||
Table("tb_order_item").
|
||||
Select("order_id, package_name, quantity").
|
||||
Where("order_id IN ?", orderIDs).
|
||||
Where("deleted_at IS NULL").
|
||||
Order("order_id ASC, id ASC").
|
||||
Scan(&items).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, item := range items {
|
||||
result[item.OrderID] = append(result[item.OrderID], item)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *OrderDataSource) fetchBoundCards(ctx context.Context, deviceIDs []uint) (map[uint][]orderExportCardRow, error) {
|
||||
result := make(map[uint][]orderExportCardRow, len(deviceIDs))
|
||||
deviceIDs = normalizeUintSlice(deviceIDs)
|
||||
if len(deviceIDs) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
var cards []orderExportCardRow
|
||||
if err := s.db.WithContext(ctx).
|
||||
Table("tb_device_sim_binding AS b").
|
||||
Select(`
|
||||
b.device_id,
|
||||
b.slot_position,
|
||||
c.msisdn,
|
||||
c.iccid
|
||||
`).
|
||||
Joins("JOIN tb_iot_card AS c ON c.id = b.iot_card_id AND c.deleted_at IS NULL").
|
||||
Where("b.device_id IN ?", deviceIDs).
|
||||
Where("b.bind_status = ?", constants.BindStatusBound).
|
||||
Where("b.deleted_at IS NULL").
|
||||
Order("b.device_id ASC, b.slot_position ASC, b.id ASC").
|
||||
Scan(&cards).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, card := range cards {
|
||||
result[card.DeviceID] = append(result[card.DeviceID], card)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *OrderDataSource) fetchPreferredPayments(ctx context.Context, orderIDs []uint) (map[uint]orderExportPaymentRow, error) {
|
||||
result := make(map[uint]orderExportPaymentRow, len(orderIDs))
|
||||
if len(orderIDs) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
var payments []orderExportPaymentRow
|
||||
if err := s.db.WithContext(ctx).
|
||||
Table("tb_payment").
|
||||
Select("order_id, third_party_trade_no, status").
|
||||
Where("order_id IN ?", orderIDs).
|
||||
Where("order_type = ?", model.PaymentOrderTypePackage).
|
||||
Where("deleted_at IS NULL").
|
||||
Order("order_id ASC, CASE WHEN status = 1 THEN 0 ELSE 1 END ASC, created_at DESC, id DESC").
|
||||
Scan(&payments).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, payment := range payments {
|
||||
if _, exists := result[payment.OrderID]; exists {
|
||||
continue
|
||||
}
|
||||
result[payment.OrderID] = payment
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *OrderDataSource) resolveOrderListAssetIdentifier(ctx context.Context, params ExportParams, identifier string) (*uint, *uint, error) {
|
||||
if identifier == "" {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
var registry orderExportAssetIdentifierRow
|
||||
registryErr := s.db.WithContext(ctx).
|
||||
Table("tb_asset_identifier").
|
||||
Select("asset_type, asset_id").
|
||||
Where("identifier = ?", identifier).
|
||||
First(®istry).Error
|
||||
if registryErr != nil && registryErr != gorm.ErrRecordNotFound {
|
||||
return nil, nil, registryErr
|
||||
}
|
||||
if registryErr == nil {
|
||||
switch registry.AssetType {
|
||||
case model.AssetTypeIotCard:
|
||||
if s.assetVisible(ctx, params, "tb_iot_card", registry.AssetID) {
|
||||
cardID := registry.AssetID
|
||||
return &cardID, nil, nil
|
||||
}
|
||||
case model.AssetTypeDevice:
|
||||
if s.assetVisible(ctx, params, "tb_device", registry.AssetID) {
|
||||
deviceID := registry.AssetID
|
||||
return nil, &deviceID, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if deviceID, err := s.resolveDeviceIDByIdentifier(ctx, params, identifier); err != nil {
|
||||
return nil, nil, err
|
||||
} else if deviceID != nil {
|
||||
return nil, deviceID, nil
|
||||
}
|
||||
|
||||
cardID, err := s.resolveCardIDByIdentifier(ctx, params, identifier)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return cardID, nil, nil
|
||||
}
|
||||
|
||||
func (s *OrderDataSource) assetVisible(ctx context.Context, params ExportParams, table string, id uint) bool {
|
||||
var count int64
|
||||
query := s.db.WithContext(ctx).Table(table).Where("id = ? AND deleted_at IS NULL", id)
|
||||
if params.UserType == constants.UserTypeAgent {
|
||||
if len(params.ScopeShopIDs) == 0 {
|
||||
return false
|
||||
}
|
||||
query = query.Where("shop_id IN ?", params.ScopeShopIDs)
|
||||
}
|
||||
return query.Count(&count).Error == nil && count > 0
|
||||
}
|
||||
|
||||
func (s *OrderDataSource) resolveDeviceIDByIdentifier(ctx context.Context, params ExportParams, identifier string) (*uint, error) {
|
||||
var row struct {
|
||||
ID uint `gorm:"column:id"`
|
||||
}
|
||||
query := s.db.WithContext(ctx).
|
||||
Table("tb_device").
|
||||
Select("id").
|
||||
Where("deleted_at IS NULL").
|
||||
Where("virtual_no = ? OR imei = ? OR sn = ?", identifier, identifier, identifier)
|
||||
if params.UserType == constants.UserTypeAgent {
|
||||
if len(params.ScopeShopIDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
query = query.Where("shop_id IN ?", params.ScopeShopIDs)
|
||||
}
|
||||
err := query.First(&row).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &row.ID, nil
|
||||
}
|
||||
|
||||
func (s *OrderDataSource) resolveCardIDByIdentifier(ctx context.Context, params ExportParams, identifier string) (*uint, error) {
|
||||
conditions := []string{"virtual_no = ?", "msisdn = ?", "iccid = ?"}
|
||||
args := []any{identifier, identifier, identifier}
|
||||
if len(identifier) == 19 {
|
||||
conditions = append(conditions, "iccid_19 = ?")
|
||||
args = append(args, identifier)
|
||||
} else if len(identifier) == 20 {
|
||||
conditions = append(conditions, "iccid_20 = ?")
|
||||
args = append(args, identifier)
|
||||
}
|
||||
|
||||
var row struct {
|
||||
ID uint `gorm:"column:id"`
|
||||
}
|
||||
query := s.db.WithContext(ctx).
|
||||
Table("tb_iot_card").
|
||||
Select("id").
|
||||
Where("deleted_at IS NULL").
|
||||
Where(strings.Join(conditions, " OR "), args...)
|
||||
if params.UserType == constants.UserTypeAgent {
|
||||
if len(params.ScopeShopIDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
query = query.Where("shop_id IN ?", params.ScopeShopIDs)
|
||||
}
|
||||
err := query.First(&row).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &row.ID, nil
|
||||
}
|
||||
|
||||
type orderExportRow struct {
|
||||
ID uint `gorm:"column:id"`
|
||||
OrderNo string `gorm:"column:order_no"`
|
||||
ShopName string `gorm:"column:shop_name"`
|
||||
AssetIdentifier string `gorm:"column:asset_identifier"`
|
||||
SellerCostPrice int64 `gorm:"column:seller_cost_price"`
|
||||
TotalAmount int64 `gorm:"column:total_amount"`
|
||||
ActualPaidAmount *int64 `gorm:"column:actual_paid_amount"`
|
||||
PaymentStatus int `gorm:"column:payment_status"`
|
||||
PaymentMethod string `gorm:"column:payment_method"`
|
||||
CreatedAt time.Time `gorm:"column:created_at"`
|
||||
DeviceID *uint `gorm:"column:device_id"`
|
||||
}
|
||||
|
||||
type orderExportItemRow struct {
|
||||
OrderID uint `gorm:"column:order_id"`
|
||||
PackageName string `gorm:"column:package_name"`
|
||||
Quantity int `gorm:"column:quantity"`
|
||||
}
|
||||
|
||||
type orderExportPaymentRow struct {
|
||||
OrderID uint `gorm:"column:order_id"`
|
||||
ThirdPartyTradeNo string `gorm:"column:third_party_trade_no"`
|
||||
Status int `gorm:"column:status"`
|
||||
}
|
||||
|
||||
type orderExportCardRow struct {
|
||||
DeviceID uint `gorm:"column:device_id"`
|
||||
SlotPosition int `gorm:"column:slot_position"`
|
||||
MSISDN string `gorm:"column:msisdn"`
|
||||
ICCID string `gorm:"column:iccid"`
|
||||
}
|
||||
|
||||
type orderExportAssetIdentifierRow struct {
|
||||
AssetType string `gorm:"column:asset_type"`
|
||||
AssetID uint `gorm:"column:asset_id"`
|
||||
}
|
||||
|
||||
func buildOrderExportHeaders(cardGroups int) []string {
|
||||
if cardGroups < orderExportMinCardGroups {
|
||||
cardGroups = orderExportMinCardGroups
|
||||
}
|
||||
|
||||
headers := []string{
|
||||
"订单号",
|
||||
"店铺",
|
||||
"虚拟号",
|
||||
"套餐名称",
|
||||
"成本价",
|
||||
"下单金额",
|
||||
"支付状态",
|
||||
"支付方式",
|
||||
"数量",
|
||||
"下单时间",
|
||||
"第三方单号",
|
||||
}
|
||||
for i := 1; i <= cardGroups; i++ {
|
||||
headers = append(headers,
|
||||
fmt.Sprintf("接入号%d", i),
|
||||
fmt.Sprintf("ICCID%d", i),
|
||||
)
|
||||
}
|
||||
return headers
|
||||
}
|
||||
|
||||
func buildOrderExportRow(item orderExportRow, items []orderExportItemRow, payment orderExportPaymentRow, cards []orderExportCardRow, cardGroups int) []string {
|
||||
if cardGroups < orderExportMinCardGroups {
|
||||
cardGroups = orderExportMinCardGroups
|
||||
}
|
||||
|
||||
row := []string{
|
||||
item.OrderNo,
|
||||
item.ShopName,
|
||||
item.AssetIdentifier,
|
||||
joinOrderPackageNames(items),
|
||||
formatMoneyYuan(item.SellerCostPrice),
|
||||
formatMoneyYuan(orderActualPaidAmount(item)),
|
||||
constants.GetOrderPaymentStatusName(item.PaymentStatus),
|
||||
formatOrderPaymentMethod(item.PaymentMethod),
|
||||
formatOrderQuantity(items),
|
||||
item.CreatedAt.Format(exportTimeLayout),
|
||||
payment.ThirdPartyTradeNo,
|
||||
}
|
||||
for i := 0; i < cardGroups; i++ {
|
||||
if i >= len(cards) {
|
||||
row = append(row, "", "")
|
||||
continue
|
||||
}
|
||||
row = append(row, cards[i].MSISDN, cards[i].ICCID)
|
||||
}
|
||||
return row
|
||||
}
|
||||
|
||||
func orderCardGroupCountFromHeaders(headers []string) int {
|
||||
if len(headers) < orderExportBaseHeaderCount {
|
||||
return 0
|
||||
}
|
||||
cardColumnCount := len(headers) - orderExportBaseHeaderCount
|
||||
if cardColumnCount <= 0 || cardColumnCount%orderExportCardGroupSize != 0 {
|
||||
return 0
|
||||
}
|
||||
return cardColumnCount / orderExportCardGroupSize
|
||||
}
|
||||
|
||||
func joinOrderPackageNames(items []orderExportItemRow) string {
|
||||
if len(items) == 0 {
|
||||
return ""
|
||||
}
|
||||
names := make([]string, 0, len(items))
|
||||
for _, item := range items {
|
||||
if item.PackageName != "" {
|
||||
names = append(names, item.PackageName)
|
||||
}
|
||||
}
|
||||
return strings.Join(names, ",")
|
||||
}
|
||||
|
||||
func formatOrderQuantity(items []orderExportItemRow) string {
|
||||
if len(items) == 0 {
|
||||
return "0"
|
||||
}
|
||||
total := 0
|
||||
for _, item := range items {
|
||||
total += item.Quantity
|
||||
}
|
||||
return fmt.Sprintf("%d", total)
|
||||
}
|
||||
|
||||
func orderActualPaidAmount(item orderExportRow) int64 {
|
||||
if item.ActualPaidAmount != nil {
|
||||
return *item.ActualPaidAmount
|
||||
}
|
||||
if item.PaymentStatus == model.PaymentStatusPaid {
|
||||
return item.TotalAmount
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func formatOrderPaymentMethod(method string) string {
|
||||
switch method {
|
||||
case model.PaymentMethodWallet:
|
||||
return "钱包支付"
|
||||
case model.PaymentMethodWechat:
|
||||
return "微信支付"
|
||||
case model.PaymentMethodAlipay:
|
||||
return "支付宝支付"
|
||||
case model.PaymentMethodOffline:
|
||||
return "线下支付"
|
||||
default:
|
||||
return method
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user