Files
customer-server/dao/product_dao.go
2026-03-14 10:02:49 +08:00

186 lines
5.3 KiB
Go
Raw Permalink 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 dao
import (
"context"
"customer-server/model/dto"
"customer-server/model/entity"
"gitea.com/red-future/common/beans"
"gitea.com/red-future/common/db/mongo"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"go.mongodb.org/mongo-driver/v2/bson"
)
var Product = new(product)
type product struct{}
// Insert 插入产品
// 注意mongo.DB().Insert不会自动将生成的ID回写到原始对象
// 必须手动从返回的InsertedIDs中提取并赋值给data.Id否则后续访问data.Id会触发空指针异常
func (d *product) Insert(ctx context.Context, data *entity.Product) (id bson.ObjectID, err error) {
ids, err := mongo.DB().Insert(ctx, []interface{}{data}, entity.ProductCollection)
if err != nil {
return
}
// 从返回的ID列表中提取ObjectID并回写到data.Id
if len(ids) > 0 {
if oid, ok := ids[0].(bson.ObjectID); ok {
id = oid
data.Id = &oid // 回写ID到原始对象防止后续访问时空指针异常
}
}
return
}
// Update 更新产品
func (d *product) Update(ctx context.Context, req *dto.UpdateProductReq) (err error) {
objectId, err := bson.ObjectIDFromHex(req.Id)
if err != nil {
return
}
filter := bson.M{"_id": objectId, "isDeleted": false}
updateFields := bson.M{}
if !g.IsEmpty(req.Name) {
updateFields["name"] = req.Name
}
if !g.IsEmpty(req.Description) {
updateFields["description"] = req.Description
}
// 自动更新时间为当前时间
updateFields["updatedAt"] = gtime.Now().Time
if len(updateFields) > 0 {
_, err = mongo.DB().Update(ctx, filter, bson.M{"$set": updateFields}, entity.ProductCollection)
}
return
}
// Delete 软删除产品(设置 IsDeleted=true
func (d *product) Delete(ctx context.Context, req *dto.DeleteProductReq) (err error) {
objectId, err := bson.ObjectIDFromHex(req.Id)
if err != nil {
return
}
filter := bson.M{"_id": objectId, "isDeleted": false}
update := bson.M{"$set": bson.M{"isDeleted": true, "updatedAt": gtime.Now().Time}}
_, err = mongo.DB().Update(ctx, filter, update, entity.ProductCollection)
if err != nil {
return gerror.Wrap(err, "删除产品失败")
}
return
}
// buildListFilter 构建列表查询的过滤条件
func (d *product) buildListFilter(req *dto.ListProductReq) bson.M {
filter := bson.M{"isDeleted": false}
if !g.IsEmpty(req.Name) {
filter["name"] = bson.M{"$regex": req.Name}
}
return filter
}
// checkTotalCount 检查总数
func (d *product) checkTotalCount(ctx context.Context, filter bson.M) (total int64, err error) {
total, err = mongo.DB().Count(ctx, filter, entity.ProductCollection)
return
}
// FindByName 根据名称查询产品(用于去重检查)
func (d *product) FindByName(ctx context.Context, name string) (product *entity.Product, err error) {
filter := bson.M{
"name": name,
"isDeleted": false,
}
err = mongo.DB().FindOne(ctx, filter, &product, entity.ProductCollection)
if err != nil {
if err.Error() == "mongo: no documents in result" {
return nil, nil
}
return nil, err
}
return
}
// List 获取产品列表(排除已删除)
func (d *product) List(ctx context.Context, req *dto.ListProductReq) (list []*entity.Product, total int64, err error) {
// 构建查询过滤条件
filter := d.buildListFilter(req)
// 检查总数
total, err = d.checkTotalCount(ctx, filter)
if err != nil {
return
}
// 分页参数处理
pageNum := req.PageNum
if pageNum <= 0 {
pageNum = 1
}
pageSize := req.PageSize
if pageSize <= 0 {
pageSize = 20
}
// 使用统一的mongo.DB().Find方法支持分页和排序
page := &beans.Page{
PageNum: int64(pageNum),
PageSize: int64(pageSize),
}
orderBy := []beans.OrderBy{
{Field: "createdAt", Order: beans.Desc}, // 按创建时间倒序
}
_, err = mongo.DB().Find(ctx, filter, &list, entity.ProductCollection, page, orderBy)
return
}
// GetById 根据ID获取产品
func (d *product) GetById(ctx context.Context, id string) (product *entity.Product, err error) {
objectId, err := bson.ObjectIDFromHex(id)
if err != nil {
return
}
filter := bson.M{"_id": objectId, "isDeleted": false}
err = mongo.DB().FindOne(ctx, filter, &product, entity.ProductCollection)
return
}
// FindAllForExport 查询所有产品用于导出(不分页)
func (d *product) FindAllForExport(ctx context.Context, name string) (list []*entity.Product, err error) {
filter := bson.M{}
if !g.IsEmpty(name) {
filter["name"] = bson.M{"$regex": name, "$options": "i"} // 模糊查询,忽略大小写
}
// 使用 mongo.DB().Find会自动过滤租户和已删除数据
// 导出场景不分页设置足够大的PageSize
page := &beans.Page{
PageNum: 1,
PageSize: 100000, // 导出场景设置足够大的PageSize
}
orderBy := []beans.OrderBy{
{Field: "createdAt", Order: beans.Desc}, // 按创建时间倒序
}
_, err = mongo.DB().Find(ctx, filter, &list, entity.ProductCollection, page, orderBy)
return
}
// UpdateEntity 更新产品实体(用于绑定/解绑/同步等场景)
func (d *product) UpdateEntity(ctx context.Context, product *entity.Product) (err error) {
filter := bson.M{"_id": product.Id, "isDeleted": false}
// 将实体转换为bson.M
updateDoc := bson.M{}
data, _ := bson.Marshal(product)
bson.Unmarshal(data, &updateDoc)
_, err = mongo.DB().Update(ctx, filter, bson.M{"$set": updateDoc}, entity.ProductCollection)
return
}