186 lines
5.3 KiB
Go
186 lines
5.3 KiB
Go
|
|
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
|
|||
|
|
}
|