diff --git a/server/handler/upload.go b/server/handler/upload.go index fe8571c..83d0c46 100644 --- a/server/handler/upload.go +++ b/server/handler/upload.go @@ -15,6 +15,7 @@ import ( "billai-server/config" "billai-server/model" + "billai-server/repository" "billai-server/service" ) @@ -254,22 +255,41 @@ func Upload(c *gin.Context) { } service.CleanupExtractedFiles(extractedFiles) - // 13. 返回成功响应 + // 13. 如果是京东账单,软删除其他来源中包含"京东-订单编号"的记录 + var jdRelatedDeleted int64 + if billType == "jd" { + repo := repository.GetRepository() + if repo != nil { + deleted, err := repo.SoftDeleteJDRelatedBills() + if err != nil { + fmt.Printf("⚠️ 软删除京东关联记录失败: %v\n", err) + } else if deleted > 0 { + jdRelatedDeleted = deleted + fmt.Printf("🗑️ 已软删除 %d 条其他来源中的京东关联记录\n", deleted) + } + } + } + + // 14. 返回成功响应 message := fmt.Sprintf("处理成功,新增 %d 条记录", cleanedCount) if dedupResult.DuplicateCount > 0 { message = fmt.Sprintf("处理成功,新增 %d 条,跳过 %d 条重复记录", cleanedCount, dedupResult.DuplicateCount) } + if jdRelatedDeleted > 0 { + message = fmt.Sprintf("%s,标记删除 %d 条重复的京东订单", message, jdRelatedDeleted) + } c.JSON(http.StatusOK, model.UploadResponse{ Result: true, Message: message, Data: &model.UploadData{ - BillType: billType, - FileURL: fmt.Sprintf("/download/%s", outputFileName), - FileName: outputFileName, - RawCount: rawCount, - CleanedCount: cleanedCount, - DuplicateCount: dedupResult.DuplicateCount, + BillType: billType, + FileURL: fmt.Sprintf("/download/%s", outputFileName), + FileName: outputFileName, + RawCount: rawCount, + CleanedCount: cleanedCount, + DuplicateCount: dedupResult.DuplicateCount, + JDRelatedDeleted: jdRelatedDeleted, }, }) } diff --git a/server/model/response.go b/server/model/response.go index 1879873..77a4ab8 100644 --- a/server/model/response.go +++ b/server/model/response.go @@ -2,12 +2,13 @@ package model // UploadData 上传响应数据 type UploadData struct { - BillType string `json:"bill_type,omitempty"` // alipay/wechat/jd - FileURL string `json:"file_url,omitempty"` // 下载链接 - FileName string `json:"file_name,omitempty"` // 文件名 - RawCount int `json:"raw_count,omitempty"` // 存储到原始数据集合的记录数 - CleanedCount int `json:"cleaned_count,omitempty"` // 存储到清洗后数据集合的记录数 - DuplicateCount int `json:"duplicate_count,omitempty"` // 重复跳过的记录数 + BillType string `json:"bill_type,omitempty"` // alipay/wechat/jd + FileURL string `json:"file_url,omitempty"` // 下载链接 + FileName string `json:"file_name,omitempty"` // 文件名 + RawCount int `json:"raw_count,omitempty"` // 存储到原始数据集合的记录数 + CleanedCount int `json:"cleaned_count,omitempty"` // 存储到清洗后数据集合的记录数 + DuplicateCount int `json:"duplicate_count,omitempty"` // 重复跳过的记录数 + JDRelatedDeleted int64 `json:"jd_related_deleted,omitempty"` // 软删除的京东关联记录数(其他来源中描述包含京东订单号的记录) } // UploadResponse 上传响应 diff --git a/server/repository/mongo/repository.go b/server/repository/mongo/repository.go index 013b6e5..ed14777 100644 --- a/server/repository/mongo/repository.go +++ b/server/repository/mongo/repository.go @@ -458,6 +458,41 @@ func (r *Repository) DeleteCleanedBillByID(id string) error { return nil } +// SoftDeleteJDRelatedBills 软删除描述中包含"京东-订单编号"的非京东账单 +// 用于避免京东账单与其他来源(微信、支付宝)账单重复计算 +func (r *Repository) SoftDeleteJDRelatedBills() (int64, error) { + if r.cleanedCollection == nil { + return 0, fmt.Errorf("cleaned collection not initialized") + } + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + // 筛选条件: + // 1. 账单类型不是 jd(只处理微信、支付宝等其他来源) + // 2. 描述中包含"京东-订单编号" + // 3. 尚未被删除 + filter := bson.M{ + "bill_type": bson.M{"$ne": "jd"}, + "description": bson.M{"$regex": "京东-订单编号", "$options": ""}, + "is_deleted": bson.M{"$ne": true}, + } + + update := bson.M{ + "$set": bson.M{ + "is_deleted": true, + "updated_at": time.Now(), + }, + } + + result, err := r.cleanedCollection.UpdateMany(ctx, filter, update) + if err != nil { + return 0, fmt.Errorf("soft delete JD related bills failed: %w", err) + } + + return result.ModifiedCount, nil +} + // GetClient 获取 MongoDB 客户端(用于兼容旧代码) func (r *Repository) GetClient() *mongo.Client { return r.client diff --git a/server/repository/repository.go b/server/repository/repository.go index edaf4f7..8230842 100644 --- a/server/repository/repository.go +++ b/server/repository/repository.go @@ -51,4 +51,9 @@ type BillRepository interface { // CountRawByField 按字段统计原始数据数量 CountRawByField(fieldName, value string) (int64, error) + + // SoftDeleteJDRelatedBills 软删除描述中包含"京东-订单编号"的非京东账单 + // 用于避免京东账单与其他来源(微信、支付宝)账单重复计算 + // 返回: 删除数量、错误 + SoftDeleteJDRelatedBills() (int64, error) }