|
@@ -3,7 +3,6 @@ package api
|
|
|
import (
|
|
|
"box-cost/db/model"
|
|
|
"box-cost/db/repo"
|
|
|
- "context"
|
|
|
"encoding/json"
|
|
|
"errors"
|
|
|
"fmt"
|
|
@@ -18,18 +17,18 @@ import (
|
|
|
|
|
|
// StageRequest 用于添加和更新stage的请求结构
|
|
|
type StageRequest struct {
|
|
|
- PlanId string `json:"planId"`
|
|
|
- PackId string `json:"packId"`
|
|
|
+ PlanId string `json:"planId"`
|
|
|
+ // PackId string `json:"packId"`
|
|
|
CompId string `json:"componentId"`
|
|
|
StageId string `json:"stageId,omitempty"`
|
|
|
Stages []*model.ComponentStage `json:"stages"`
|
|
|
}
|
|
|
|
|
|
// 更新计划和部件的价格
|
|
|
-func updatePrices(ctx context.Context, db *mongo.Collection, planId primitive.ObjectID, compId string) error {
|
|
|
+func updatePrices(c *gin.Context, db *mongo.Collection, planId primitive.ObjectID, compId string) error {
|
|
|
// 1. 获取计划详情
|
|
|
var plan model.ProductPlan
|
|
|
- err := db.FindOne(ctx, bson.M{"_id": planId}).Decode(&plan)
|
|
|
+ err := db.FindOne(c.Request.Context(), bson.M{"_id": planId}).Decode(&plan)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
@@ -45,7 +44,7 @@ func updatePrices(ctx context.Context, db *mongo.Collection, planId primitive.Ob
|
|
|
}
|
|
|
// 更新组件总价
|
|
|
if comp.Id == compId {
|
|
|
- _, err = db.UpdateOne(ctx,
|
|
|
+ _, err = db.UpdateOne(c.Request.Context(),
|
|
|
bson.M{"_id": planId, "pack.components.id": compId},
|
|
|
bson.M{"$set": bson.M{"pack.components.$.totalPrice": compPrice}})
|
|
|
if err != nil {
|
|
@@ -56,7 +55,7 @@ func updatePrices(ctx context.Context, db *mongo.Collection, planId primitive.Ob
|
|
|
}
|
|
|
|
|
|
// 3. 更新计划总价
|
|
|
- _, err = db.UpdateOne(ctx,
|
|
|
+ _, err = db.UpdateOne(c.Request.Context(),
|
|
|
bson.M{"_id": planId},
|
|
|
bson.M{"$set": bson.M{"totalPrice": &totalPrice}})
|
|
|
return err
|
|
@@ -96,7 +95,7 @@ func AddStage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
})
|
|
|
db := apictx.Svc.Mongo.GetCollection(repo.CollectionProductPlan)
|
|
|
|
|
|
- result, err := db.UpdateOne(apictx.CreateRepoCtx().Ctx,
|
|
|
+ result, err := db.UpdateOne(c.Request.Context(),
|
|
|
bson.M{"_id": planId},
|
|
|
update,
|
|
|
opts,
|
|
@@ -107,7 +106,7 @@ func AddStage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
}
|
|
|
|
|
|
// 更新价格
|
|
|
- err = updatePrices(apictx.CreateRepoCtx().Ctx, db, planId, req.CompId)
|
|
|
+ err = updatePrices(c, db, planId, req.CompId)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
@@ -153,7 +152,7 @@ func DeleteStage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
Filters: arrayFilters,
|
|
|
})
|
|
|
|
|
|
- result, err := db.UpdateOne(apictx.CreateRepoCtx().Ctx,
|
|
|
+ result, err := db.UpdateOne(c.Request.Context(),
|
|
|
bson.M{"_id": planId},
|
|
|
update,
|
|
|
opts,
|
|
@@ -164,7 +163,7 @@ func DeleteStage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
}
|
|
|
|
|
|
// 更新价格
|
|
|
- err = updatePrices(apictx.CreateRepoCtx().Ctx, db, planId, req.CompId)
|
|
|
+ err = updatePrices(c, db, planId, req.CompId)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
@@ -177,10 +176,68 @@ func DeleteStage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
return result, nil
|
|
|
}
|
|
|
|
|
|
+// 根据planId packId compentId stageId定位到到计划中的stage
|
|
|
+// 注意更新计划价格 组件价格
|
|
|
+// 根据planId packId compentId stageId定位到到计划中的stage
|
|
|
+// 注意更新计划价格 组件价格
|
|
|
+func updateStage(c *gin.Context, db *mongo.Collection, req *StageRequest) (interface{}, error) {
|
|
|
+ if len(req.PlanId) == 0 || len(req.CompId) == 0 || len(req.StageId) == 0 {
|
|
|
+ return nil, fmt.Errorf("planId, componentId and stageId are required")
|
|
|
+ }
|
|
|
+
|
|
|
+ planId, err := primitive.ObjectIDFromHex(req.PlanId)
|
|
|
+ if err != nil {
|
|
|
+ return nil, fmt.Errorf("invalid planId: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建更新
|
|
|
+ update := bson.M{
|
|
|
+ "$set": bson.M{
|
|
|
+ "pack.components.$[components].stages.$[stage]": req.Stages[0],
|
|
|
+ "updateTime": time.Now(),
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置数组过滤器
|
|
|
+ arrayFilters := options.ArrayFilters{
|
|
|
+ Filters: []interface{}{
|
|
|
+ bson.M{"components.id": req.CompId},
|
|
|
+ bson.M{"stage.id": req.StageId},
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ // 执行更新
|
|
|
+ opts := options.FindOneAndUpdate().
|
|
|
+ SetArrayFilters(arrayFilters).
|
|
|
+ SetReturnDocument(options.After)
|
|
|
+
|
|
|
+ result := db.FindOneAndUpdate(
|
|
|
+ c.Request.Context(),
|
|
|
+ bson.M{"_id": planId},
|
|
|
+ update,
|
|
|
+ opts,
|
|
|
+ )
|
|
|
+
|
|
|
+ if result.Err() != nil {
|
|
|
+ if result.Err() == mongo.ErrNoDocuments {
|
|
|
+ return nil, fmt.Errorf("plan or stage not found")
|
|
|
+ }
|
|
|
+ return nil, fmt.Errorf("failed to update stage: %v", result.Err())
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新价格
|
|
|
+ err = updatePrices(c, db, planId, req.CompId)
|
|
|
+ if err != nil {
|
|
|
+ return nil, fmt.Errorf("failed to update prices: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ return true, nil
|
|
|
+}
|
|
|
+
|
|
|
// 更新stages
|
|
|
// 根据planId packId compentId stageId定位到到计划中的stage
|
|
|
// 注意更新计划价格 组件价格
|
|
|
-func UpdateStage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
+func UpdateStages(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
var req StageRequest
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
return nil, err
|
|
@@ -198,8 +255,10 @@ func UpdateStage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
|
|
|
// 获取更新前的数据用于验证
|
|
|
db := apictx.Svc.Mongo.GetCollection(repo.CollectionProductPlan)
|
|
|
+ ctx := c.Request.Context()
|
|
|
+
|
|
|
var plan model.ProductPlan
|
|
|
- err = db.FindOne(apictx.CreateRepoCtx().Ctx, bson.M{"_id": planId}).Decode(&plan)
|
|
|
+ err = db.FindOne(ctx, bson.M{"_id": planId}).Decode(&plan)
|
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("failed to find plan: %v", err)
|
|
|
}
|
|
@@ -255,13 +314,13 @@ func UpdateStage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
|
|
|
// 执行批量更新
|
|
|
opts := options.BulkWrite().SetOrdered(false) // 允许并行执行
|
|
|
- result, err := db.BulkWrite(apictx.CreateRepoCtx().Ctx, models, opts)
|
|
|
+ result, err := db.BulkWrite(c.Request.Context(), models, opts)
|
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("failed to update stages: %v", err)
|
|
|
}
|
|
|
|
|
|
// 更新价格
|
|
|
- err = updatePrices(apictx.CreateRepoCtx().Ctx, db, planId, req.CompId)
|
|
|
+ err = updatePrices(c, db, planId, req.CompId)
|
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("failed to update prices: %v", err)
|
|
|
}
|
|
@@ -297,6 +356,7 @@ func UpdatePlanfileds(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
Total: req.Total,
|
|
|
CreateUser: req.CreateUser,
|
|
|
Name: req.Name,
|
|
|
+ UpdateTime: time.Now(),
|
|
|
})
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
@@ -328,7 +388,7 @@ func AddCompnonet(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
newTotalPrice := component.TotalPrice
|
|
|
oldPlan := &model.ProductPlan{}
|
|
|
db := apictx.Svc.Mongo.GetCollection(repo.CollectionProductPlan)
|
|
|
- if err := db.FindOne(c, bson.M{"_id": planId}).Decode(&oldPlan); err != nil {
|
|
|
+ if err := db.FindOne(c.Request.Context(), bson.M{"_id": planId}).Decode(&oldPlan); err != nil {
|
|
|
return nil, err
|
|
|
} else if oldPlan.TotalPrice != nil {
|
|
|
newTotalPrice += *oldPlan.TotalPrice
|
|
@@ -347,7 +407,7 @@ func AddCompnonet(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
}
|
|
|
|
|
|
filter := bson.M{"_id": planId}
|
|
|
- result := db.FindOneAndUpdate(c, filter, update)
|
|
|
+ result := db.FindOneAndUpdate(c.Request.Context(), filter, update)
|
|
|
if result.Err() != nil {
|
|
|
return nil, result.Err()
|
|
|
}
|
|
@@ -376,7 +436,7 @@ func DeleteCompnonet(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
// Find the component to be deleted and its price
|
|
|
db := apictx.Svc.Mongo.GetCollection(repo.CollectionProductPlan)
|
|
|
var componentPrice float64
|
|
|
- if err := db.FindOne(c, bson.M{"_id": planId}).Decode(&oldPlan); err != nil {
|
|
|
+ if err := db.FindOne(c.Request.Context(), bson.M{"_id": planId}).Decode(&oldPlan); err != nil {
|
|
|
return nil, err
|
|
|
} else if oldPlan.Pack != nil {
|
|
|
for _, comp := range oldPlan.Pack.Components {
|
|
@@ -409,7 +469,7 @@ func DeleteCompnonet(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
}
|
|
|
|
|
|
filter := bson.M{"_id": planId}
|
|
|
- result := db.FindOneAndUpdate(c, filter, update)
|
|
|
+ result := db.FindOneAndUpdate(c.Request.Context(), filter, update)
|
|
|
if result.Err() != nil {
|
|
|
return nil, result.Err()
|
|
|
}
|
|
@@ -422,7 +482,12 @@ func DeleteCompnonet(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
return true, nil
|
|
|
}
|
|
|
|
|
|
-func UpdateCompnonetName(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
+type UpdateCompnonetReq struct {
|
|
|
+ Name string `json:"name,omitempty"`
|
|
|
+ Stages []*model.ComponentStage `json:"stages,omitempty"`
|
|
|
+}
|
|
|
+
|
|
|
+func UpdateCompnonet(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
_planId := c.Param("id")
|
|
|
planId, _ := primitive.ObjectIDFromHex(_planId)
|
|
|
if planId.IsZero() {
|
|
@@ -433,31 +498,50 @@ func UpdateCompnonetName(c *gin.Context, apictx *ApiSession) (interface{}, error
|
|
|
return nil, fmt.Errorf("componentId is invalid")
|
|
|
}
|
|
|
|
|
|
- var nameUpdate struct {
|
|
|
- Name string `json:"name"`
|
|
|
- }
|
|
|
+ var nameUpdate UpdateCompnonetReq
|
|
|
if err := c.ShouldBindJSON(&nameUpdate); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
+ // 检查是否有需要更新的字段
|
|
|
+ if len(nameUpdate.Name) == 0 && len(nameUpdate.Stages) == 0 {
|
|
|
+ return nil, fmt.Errorf("no fields to update")
|
|
|
+ }
|
|
|
+
|
|
|
+ db := apictx.Svc.Mongo.GetCollection(repo.CollectionProductPlan)
|
|
|
update := bson.M{
|
|
|
"$set": bson.M{
|
|
|
- "pack.components.$.name": nameUpdate.Name,
|
|
|
- "updateTime": time.Now(),
|
|
|
+ "updateTime": time.Now(),
|
|
|
},
|
|
|
}
|
|
|
|
|
|
+ if len(nameUpdate.Name) > 0 {
|
|
|
+ update["$set"].(bson.M)["pack.components.$.name"] = nameUpdate.Name
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(nameUpdate.Stages) > 0 {
|
|
|
+ update["$set"].(bson.M)["pack.components.$.stages"] = nameUpdate.Stages
|
|
|
+ }
|
|
|
+
|
|
|
filter := bson.M{
|
|
|
"_id": planId,
|
|
|
"pack.components.id": componentId,
|
|
|
}
|
|
|
- db := apictx.Svc.Mongo.GetCollection(repo.CollectionProductPlan)
|
|
|
- result := db.FindOneAndUpdate(c, filter, update)
|
|
|
+
|
|
|
+ result := db.FindOneAndUpdate(c.Request.Context(), filter, update)
|
|
|
if result.Err() != nil {
|
|
|
return nil, result.Err()
|
|
|
}
|
|
|
|
|
|
- // 获取更新后的数据并记录历史
|
|
|
+ // 如果更新了stages,需要更新价格
|
|
|
+ if len(nameUpdate.Stages) > 0 {
|
|
|
+ err := updatePrices(c, db, planId, componentId)
|
|
|
+ if err != nil {
|
|
|
+ return nil, fmt.Errorf("failed to update prices: %v", err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 记录历史
|
|
|
_, err := AddPlanHistory(c, apictx, _planId)
|
|
|
if err != nil {
|
|
|
fmt.Println("记录历史失败:", err)
|
|
@@ -467,7 +551,11 @@ func UpdateCompnonetName(c *gin.Context, apictx *ApiSession) (interface{}, error
|
|
|
}
|
|
|
|
|
|
// 记录历史
|
|
|
-func AddPlanHistory(c *gin.Context, apictx *ApiSession, planId string) (interface{}, error) {
|
|
|
+func AddPlanHistory(c *gin.Context, apictx *ApiSession, planId string, ht ...string) (interface{}, error) {
|
|
|
+ htype := "update"
|
|
|
+ if len(ht) > 0 {
|
|
|
+ htype = ht[0]
|
|
|
+ }
|
|
|
// 获取更新后的数据并记录历史
|
|
|
newPlan := &model.ProductPlan{}
|
|
|
found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
|
|
@@ -493,7 +581,7 @@ func AddPlanHistory(c *gin.Context, apictx *ApiSession, planId string) (interfac
|
|
|
TargetId: planId,
|
|
|
Path: c.Request.URL.Path,
|
|
|
Collection: repo.CollectionProductPlan,
|
|
|
- Type: "update",
|
|
|
+ Type: htype,
|
|
|
Content: string(newPlanBytes),
|
|
|
CreateTime: time.Now(),
|
|
|
}
|