feat: 添加账单软删除功能
- 新增删除按钮(带二次确认)到账单详情抽屉 - 后端实现软删除(设置 is_deleted 标记) - 所有查询方法自动过滤已删除记录 - 账单列表和复核页面都支持删除 - 版本更新至 1.2.0
This commit is contained in:
@@ -192,6 +192,9 @@ func (r *Repository) GetCleanedBills(filter map[string]interface{}) ([]model.Cle
|
||||
bsonFilter[k] = v
|
||||
}
|
||||
|
||||
// 排除已删除的记录
|
||||
bsonFilter["is_deleted"] = bson.M{"$ne": true}
|
||||
|
||||
// 按时间倒序排列
|
||||
opts := options.Find().SetSort(bson.D{{Key: "time", Value: -1}})
|
||||
|
||||
@@ -220,6 +223,9 @@ func (r *Repository) GetCleanedBillsPaged(filter map[string]interface{}, page, p
|
||||
bsonFilter[k] = v
|
||||
}
|
||||
|
||||
// 排除已删除的记录
|
||||
bsonFilter["is_deleted"] = bson.M{"$ne": true}
|
||||
|
||||
// 计算总数
|
||||
total, err := r.cleanedCollection.CountDocuments(ctx, bsonFilter)
|
||||
if err != nil {
|
||||
@@ -260,6 +266,9 @@ func (r *Repository) GetBillsAggregate(filter map[string]interface{}) (totalExpe
|
||||
bsonFilter[k] = v
|
||||
}
|
||||
|
||||
// 排除已删除的记录
|
||||
bsonFilter["is_deleted"] = bson.M{"$ne": true}
|
||||
|
||||
// 使用聚合管道按 income_expense 分组统计金额
|
||||
pipeline := mongo.Pipeline{
|
||||
{{Key: "$match", Value: bsonFilter}},
|
||||
@@ -300,6 +309,7 @@ func (r *Repository) GetBillsAggregate(filter map[string]interface{}) (totalExpe
|
||||
func (r *Repository) GetBillsNeedReview() ([]model.CleanedBill, error) {
|
||||
filter := map[string]interface{}{
|
||||
"review_level": bson.M{"$in": []string{"HIGH", "LOW"}},
|
||||
"is_deleted": bson.M{"$ne": true},
|
||||
}
|
||||
return r.GetCleanedBills(filter)
|
||||
}
|
||||
@@ -312,6 +322,8 @@ func (r *Repository) GetMonthlyStats() ([]model.MonthlyStat, error) {
|
||||
// 使用聚合管道按月份分组统计
|
||||
// 先按月份和收支类型分组,再汇总
|
||||
pipeline := mongo.Pipeline{
|
||||
// 排除已删除的记录
|
||||
{{Key: "$match", Value: bson.M{"is_deleted": bson.M{"$ne": true}}}},
|
||||
// 添加月份字段
|
||||
{{Key: "$addFields", Value: bson.D{
|
||||
{Key: "month", Value: bson.D{
|
||||
@@ -418,6 +430,34 @@ func (r *Repository) UpdateCleanedBillByID(id string, updates map[string]interfa
|
||||
return &updated, nil
|
||||
}
|
||||
|
||||
// DeleteCleanedBillByID 按 ID 软删除清洗后的账单(设置 is_deleted = true)
|
||||
func (r *Repository) DeleteCleanedBillByID(id string) error {
|
||||
if r.cleanedCollection == nil {
|
||||
return fmt.Errorf("cleaned collection not initialized")
|
||||
}
|
||||
|
||||
oid, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid id: %w", err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
filter := bson.M{"_id": oid}
|
||||
update := bson.M{"$set": bson.M{"is_deleted": true}}
|
||||
result, err := r.cleanedCollection.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
return fmt.Errorf("soft delete bill failed: %w", err)
|
||||
}
|
||||
|
||||
if result.MatchedCount == 0 {
|
||||
return repository.ErrNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetClient 获取 MongoDB 客户端(用于兼容旧代码)
|
||||
func (r *Repository) GetClient() *mongo.Client {
|
||||
return r.client
|
||||
|
||||
@@ -46,6 +46,9 @@ type BillRepository interface {
|
||||
// UpdateCleanedBillByID 按 ID 更新清洗后的账单,并返回更新后的记录
|
||||
UpdateCleanedBillByID(id string, updates map[string]interface{}) (*model.CleanedBill, error)
|
||||
|
||||
// DeleteCleanedBillByID 按 ID 删除清洗后的账单
|
||||
DeleteCleanedBillByID(id string) error
|
||||
|
||||
// CountRawByField 按字段统计原始数据数量
|
||||
CountRawByField(fieldName, value string) (int64, error)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user