2026-07-02 10:53:44 +08:00

80 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package wallet
import (
"context"
"strings"
"hyapp/pkg/appcode"
"hyapp/pkg/xerr"
"hyapp/services/wallet-service/internal/domain/ledger"
)
// FreezeSalaryWithdrawal 把工资从可用余额冻结到提现审核池;提交申请前必须先由 gateway 完成身份校验。
func (s *Service) FreezeSalaryWithdrawal(ctx context.Context, command ledger.SalaryWithdrawalCommand) (ledger.SalaryWithdrawalReceipt, error) {
if err := normalizeSalaryWithdrawalCommand(&command, false); err != nil {
return ledger.SalaryWithdrawalReceipt{}, err
}
if command.Reason == "" {
command.Reason = "salary withdrawal freeze"
}
if s.repository == nil {
return ledger.SalaryWithdrawalReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
command.AppCode = appcode.Normalize(command.AppCode)
ctx = appcode.WithContext(ctx, command.AppCode)
return s.repository.FreezeSalaryWithdrawal(ctx, command)
}
// SettleSalaryWithdrawal 在财务审核通过后扣减冻结金额;它只动 frozen不再次扣 available。
func (s *Service) SettleSalaryWithdrawal(ctx context.Context, command ledger.SalaryWithdrawalCommand) (ledger.SalaryWithdrawalReceipt, error) {
if err := normalizeSalaryWithdrawalCommand(&command, true); err != nil {
return ledger.SalaryWithdrawalReceipt{}, err
}
if command.Reason == "" {
command.Reason = "salary withdrawal approved"
}
if s.repository == nil {
return ledger.SalaryWithdrawalReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
command.AppCode = appcode.Normalize(command.AppCode)
ctx = appcode.WithContext(ctx, command.AppCode)
return s.repository.SettleSalaryWithdrawal(ctx, command)
}
// ReleaseSalaryWithdrawal 在审核拒绝或申请创建失败时把冻结工资返还到可用余额。
func (s *Service) ReleaseSalaryWithdrawal(ctx context.Context, command ledger.SalaryWithdrawalCommand) (ledger.SalaryWithdrawalReceipt, error) {
if err := normalizeSalaryWithdrawalCommand(&command, false); err != nil {
return ledger.SalaryWithdrawalReceipt{}, err
}
if command.Reason == "" {
command.Reason = "salary withdrawal released"
}
if s.repository == nil {
return ledger.SalaryWithdrawalReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
command.AppCode = appcode.Normalize(command.AppCode)
ctx = appcode.WithContext(ctx, command.AppCode)
return s.repository.ReleaseSalaryWithdrawal(ctx, command)
}
func normalizeSalaryWithdrawalCommand(command *ledger.SalaryWithdrawalCommand, requireOperator bool) error {
if command == nil || command.CommandID == "" || command.UserID <= 0 || command.SalaryUSDMinor <= 0 {
return xerr.New(xerr.InvalidArgument, "salary withdrawal command is incomplete")
}
if requireOperator && command.OperatorUserID <= 0 {
return xerr.New(xerr.InvalidArgument, "operator_user_id is required")
}
command.SalaryAssetType = strings.ToUpper(strings.TrimSpace(command.SalaryAssetType))
if !ledger.ValidSalaryAssetType(command.SalaryAssetType) {
return xerr.New(xerr.InvalidArgument, "salary_asset_type is invalid")
}
command.CommandID = strings.TrimSpace(command.CommandID)
command.Reason = strings.TrimSpace(command.Reason)
command.WithdrawalRef = strings.TrimSpace(command.WithdrawalRef)
command.WithdrawalApplicationID = strings.TrimSpace(command.WithdrawalApplicationID)
if len(command.CommandID) > 128 || len(command.Reason) > 512 || len(command.WithdrawalRef) > 128 || len(command.WithdrawalApplicationID) > 64 {
return xerr.New(xerr.InvalidArgument, "salary withdrawal text fields are too long")
}
return nil
}