package teamsalarysettlement import ( "encoding/json" "fmt" "strconv" "strings" ) // settlementUserID 只用于批量结算 HTTP 入参,兼容前端新合约的字符串 ID 和旧页面残留的数字 ID。 // 解析后仍以 int64 进入候选过滤和钱包结算,保证结算引擎内部只有一种精确 ID 表示。 type settlementUserID int64 func (v *settlementUserID) UnmarshalJSON(data []byte) error { raw := strings.TrimSpace(string(data)) if raw == "" || raw == "null" { *v = 0 return nil } if strings.HasPrefix(raw, `"`) { var text string if err := json.Unmarshal(data, &text); err != nil { return err } raw = strings.TrimSpace(text) if raw == "" { *v = 0 return nil } } parsed, err := strconv.ParseInt(raw, 10, 64) if err != nil { return fmt.Errorf("invalid settlement user id %q", raw) } *v = settlementUserID(parsed) return nil } func settlementUserIDValues(items []settlementUserID) []int64 { out := make([]int64, 0, len(items)) for _, item := range items { out = append(out, int64(item)) } return out } type userDTO struct { UserID string `json:"user_id"` DisplayUserID string `json:"display_user_id"` Username string `json:"username"` Avatar string `json:"avatar"` } type pendingDTO struct { PolicyType string `json:"policy_type"` UserID string `json:"user_id"` User userDTO `json:"user"` CycleKey string `json:"cycle_key"` RegionID int64 `json:"region_id"` RegionName string `json:"region_name"` PolicyID uint64 `json:"policy_id"` PolicyName string `json:"policy_name"` LevelNo int32 `json:"level_no"` IncomeUSDMinor int64 `json:"income_usd_minor"` IncomeUSD string `json:"income_usd"` SalaryUSDMinorTarget int64 `json:"salary_usd_minor_target"` SalaryUSDTarget string `json:"salary_usd_target"` SalaryUSDMinorDelta int64 `json:"salary_usd_minor_delta"` SalaryUSDDelta string `json:"salary_usd_delta"` SettledLevelNo int32 `json:"settled_level_no"` SettledSalaryUSDMinor int64 `json:"settled_salary_usd_minor"` SettledSalaryUSD string `json:"settled_salary_usd"` LastSettledIncomeUSDMinor int64 `json:"last_settled_income_usd_minor"` LastSettledIncomeUSD string `json:"last_settled_income_usd"` MonthClosedAtMS int64 `json:"month_closed_at_ms"` } type recordDTO struct { SettlementID string `json:"settlement_id"` CommandID string `json:"command_id"` TransactionID string `json:"transaction_id"` PolicyType string `json:"policy_type"` TriggerMode string `json:"trigger_mode"` UserID string `json:"user_id"` User userDTO `json:"user"` CycleKey string `json:"cycle_key"` RegionID int64 `json:"region_id"` PolicyID uint64 `json:"policy_id"` LevelNo int32 `json:"level_no"` IncomeUSDMinor int64 `json:"income_usd_minor"` IncomeUSD string `json:"income_usd"` SalaryUSDMinorDelta int64 `json:"salary_usd_minor_delta"` SalaryUSDDelta string `json:"salary_usd_delta"` Status string `json:"status"` Reason string `json:"reason"` CreatedAtMS int64 `json:"created_at_ms"` } type pendingQuery struct { Page int PageSize int PolicyType string TriggerMode string CycleKey string RegionID int64 CountryID int64 CountryCode string UserID int64 } type recordQuery struct { Page int PageSize int PolicyType string TriggerMode string CycleKey string Status string RegionID int64 CountryID int64 CountryCode string UserID int64 PolicyID uint64 StartAtMS int64 EndAtMS int64 } type settleRequest struct { PolicyType string `json:"policy_type"` TriggerMode string `json:"trigger_mode"` CycleKey string `json:"cycle_key"` RegionID int64 `json:"region_id"` CountryID int64 `json:"country_id"` CountryCode string `json:"country_code"` UserIDs []settlementUserID `json:"user_ids"` } type settleResultDTO struct { PolicyType string `json:"policy_type"` CycleKey string `json:"cycle_key"` RequestedCount int `json:"requested_count"` ProcessedCount int `json:"processed_count"` SuccessCount int `json:"success_count"` SkippedCount int `json:"skipped_count"` FailureCount int `json:"failure_count"` Records []recordDTO `json:"records"` }