Files
hfb_sys/backend/internal/modules/pickup/dto.go
T
yml2213 f3c5235b81 feat(pickup): 店铺管理支持历史店铺可视化手动映射与一键批量清洗
- 数据库升级:新增 pickup_shop_mappings 映射别名表,并在 admin_pickups 增加 raw_shop_name 永久保留原始店铺录入值
- 后端映射能力:提供历史店铺聚合统计、单条/批量映射至目标标准店铺、映射规则撤销与提号单还原接口;新建提号时若录入已映射别名自动归一化
- 前端管理升级:PickupShopDialog 升级为双 Tab 结构,Tab 2「历史店铺映射与清洗」支持总览统计卡片、状态筛选、单条/批量映射清洗、一键设为标准店铺及撤销还原
- 验证方式:执行并通过全套代码门禁(scripts/check.sh:SQL约束、go vet/build/test、MySQL测试库覆盖率、vue大小、eslint、prettier、vue-tsc及vite构建)
2026-10-09 13:31:11 +08:00

282 lines
12 KiB
Go

package pickup
import (
"errors"
"time"
"gorm.io/datatypes"
)
// 提号状态
const (
StatusPickingUp = "picking_up"
StatusCompleted = "completed"
StatusCancelled = "cancelled"
AccountSourceInternal = "internal"
AccountSourceExternalPlatformManaged = "external_platform_managed"
ListingSourceExternal = "external"
ListingSourceInternal = "internal"
SettlementModeOwnerWallet = "owner_wallet"
SettlementModePlatformManaged = "platform_managed"
OfflineSettlementStatusNone = "none"
OfflineSettlementStatusPending = "pending"
OfflineSettlementStatusSettled = "settled"
FinancialAdjustmentStatusSettled = "settled"
FinancialAdjustmentStatusPending = "pending"
FinancialAdjustmentStatusRecovery = "recovery_pending"
PickupShopStatusActive = "active"
PickupShopStatusDisabled = "disabled"
)
var (
ErrDependencyUnavailable = errors.New("dependency unavailable")
ErrListingUnavailable = errors.New("listing unavailable")
ErrPickupNotFound = errors.New("pickup not found")
ErrPickupNotPickingUp = errors.New("pickup not in picking_up status")
ErrInvalidAmount = errors.New("invalid amount")
ErrInvalidProfit = errors.New("invalid profit amount")
ErrDuplicatePickup = errors.New("duplicate pickup in progress")
ErrOfflineSettlementCannotMark = errors.New("pickup offline settlement cannot be marked")
ErrFinancialAdjustmentInvalid = errors.New("financial adjustment invalid")
ErrFinancialAdjustmentNotFound = errors.New("financial adjustment not found")
ErrFinancialAdjustmentCannotSettle = errors.New("financial adjustment cannot be settled")
ErrPickupShopNotFound = errors.New("pickup shop not found")
ErrPickupShopNameExists = errors.New("pickup shop name already exists")
)
type PickupDTO struct {
ID uint64 `json:"id"`
PickupNo string `json:"pickup_no"`
ListingID uint64 `json:"listing_id"`
ListingNo string `json:"listing_no"`
AccountID uint64 `json:"account_id"`
AccountTitle string `json:"account_title"`
ServerRegion string `json:"server_region"`
LoginPlatform string `json:"login_platform"`
OwnerID uint64 `json:"owner_id"`
OwnerPhone string `json:"owner_phone"`
AdminID uint64 `json:"admin_id"`
Operator string `json:"operator"`
Platform string `json:"platform"`
ThirdPartyOrderNo string `json:"third_party_order_no"`
ShopName string `json:"shop_name"`
RawShopName string `json:"raw_shop_name"`
AccountSource string `json:"account_source"`
SourceChannel string `json:"source_channel"`
SettlementMode string `json:"settlement_mode"`
ListingPriceCent int64 `json:"listing_price_cent"`
OrderAmountCent int64 `json:"order_amount_cent"`
DepositAmountCent int64 `json:"deposit_amount_cent"`
OwnerPriceCent int64 `json:"owner_price_cent"`
WebsiteProfitCent int64 `json:"website_profit_cent"`
ProfitAmountCent int64 `json:"profit_amount_cent"`
ProfitAdjustmentCent int64 `json:"profit_adjustment_cent"`
EffectiveProfitAmountCent int64 `json:"effective_profit_amount_cent"`
SellerRatio float64 `json:"seller_ratio"`
BuyerRatio float64 `json:"buyer_ratio"`
AccountSnapshot datatypes.JSON `json:"account_snapshot,omitempty"`
SettleAmountCent int64 `json:"settle_amount_cent"`
SettleAdjustmentCent int64 `json:"settle_adjustment_cent"`
EffectiveSettleAmountCent int64 `json:"effective_settle_amount_cent"`
Status string `json:"status"`
OfflineSettlementStatus string `json:"offline_settlement_status"`
OfflineSettlementRemark string `json:"offline_settlement_remark"`
OfflineSettledBy *uint64 `json:"offline_settled_by,omitempty"`
OfflineSettledAt *time.Time `json:"offline_settled_at,omitempty"`
Remark string `json:"remark"`
CompleteRemark string `json:"complete_remark"`
CreatedAt time.Time `json:"created_at"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
CancelledAt *time.Time `json:"cancelled_at,omitempty"`
}
type FinancialAdjustmentDTO struct {
ID uint64 `json:"id"`
PickupID uint64 `json:"pickup_id"`
ProfitDeltaCent int64 `json:"profit_delta_cent"`
SettleDeltaCent int64 `json:"settle_delta_cent"`
SettlementMode string `json:"settlement_mode"`
Status string `json:"status"`
Reason string `json:"reason"`
CreatedBy uint64 `json:"created_by"`
SettledBy *uint64 `json:"settled_by,omitempty"`
SettledAt *time.Time `json:"settled_at,omitempty"`
SettlementRemark string `json:"settlement_remark"`
CreatedAt time.Time `json:"created_at"`
}
type CreateRequest struct {
ListingID uint64 `json:"listing_id" binding:"required"`
Operator string `json:"operator" binding:"max=64"`
Platform string `json:"platform"`
ThirdPartyOrderNo string `json:"third_party_order_no" binding:"max=128"`
ShopName string `json:"shop_name" binding:"max=100"`
OrderAmountCent int64 `json:"order_amount_cent" binding:"min=0"`
DepositAmountCent int64 `json:"deposit_amount_cent" binding:"min=0"`
ProfitAmountCent int64 `json:"profit_amount_cent"`
Remark string `json:"remark"`
}
type CompleteRequest struct {
SettleAmountCent int64 `json:"settle_amount_cent" binding:"required,min=1"`
ProfitAmountCent *int64 `json:"profit_amount_cent"`
CompleteRemark string `json:"complete_remark"`
}
type OfflineSettlementRequest struct {
Remark string `json:"remark" binding:"max=255"`
}
type UpdateProfitRequest struct {
ProfitAmountCent int64 `json:"profit_amount_cent" binding:"min=0"`
Reason string `json:"reason"`
}
// FinancialAdjustmentRequest 按目标金额创建完成后的差额流水,至少提供一个金额。
type FinancialAdjustmentRequest struct {
ProfitAmountCent *int64 `json:"profit_amount_cent"`
SettleAmountCent *int64 `json:"settle_amount_cent"`
Reason string `json:"reason" binding:"required,max=255"`
}
type FinancialAdjustmentSettlementRequest struct {
Remark string `json:"remark" binding:"max=255"`
}
type CancelRequest struct {
Reason string `json:"reason" binding:"required"`
}
type AdminPickupQuery struct {
Page int
PageSize int
Keyword string
Status string
ShopName string
AccountSource string
OfflineSettlementStatus string
Operator string
ThirdPartyOrderNo string
StartTime *time.Time
EndTime *time.Time
}
type PickupShopDTO struct {
ID uint64 `json:"id"`
Name string `json:"name"`
Platform string `json:"platform"`
Status string `json:"status"`
SortOrder int `json:"sort_order"`
Remark string `json:"remark"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type CreatePickupShopRequest struct {
Name string `json:"name" binding:"required,max=100"`
Platform string `json:"platform" binding:"max=32"`
Status string `json:"status" binding:"omitempty,oneof=active disabled"`
SortOrder int `json:"sort_order"`
Remark string `json:"remark" binding:"max=255"`
}
type UpdatePickupShopRequest struct {
Name string `json:"name" binding:"required,max=100"`
Platform string `json:"platform" binding:"max=32"`
Status string `json:"status" binding:"required,oneof=active disabled"`
SortOrder int `json:"sort_order"`
Remark string `json:"remark" binding:"max=255"`
}
type PickupShopQuery struct {
Keyword string
Platform string
Status string
}
type PickupShopHistoricalItemDTO struct {
SourceName string `json:"source_name"`
Count int64 `json:"count"`
MappingStatus string `json:"mapping_status"` // standard, mapped, unmapped
TargetShopID uint64 `json:"target_shop_id,omitempty"`
TargetShopName string `json:"target_shop_name,omitempty"`
Remark string `json:"remark,omitempty"`
}
type PickupShopHistoricalStatsDTO struct {
Items []PickupShopHistoricalItemDTO `json:"items"`
TotalPickups int64 `json:"total_pickups"`
TotalShops int `json:"total_shops"`
StandardCount int `json:"standard_count"`
MappedCount int `json:"mapped_count"`
UnmappedCount int `json:"unmapped_count"`
}
type MapHistoricalShopsRequest struct {
FromShopNames []string `json:"from_shop_names" binding:"required,min=1"`
TargetShopName string `json:"target_shop_name" binding:"required,max=100"`
CreateTargetMissing bool `json:"create_target_missing"`
TargetPlatform string `json:"target_platform" binding:"max=32"`
Remark string `json:"remark" binding:"max=255"`
}
type MapHistoricalShopsResultDTO struct {
UpdatedPickupsCount int64 `json:"updated_pickups_count"`
TargetShopName string `json:"target_shop_name"`
TargetShopID uint64 `json:"target_shop_id"`
CreatedStandardShop bool `json:"created_standard_shop"`
}
type SellerPickupQuery struct {
Page int
PageSize int
Status string
}
type AvailableListingDTO struct {
ID uint64 `json:"id"`
ListingNo string `json:"listing_no"`
AccountID uint64 `json:"account_id"`
AccountTitle string `json:"account_title"`
ServerRegion string `json:"server_region"`
LoginPlatform string `json:"login_platform"`
OwnerID uint64 `json:"owner_id"`
OwnerPhone string `json:"owner_phone"`
ListingPriceCent int64 `json:"listing_price_cent"`
OwnerPriceCent int64 `json:"owner_price_cent"`
OwnerPurePriceCent int64 `json:"owner_pure_price_cent"`
OwnerExtraItemPriceCent int64 `json:"owner_extra_item_price_cent"`
OwnerTotalPriceCent int64 `json:"owner_total_price_cent"`
WebsiteProfitCent int64 `json:"website_profit_cent"`
SellerRatio float64 `json:"seller_ratio"`
BuyerRatio float64 `json:"buyer_ratio"`
AccountSource string `json:"account_source"`
IsExternalUpload bool `json:"is_external_upload"`
SourceChannel string `json:"source_channel"`
HandoffMode string `json:"handoff_mode"`
SettlementMode string `json:"settlement_mode"`
}
type AvailableListingQuery struct {
Page int
PageSize int
Keyword string
SourceType string
}
type PaginatedResult struct {
Items []PickupDTO `json:"items"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}
type AvailableListingsResult struct {
Items []AvailableListingDTO `json:"items"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}