1. 排除商城直购(source_type=1):GMV和成本过滤条件从IN(1,2,3,4)改为IN(2,3,4) 2. 排除次卡免费使用订单(actual_amount=0):避免购买次卡和使用次卡双重计入GMV - source_type=4 一番赏使用次卡:1578单 44032元重复 - source_type=3 对对碰使用次卡:422单 7042元重复 - 合计去除51074元虚增GMV(29.1%) 3. 成本过滤条件同步修正:source_type IN(2,3,4),total_amount>0 修正后:GMV从175600降至124527元,毛利率从37.4%回到真实的11.8%
200 lines
5.2 KiB
Go
200 lines
5.2 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"strings"
|
||
|
||
"gorm.io/driver/mysql"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
func main() {
|
||
dsn := "root:bindbox2025kdy@tcp(150.158.78.154:3306)/dev_game?charset=utf8mb4&parseTime=True&loc=Local"
|
||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||
if err != nil {
|
||
fmt.Println("连接失败:", err)
|
||
return
|
||
}
|
||
|
||
channelID := 3
|
||
orderFilter := "users.channel_id = ? AND users.deleted_at IS NULL AND orders.status = 2 AND orders.actual_amount > 0 AND orders.source_type IN (1,2,3,4) AND (orders.ext_order_id = '' OR orders.ext_order_id IS NULL)"
|
||
|
||
// 1. actual_amount 统计
|
||
type AmountResult struct {
|
||
OrderCount int64
|
||
TotalCents int64
|
||
}
|
||
var ar AmountResult
|
||
db.Table("orders").
|
||
Joins("JOIN users ON users.id = orders.user_id").
|
||
Select("COUNT(DISTINCT orders.id) as order_count, COALESCE(SUM(orders.actual_amount), 0) as total_cents").
|
||
Where(orderFilter, channelID).
|
||
Scan(&ar)
|
||
|
||
fmt.Println("========================================")
|
||
fmt.Printf("渠道 %d 数据对比\n", channelID)
|
||
fmt.Println("========================================")
|
||
fmt.Println()
|
||
fmt.Println("【方式1】SUM(actual_amount) — 用户实际支付")
|
||
fmt.Printf(" 订单数: %d\n", ar.OrderCount)
|
||
fmt.Printf(" 金额: %d 分 = %.2f 元\n", ar.TotalCents, float64(ar.TotalCents)/100)
|
||
fmt.Println()
|
||
|
||
// 2. 取所有订单的 remark,Go 中解析
|
||
type RemarkRow struct {
|
||
Remark string
|
||
}
|
||
var remarks []RemarkRow
|
||
db.Table("orders").
|
||
Joins("JOIN users ON users.id = orders.user_id").
|
||
Select("orders.remark").
|
||
Where(orderFilter, channelID).
|
||
Scan(&remarks)
|
||
|
||
// 解析 remark 收集 activityIDs
|
||
type parsed struct {
|
||
activityID int64
|
||
count int64
|
||
}
|
||
var items []parsed
|
||
idSet := make(map[int64]struct{})
|
||
noRemarkCount := 0
|
||
|
||
for _, r := range remarks {
|
||
aid, cnt := parseRemark(r.Remark)
|
||
if aid > 0 {
|
||
items = append(items, parsed{activityID: aid, count: cnt})
|
||
idSet[aid] = struct{}{}
|
||
} else {
|
||
noRemarkCount++
|
||
}
|
||
}
|
||
|
||
// 批量查 price_draw(含软删除)
|
||
actIDs := make([]int64, 0, len(idSet))
|
||
for id := range idSet {
|
||
actIDs = append(actIDs, id)
|
||
}
|
||
|
||
type ActPrice struct {
|
||
ID int64
|
||
PriceDraw int64
|
||
}
|
||
priceMap := make(map[int64]int64)
|
||
if len(actIDs) > 0 {
|
||
var acts []ActPrice
|
||
db.Unscoped().Table("activities").
|
||
Select("id, price_draw").
|
||
Where("id IN ?", actIDs).
|
||
Find(&acts)
|
||
for _, a := range acts {
|
||
priceMap[a.ID] = a.PriceDraw
|
||
}
|
||
}
|
||
|
||
// 计算 price_draw × count
|
||
var totalPriceDraw int64
|
||
matchedCount := 0
|
||
unmatchedCount := 0
|
||
for _, item := range items {
|
||
if price, ok := priceMap[item.activityID]; ok {
|
||
totalPriceDraw += price * item.count
|
||
matchedCount++
|
||
} else {
|
||
unmatchedCount++
|
||
}
|
||
}
|
||
|
||
fmt.Println("【方式2】price_draw × count — 门票原价(当前实现)")
|
||
fmt.Printf(" 有效订单: %d (有 remark 且匹配活动)\n", matchedCount)
|
||
fmt.Printf(" 无 remark: %d\n", noRemarkCount)
|
||
fmt.Printf(" 活动不存在: %d\n", unmatchedCount)
|
||
fmt.Printf(" 金额: %d 分 = %.2f 元\n", totalPriceDraw, float64(totalPriceDraw)/100)
|
||
fmt.Println()
|
||
|
||
// 3. 差额
|
||
diff := totalPriceDraw - ar.TotalCents
|
||
fmt.Println("【差异分析】")
|
||
fmt.Printf(" price_draw×count - actual_amount = %d 分 = %.2f 元\n", diff, float64(diff)/100)
|
||
if diff > 0 {
|
||
fmt.Printf(" 说明: 用户总共享受了 %.2f 元优惠(优惠券/积分/折扣)\n", float64(diff)/100)
|
||
} else if diff < 0 {
|
||
fmt.Printf(" 说明: actual_amount 比 price_draw×count 多 %.2f 元(可能有额外费用)\n", float64(-diff)/100)
|
||
} else {
|
||
fmt.Println(" 说明: 两者完全一致,无优惠抵扣")
|
||
}
|
||
fmt.Println()
|
||
|
||
// 4. 抽样展示前10条差异订单
|
||
type DetailRow struct {
|
||
OrderID int64
|
||
ActualAmount int64
|
||
Remark string
|
||
}
|
||
var details []DetailRow
|
||
db.Table("orders").
|
||
Joins("JOIN users ON users.id = orders.user_id").
|
||
Select("orders.id as order_id, orders.actual_amount, orders.remark").
|
||
Where(orderFilter, channelID).
|
||
Limit(200).
|
||
Scan(&details)
|
||
|
||
fmt.Println("【差异订单抽样(前10条有差异的)】")
|
||
fmt.Printf("%-10s %-15s %-15s %-10s %s\n", "订单ID", "actual_amount", "price×count", "差额", "remark摘要")
|
||
fmt.Println(strings.Repeat("-", 90))
|
||
shown := 0
|
||
for _, d := range details {
|
||
aid, cnt := parseRemark(d.Remark)
|
||
if aid <= 0 {
|
||
continue
|
||
}
|
||
price, ok := priceMap[aid]
|
||
if !ok {
|
||
continue
|
||
}
|
||
priceTotal := price * cnt
|
||
orderDiff := priceTotal - d.ActualAmount
|
||
if orderDiff != 0 && shown < 10 {
|
||
remarkShort := d.Remark
|
||
if len(remarkShort) > 40 {
|
||
remarkShort = remarkShort[:40] + "..."
|
||
}
|
||
fmt.Printf("%-10d %-15d %-15d %-10d %s\n", d.OrderID, d.ActualAmount, priceTotal, orderDiff, remarkShort)
|
||
shown++
|
||
}
|
||
}
|
||
if shown == 0 {
|
||
fmt.Println(" (前200条订单中无差异)")
|
||
}
|
||
}
|
||
|
||
func parseRemark(rm string) (activityID, count int64) {
|
||
count = 1
|
||
parts := strings.Split(rm, "|")
|
||
for _, p := range parts {
|
||
if strings.HasPrefix(p, "lottery:activity:") {
|
||
activityID = parseInt64(p[17:])
|
||
} else if strings.HasPrefix(p, "activity:") {
|
||
activityID = parseInt64(p[9:])
|
||
} else if strings.HasPrefix(p, "count:") {
|
||
n := parseInt64(p[6:])
|
||
if n > 0 {
|
||
count = n
|
||
}
|
||
}
|
||
}
|
||
return
|
||
}
|
||
|
||
func parseInt64(s string) int64 {
|
||
var n int64
|
||
for _, c := range s {
|
||
if c >= '0' && c <= '9' {
|
||
n = n*10 + int64(c-'0')
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
return n
|
||
}
|