119 lines
4.7 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 financewithdrawal
import (
"context"
"fmt"
"strings"
"time"
"hyapp-admin-server/internal/model"
"hyapp-admin-server/internal/repository"
)
type markdownSender interface {
SendMarkdown(ctx context.Context, title string, text string) error
}
// ReviewPendingNotifier 只通知“当前待谁处理”,不参与提现创建、冻结或审核事务。
type ReviewPendingNotifier interface {
NotifyReviewPending(ctx context.Context, application model.UserWithdrawalApplication, stage repository.WithdrawalApplicationReviewStage) error
}
type dingTalkReviewPendingNotifier struct {
sender markdownSender
}
func NewDingTalkReviewPendingNotifier(sender markdownSender) ReviewPendingNotifier {
if sender == nil {
return nil
}
return &dingTalkReviewPendingNotifier{sender: sender}
}
func (n *dingTalkReviewPendingNotifier) NotifyReviewPending(ctx context.Context, application model.UserWithdrawalApplication, stage repository.WithdrawalApplicationReviewStage) error {
if n == nil || n.sender == nil {
return nil
}
title, text := withdrawalReviewPendingMarkdown(application, stage)
return n.sender.SendMarkdown(ctx, title, text)
}
func withdrawalReviewPendingMarkdown(application model.UserWithdrawalApplication, stage repository.WithdrawalApplicationReviewStage) (string, string) {
stageName := "运营审核阶段"
pageURL := "https://admin-acc.global-interaction.com/finance/?view=withdrawalOperations"
if stage == repository.WithdrawalApplicationReviewStageFinance {
stageName = "财务审核阶段"
pageURL = "https://admin-acc.global-interaction.com/finance/?view=withdrawalFinance"
}
title := fmt.Sprintf("用户提现待处理【%s】", stageName)
lines := []string{
fmt.Sprintf("### 用户提现待处理【%s】", stageName),
"",
fmt.Sprintf("- 当前阶段:**%s**", stageName),
fmt.Sprintf("- 申请ID%d", application.ID),
fmt.Sprintf("- APP%s", withdrawalMarkdownValue(application.AppCode)),
fmt.Sprintf("- 来源系统:%s", withdrawalMarkdownValue(application.SourceSystem)),
fmt.Sprintf("- 来源单号:%s", withdrawalMarkdownValue(application.SourceApplicationID)),
fmt.Sprintf("- 用户ID%s", withdrawalMarkdownValue(application.UserID)),
fmt.Sprintf("- 申请金额:$ %s", withdrawalMarkdownValue(application.WithdrawAmount)),
fmt.Sprintf("- 提现方式:%s", withdrawalMarkdownValue(application.WithdrawMethod)),
fmt.Sprintf("- 提现地址:%s", withdrawalMarkdownValue(application.WithdrawAddress)),
fmt.Sprintf("- 申请时间:%s", formatWithdrawalNotifyMillis(application.CreatedAtMS)),
}
if hasWithdrawalPayoutSnapshot(application) {
// 协作通知展示来源申请时的不可变快照,财务不应在审核时按当前费率重算。
lines = append(lines,
fmt.Sprintf("- 手续费:$ %s费率 %s%%", withdrawalOptionalMarkdownValue(application.ServiceCharge), withdrawalOptionalMarkdownValue(application.ServiceChargeRatio)),
fmt.Sprintf("- 实际打款金额:$ %s", withdrawalOptionalMarkdownValue(application.ActualAmount)),
)
}
if stage == repository.WithdrawalApplicationReviewStageFinance {
// 财务提醒保留运营审核快照,接收人无需先打开后台就能确认这是一张已完成初审的申请。
lines = append(lines,
fmt.Sprintf("- 运营审核人:%s", withdrawalMarkdownValue(application.OperationsReviewerName)),
fmt.Sprintf("- 运营审核备注:%s", withdrawalMarkdownValue(application.OperationsAuditRemark)),
fmt.Sprintf("- 运营通过时间:%s", formatWithdrawalNotifyMillis(int64Value(application.OperationsReviewedAtMS))),
)
}
lines = append(lines, "- 后台地址:"+pageURL)
return title, strings.Join(lines, "\n")
}
func hasWithdrawalPayoutSnapshot(application model.UserWithdrawalApplication) bool {
return application.ServiceChargeRatio != nil || application.ServiceCharge != nil || application.ActualAmount != nil || application.ActualAmountMinor != nil
}
func withdrawalOptionalMarkdownValue(value *string) string {
if value == nil {
return "-"
}
return withdrawalMarkdownValue(*value)
}
func formatWithdrawalNotifyMillis(value int64) string {
if value <= 0 {
return "-"
}
// 协作消息按运营团队使用的北京时间展示;接口和数据库仍以 Unix 毫秒 UTC 事实为准。
return time.UnixMilli(value).In(time.FixedZone("UTC+8", 8*60*60)).Format("2006-01-02 15:04:05")
}
func int64Value(value *int64) int64 {
if value == nil {
return 0
}
return *value
}
func withdrawalMarkdownValue(value string) string {
value = strings.TrimSpace(value)
if value == "" {
return "-"
}
runes := []rune(value)
if len(runes) > 240 {
value = string(runes[:240]) + "..."
}
return strings.NewReplacer("\r", " ", "\n", " ", "\t", " ").Replace(value)
}