zhangqian
2024-04-07 bd33bea0f3b44e608fcb4d9aa9d1f51a2f5bcf17
新增按仓库分组的发货准备接口
6个文件已修改
230 ■■■■■ 已修改文件
api/v1/salesDetails.go 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/docs.go 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/swagger.json 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/swagger.yaml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/response/salesDetails.go 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
router/salesDetails.go 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/salesDetails.go
@@ -290,6 +290,7 @@
type GetWarehouseProductInfoReq struct {
    SaleDetailID     int    `json:"saleDetailID,omitempty"`
    SaleDetailNumber string `json:"saleDetailNumber,omitempty"`
    GroupByWarehouse bool   `json:"groupByWarehouse"`
}
// GetDeliveryPrepareInfo
@@ -396,6 +397,133 @@
    ctx.OkWithDetailed(storeList)
}
// GetDeliveryPrepareInfoByWarehouse
// @Tags        SalesDetails
// @Summary    获取产品入库信息按仓库分组
// @Produce    application/json
// @Param        object     body GetWarehouseProductInfoReq    true    "明细编码"
// @Success    200    {object}    response.ListResponse
// @Router        /api/salesDetails/getDeliveryPrepareInfoByWarehouse [post]
func (s *SalesDetailsApi) GetDeliveryPrepareInfoByWarehouse(c *gin.Context) {
    var params GetWarehouseProductInfoReq
    ctx, ok := contextx.NewContext(c, &params)
    if !ok {
        return
    }
    if params.SaleDetailID == 0 {
        ctx.FailWithMsg(ecode.ParamsErr, "参数缺失")
        return
    }
    salesDetails, err := salesDetailsService.GetSalesDetails(params.SaleDetailID)
    if err == gorm.ErrRecordNotFound || salesDetails.Number != params.SaleDetailNumber {
        ctx.FailWithMsg(ecode.ParamsErr, "销售订单不存在")
        return
    }
    productMap := model.ProductMap(salesDetails.Products)
    client := product_inventory.NewProductInventoryServiceClient(grpc_init.ProductInventoryServiceConn)
    grpcResp, err := client.GetOrderInputAndOutputInfo(ctx.GetCtx(), &product_inventory.GetOrderInputAndOutputInfoRequest{
        Number: params.SaleDetailNumber,
    })
    if err != nil {
        if strings.Contains(err.Error(), "record not found") {
            ctx.Ok()
            return
        }
        logx.Errorf("GetOrderInputAndOutputInfo err: %v", err.Error())
        ctx.FailWithMsg(ecode.UnknownErr, "grpc调用错误")
        return
    }
    grpcOutputList := grpcResp.OutputList
    grpcInputList := grpcResp.InputList
    inputProductMap := make(map[int64]map[string]*response.StoreInfo)
    outputProductMap := make(map[int64]map[string]*response.OutputSimpleInfo)
    warehouseIds := make([]int64, 0)
    warehouseIdMap := make(map[int64]string, 0)
    for _, v := range grpcOutputList {
        if productMap[v.Number] == nil {
            continue
        }
        if outputProductMap[v.WareHouseID] == nil {
            outputProductMap[v.WareHouseID] = make(map[string]*response.OutputSimpleInfo)
        }
        if outputProductMap[v.WareHouseID][v.Number] == nil {
            simpleInfo := &response.OutputSimpleInfo{
                Number: v.Number,
            }
            amount, _ := decimal.NewFromString(v.Amount)
            simpleInfo.Amount = amount
            outputProductMap[v.WareHouseID][v.Number] = simpleInfo
        } else {
            amount, _ := decimal.NewFromString(v.Amount)
            outputProductMap[v.WareHouseID][v.Number].Amount = outputProductMap[v.WareHouseID][v.Number].Amount.Add(amount)
        }
    }
    for _, v := range grpcInputList {
        if _, ok := warehouseIdMap[v.WareHouseID]; !ok {
            warehouseIds = append(warehouseIds, v.WareHouseID)
            warehouseIdMap[v.WareHouseID] = v.Warehouse
        }
        if productMap[v.Number] == nil {
            continue
        }
        if inputProductMap[v.WareHouseID] == nil {
            inputProductMap[v.WareHouseID] = make(map[string]*response.StoreInfo)
        }
        if inputProductMap[v.WareHouseID][v.Number] == nil {
            storeInfo := &response.StoreInfo{
                Number:      v.Number,
                Name:        v.Name,
                OrderAmount: productMap[v.Number].Amount,
            }
            finishAmount, _ := decimal.NewFromString(v.Amount)
            storeInfo.FinishAmount = finishAmount
            storeInfo.AvailableAmount = finishAmount
            storeInfo.LeftAmount = storeInfo.OrderAmount
            inputProductMap[v.WareHouseID][v.Number] = storeInfo
        } else {
            finishAmount, _ := decimal.NewFromString(v.Amount)
            inputProductMap[v.WareHouseID][v.Number].FinishAmount = inputProductMap[v.WareHouseID][v.Number].FinishAmount.Add(finishAmount)
            inputProductMap[v.WareHouseID][v.Number].AvailableAmount = inputProductMap[v.WareHouseID][v.Number].FinishAmount
        }
    }
    data := make([]*response.StoreInfoWithWarehouse, 0)
    for _, houseId := range warehouseIds {
        storeList := make([]*response.StoreInfo, 0, len(salesDetails.Products))
        for _, product := range salesDetails.Products {
            storeInfo := inputProductMap[houseId][product.Number]
            if storeInfo == nil { //没有入库信息
                storeInfo = &response.StoreInfo{
                    Name:            product.Name,
                    Number:          product.Number,
                    OrderAmount:     product.Amount,
                    FinishAmount:    decimal.Decimal{},
                    LeftAmount:      product.Amount,
                    AvailableAmount: decimal.Decimal{},
                }
            } else { //有入库数量再查出库,算出未发货数量
                if outputProductMap[houseId][product.Number] != nil {
                    outputInfo := outputProductMap[houseId][product.Number]
                    storeInfo.LeftAmount = storeInfo.LeftAmount.Sub(outputInfo.Amount)           //剩余发货数量 = 订单数量 - 已发货数量
                    storeInfo.AvailableAmount = storeInfo.AvailableAmount.Sub(outputInfo.Amount) //可用数量 = 入库完成数量 - 已发货数量
                }
            }
            storeList = append(storeList, storeInfo)
        }
        data = append(data, &response.StoreInfoWithWarehouse{
            WarehouseId:   houseId,
            WarehouseName: warehouseIdMap[houseId],
            StoreInfoList: storeList,
        })
    }
    ctx.OkWithDetailed(data)
}
// ConfirmOutput
// @Tags        SalesDetails
// @Summary    确认发货
docs/docs.go
@@ -7205,6 +7205,36 @@
                }
            }
        },
        "/api/salesDetails/getDeliveryPrepareInfoByWarehouse": {
            "post": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "SalesDetails"
                ],
                "summary": "获取产品入库信息按仓库分组",
                "parameters": [
                    {
                        "description": "明细编码",
                        "name": "object",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v1.GetWarehouseProductInfoReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/response.ListResponse"
                        }
                    }
                }
            }
        },
        "/api/salesDetails/getProductInventoryInfo/{number}": {
            "get": {
                "produces": [
@@ -20159,6 +20189,9 @@
        "v1.GetWarehouseProductInfoReq": {
            "type": "object",
            "properties": {
                "groupByWarehouse": {
                    "type": "boolean"
                },
                "saleDetailID": {
                    "type": "integer"
                },
docs/swagger.json
@@ -7193,6 +7193,36 @@
                }
            }
        },
        "/api/salesDetails/getDeliveryPrepareInfoByWarehouse": {
            "post": {
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "SalesDetails"
                ],
                "summary": "获取产品入库信息按仓库分组",
                "parameters": [
                    {
                        "description": "明细编码",
                        "name": "object",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/v1.GetWarehouseProductInfoReq"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/response.ListResponse"
                        }
                    }
                }
            }
        },
        "/api/salesDetails/getProductInventoryInfo/{number}": {
            "get": {
                "produces": [
@@ -20147,6 +20177,9 @@
        "v1.GetWarehouseProductInfoReq": {
            "type": "object",
            "properties": {
                "groupByWarehouse": {
                    "type": "boolean"
                },
                "saleDetailID": {
                    "type": "integer"
                },
docs/swagger.yaml
@@ -6578,6 +6578,8 @@
    type: object
  v1.GetWarehouseProductInfoReq:
    properties:
      groupByWarehouse:
        type: boolean
      saleDetailID:
        type: integer
      saleDetailNumber:
@@ -11015,6 +11017,25 @@
      summary: 获取产品入库信息
      tags:
      - SalesDetails
  /api/salesDetails/getDeliveryPrepareInfoByWarehouse:
    post:
      parameters:
      - description: 明细编码
        in: body
        name: object
        required: true
        schema:
          $ref: '#/definitions/v1.GetWarehouseProductInfoReq'
      produces:
      - application/json
      responses:
        "200":
          description: OK
          schema:
            $ref: '#/definitions/response.ListResponse'
      summary: 获取产品入库信息按仓库分组
      tags:
      - SalesDetails
  /api/salesDetails/getProductInventoryInfo/{number}:
    get:
      parameters:
model/response/salesDetails.go
@@ -134,3 +134,9 @@
    Margin                  string          `json:"margin"`                  //毛利率
}
type StoreInfoWithWarehouse struct {
    WarehouseId   int64        `json:"warehouseId,omitempty"`
    WarehouseName string       `json:"warehouseName,omitempty"`
    StoreInfoList []*StoreInfo `json:"storeInfoList,omitempty"`
}
router/salesDetails.go
@@ -22,10 +22,11 @@
        salesDetailsRouter.GET("getApsProjectList", salesDetailsApi.GetApsProjectList)                          // 获取aps项目列表
        salesDetailsRouter.POST("sendSalesDetailsToOtherSystem", salesDetailsApi.SendSalesDetailsToOtherSystem) // 推送销售明细信息到其他系统                    // 创建产品出库信息
        salesDetailsRouter.POST("getDeliveryPrepareInfo", salesDetailsApi.GetDeliveryPrepareInfo) // 发货准备
        salesDetailsRouter.POST("getDeliveryList", salesDetailsApi.GetDeliveryList)               // 发货明细
        salesDetailsRouter.POST("confirmOutput", salesDetailsApi.ConfirmOutput)                   // 确认发货
        salesDetailsRouter.POST("confirmOutputOver", salesDetailsApi.ConfirmOutputOver)           // 发货完成
        salesDetailsRouter.POST("getDeliveryPrepareInfo", salesDetailsApi.GetDeliveryPrepareInfo)                       // 发货准备
        salesDetailsRouter.POST("getDeliveryPrepareInfoByWarehouse", salesDetailsApi.GetDeliveryPrepareInfoByWarehouse) // 发货准备,按仓库分组
        salesDetailsRouter.POST("getDeliveryList", salesDetailsApi.GetDeliveryList)                                     // 发货明细
        salesDetailsRouter.POST("confirmOutput", salesDetailsApi.ConfirmOutput)                                         // 确认发货
        salesDetailsRouter.POST("confirmOutputOver", salesDetailsApi.ConfirmOutputOver)                                 // 发货完成
    }
}