This commit is contained in:
2026-05-13 14:43:10 +08:00
parent 2312f54e1e
commit 3399de0dc5
49 changed files with 1637 additions and 287 deletions

View File

@@ -28,6 +28,7 @@ func NewAdminCreateProductLogic(ctx context.Context, svcCtx *svc.ServiceContext)
}
}
// AdminCreateProduct 创建产品后,在同一事务内写入一条 agent_product_config与代理产品配置列表一致
func (l *AdminCreateProductLogic) AdminCreateProduct(req *types.AdminCreateProductReq) (resp *types.AdminCreateProductResp, err error) {
// 1. 数据转换
data := &model.Product{
@@ -36,7 +37,7 @@ func (l *AdminCreateProductLogic) AdminCreateProduct(req *types.AdminCreateProdu
ProductEn: req.ProductEn,
Description: req.Description,
Notes: sql.NullString{String: req.Notes, Valid: req.Notes != ""},
CostPrice: req.CostPrice,
CostPrice: 0, // 成本由关联模块汇总,创建后为 0保存模块关联后写入
SellPrice: req.SellPrice,
}
@@ -51,7 +52,14 @@ func (l *AdminCreateProductLogic) AdminCreateProduct(req *types.AdminCreateProdu
}
productId = data.Id
// 2.2 同步创建代理产品配置(使用默认值)
// 2.2 同步创建代理产品配置(使用默认值);已存在则跳过(幂等)
if _, findErr := l.svcCtx.AgentProductConfigModel.FindOneByProductId(ctx, productId); findErr == nil {
return nil
} else if findErr != model.ErrNotFound {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"检查代理产品配置失败, err: %v, productId: %s", findErr, productId)
}
agentProductConfig := &model.AgentProductConfig{
Id: uuid.NewString(),
ProductId: productId,

View File

@@ -2,8 +2,10 @@ package admin_product
import (
"context"
"qnc-server/app/main/api/internal/svc"
"qnc-server/app/main/api/internal/types"
"qnc-server/app/main/model"
"qnc-server/common/xerr"
"github.com/pkg/errors"
@@ -25,12 +27,13 @@ func NewAdminDeleteProductLogic(ctx context.Context, svcCtx *svc.ServiceContext)
}
}
// AdminDeleteProduct 软删除产品后,在同一事务内软删除对应 agent_product_config与产品列表一致
func (l *AdminDeleteProductLogic) AdminDeleteProduct(req *types.AdminDeleteProductReq) (resp *types.AdminDeleteProductResp, err error) {
// 1. 查询记录是否存在
record, err := l.svcCtx.ProductModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"查找产品失败, err: %v, id: %d", err, req.Id)
"查找产品失败, err: %v, id: %s", err, req.Id)
}
// 2. 执行软删除(使用事务确保产品表和代理产品配置表同步)
@@ -39,20 +42,22 @@ func (l *AdminDeleteProductLogic) AdminDeleteProduct(req *types.AdminDeleteProdu
err = l.svcCtx.ProductModel.DeleteSoft(ctx, session, record)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"删除产品失败, err: %v, id: %d", err, req.Id)
"删除产品失败, err: %v, id: %s", err, record.Id)
}
// 2.2 同步软删除代理产品配置
agentProductConfig, err := l.svcCtx.AgentProductConfigModel.FindOneByProductId(ctx, req.Id)
if err != nil {
// 如果代理产品配置不存在,记录日志但不影响主流程
l.Infof("同步删除代理产品配置失败:代理产品配置不存在, productId: %d, err: %v", req.Id, err)
} else {
err = l.svcCtx.AgentProductConfigModel.DeleteSoft(ctx, session, agentProductConfig)
if err != nil {
// 2.2 同步软删除代理产品配置(按产品主键 product_id
agentProductConfig, findErr := l.svcCtx.AgentProductConfigModel.FindOneByProductId(ctx, record.Id)
switch {
case findErr == nil:
if err = l.svcCtx.AgentProductConfigModel.DeleteSoft(ctx, session, agentProductConfig); err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"同步删除代理产品配置失败, err: %v, productId: %d", err, req.Id)
"同步删除代理产品配置失败, err: %v, productId: %s", err, record.Id)
}
case findErr == model.ErrNotFound:
l.Infof("产品无对应代理产品配置,跳过同步删除, productId: %s", record.Id)
default:
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"查询代理产品配置失败, err: %v, productId: %s", findErr, record.Id)
}
return nil

View File

@@ -32,14 +32,21 @@ func (l *AdminGetProductDetailLogic) AdminGetProductDetail(req *types.AdminGetPr
"查找产品失败, err: %v, id: %d", err, req.Id)
}
// 2. 构建响应
// 2. 成本价为关联模块 cost_price 之和
costSum, err := l.svcCtx.ProductFeatureModel.SumFeatureCostPriceByProductId(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"汇总产品模块成本失败, err: %v, id: %s", err, req.Id)
}
// 3. 构建响应
resp = &types.AdminGetProductDetailResp{
Id: record.Id,
ProductName: record.ProductName,
ProductEn: record.ProductEn,
Description: record.Description,
Notes: record.Notes.String,
CostPrice: record.CostPrice,
CostPrice: costSum,
SellPrice: record.SellPrice,
CreateTime: record.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: record.UpdateTime.Format("2006-01-02 15:04:05"),

View File

@@ -105,6 +105,7 @@ func (l *AdminGetProductFeatureListLogic) AdminGetProductFeatureList(req *types.
FeatureId: item.FeatureId,
ApiId: feature.ApiId,
Name: feature.Name,
CostPrice: feature.CostPrice,
Sort: item.Sort,
Enable: item.Enable,
IsImportant: item.IsImportant,

View File

@@ -44,16 +44,26 @@ func (l *AdminGetProductListLogic) AdminGetProductList(req *types.AdminGetProduc
"查询产品列表失败, err: %v, req: %+v", err, req)
}
// 4. 构建响应列表
// 4. 构建响应列表(成本价为关联模块 cost_price 之和,非库表字段直读)
items := make([]types.ProductListItem, 0, len(list))
productIds := make([]string, 0, len(list))
for _, item := range list {
productIds = append(productIds, item.Id)
}
costByProduct, err := l.svcCtx.ProductFeatureModel.SumFeatureCostPriceByProductIds(l.ctx, productIds)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"汇总产品模块成本失败, err: %v, req: %+v", err, req)
}
for _, item := range list {
cost := costByProduct[item.Id]
listItem := types.ProductListItem{
Id: item.Id,
ProductName: item.ProductName,
ProductEn: item.ProductEn,
Description: item.Description,
Notes: item.Notes.String,
CostPrice: item.CostPrice,
CostPrice: cost,
SellPrice: item.SellPrice,
CreateTime: item.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: item.UpdateTime.Format("2006-01-02 15:04:05"),

View File

@@ -1,18 +1,20 @@
package admin_product
import (
"context"
"sync"
"qnc-server/app/main/api/internal/svc"
"qnc-server/app/main/api/internal/types"
"qnc-server/app/main/model"
"qnc-server/common/xerr"
"context"
"sync"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/mr"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/google/uuid"
"qnc-server/app/main/api/internal/logic/productcost"
"qnc-server/app/main/api/internal/svc"
"qnc-server/app/main/api/internal/types"
"qnc-server/app/main/model"
"qnc-server/common/xerr"
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/mr"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type AdminUpdateProductFeaturesLogic struct {
@@ -120,15 +122,15 @@ func (l *AdminUpdateProductFeaturesLogic) AdminUpdateProductFeatures(req *types.
return
}
} else {
// 新增关联
newFeature := &model.ProductFeature{
Id: uuid.NewString(),
ProductId: req.ProductId,
FeatureId: data.featureId,
Sort: data.newItem.Sort,
Enable: data.newItem.Enable,
IsImportant: data.newItem.IsImportant,
}
// 新增关联
newFeature := &model.ProductFeature{
Id: uuid.NewString(),
ProductId: req.ProductId,
FeatureId: data.featureId,
Sort: data.newItem.Sort,
Enable: data.newItem.Enable,
IsImportant: data.newItem.IsImportant,
}
_, err = l.svcCtx.ProductFeatureModel.Insert(ctx, session, newFeature)
if err != nil {
updateErr = errors.Wrapf(err, "新增产品功能关联失败, product_id: %d, feature_id: %d",
@@ -156,6 +158,10 @@ func (l *AdminUpdateProductFeaturesLogic) AdminUpdateProductFeatures(req *types.
"更新产品功能关联失败, err: %v, req: %+v", err, req)
}
if err := productcost.SyncProductCostFromModules(l.ctx, l.svcCtx, req.ProductId); err != nil {
return nil, err
}
// 5. 返回结果
return &types.AdminUpdateProductFeaturesResp{Success: true}, nil
}

View File

@@ -47,9 +47,6 @@ func (l *AdminUpdateProductLogic) AdminUpdateProduct(req *types.AdminUpdateProdu
if req.Notes != nil {
record.Notes = sql.NullString{String: *req.Notes, Valid: *req.Notes != ""}
}
if req.CostPrice != nil {
record.CostPrice = *req.CostPrice
}
if req.SellPrice != nil {
record.SellPrice = *req.SellPrice
}