package controllers
|
|
import (
|
"context"
|
"errors"
|
"fmt"
|
"github.com/gin-gonic/gin"
|
uuid "github.com/satori/go.uuid"
|
"github.com/shopspring/decimal"
|
"github.com/xuri/excelize/v2"
|
"gorm.io/gorm"
|
"sort"
|
"strconv"
|
"strings"
|
"time"
|
"wms/conf"
|
"wms/constvar"
|
"wms/extend/code"
|
"wms/extend/util"
|
"wms/middleware"
|
"wms/models"
|
"wms/pkg/logx"
|
"wms/pkg/mysqlx"
|
"wms/pkg/structx"
|
"wms/proto/client"
|
"wms/proto/init_client"
|
"wms/proto/inventory_order"
|
"wms/proto/product_inventory"
|
"wms/proto/purchase_wms"
|
"wms/proto/supplier"
|
"wms/request"
|
"wms/response"
|
"wms/service"
|
"wms/utils/http"
|
"wms/utils/upload"
|
)
|
|
type OperationController struct {
|
}
|
|
// Add
|
// @Tags 入库/出库
|
// @Summary 添加入库/出库
|
// @Produce application/json
|
// @Param object body request.AddOperation true "入库/出库信息"
|
// @Success 200 {object} util.Response "成功"
|
// @Router /api-wms/v1/operation/operation [post]
|
func (slf OperationController) Add(c *gin.Context) {
|
var reqParams request.AddOperation
|
var params models.Operation
|
|
if err := c.BindJSON(&reqParams); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误")
|
return
|
}
|
if err := structx.AssignTo(reqParams, ¶ms); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "数据转换错误"+err.Error())
|
return
|
}
|
if err := slf.CheckParams(params); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
|
if CheckDetailsRepeat(params.Details) {
|
util.ResponseFormat(c, code.RequestParamError, "明细中不能存在重复的产品")
|
return
|
}
|
|
if params.BaseOperationType != constvar.BaseOperationTypeAdjust {
|
if err := slf.FormatLocation(¶ms); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
|
var operationType *models.OperationType
|
var err error
|
if params.OperationTypeId == 0 {
|
operationType, err := models.NewOperationTypeSearch().
|
SetWarehouseId(params.WarehouseId).SetBaseOperationType(params.BaseOperationType).
|
First()
|
if err != nil || params.WarehouseId != operationType.WarehouseId {
|
util.ResponseFormat(c, code.RequestParamError, "参数缺失")
|
return
|
}
|
} else {
|
operationType, err = models.NewOperationTypeSearch().SetID(uint(params.OperationTypeId)).First()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
}
|
params.BaseOperationType = operationType.BaseOperationType
|
params.WarehouseId = operationType.WarehouseId
|
}
|
|
if params.DealerType == "" {
|
CheckInventoryDealerType(¶ms)
|
}
|
|
userInfo := middleware.GetUserInfo(c)
|
if userInfo == nil {
|
util.ResponseFormat(c, code.SetStatusError, "登录用户信息为空,请登录后重试!")
|
return
|
}
|
params.CreatedBy = userInfo.Username
|
params.Status = constvar.OperationStatus_Ready
|
//params.Number = strconv.FormatInt(time.Now().Unix(), 10)
|
|
for _, detail := range params.Details {
|
detail.BaseOperationType = params.BaseOperationType
|
}
|
|
var numberNum int64
|
if err := mysqlx.GetDB().Model(&models.Operation{}).Where("number=?", params.Number).Count(&numberNum).Error; err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
if numberNum > 0 {
|
util.ResponseFormat(c, code.RequestParamError, "单号已存在")
|
return
|
}
|
err := models.WithTransaction(func(db *gorm.DB) error {
|
if err := models.NewOperationSearch().Create(¶ms); err != nil {
|
return err
|
}
|
/*od := params.Details
|
for _, v := range od {
|
//material, err := models.NewMaterialSearch().SetID(v.ProductId).First()
|
//if err != nil {return err}
|
material := new(models.Material)
|
material.ID = v.ProductId
|
material.Cost = v.Cost
|
material.SalePrice = v.SalePrice
|
if err := models.NewMaterialSearch().SetOrm(db).Update(material); err != nil {
|
return err
|
}
|
}*/
|
return nil
|
})
|
|
if err != nil {
|
logx.Errorf("Operation create err: %v", err)
|
util.ResponseFormat(c, code.SaveFail, "添加失败:"+err.Error())
|
return
|
}
|
util.ResponseFormat(c, code.Success, "添加成功")
|
}
|
|
func CheckInventoryDealerType(params *models.Operation) {
|
var dictType constvar.MiniDictType
|
dictName := "其他"
|
switch params.BaseOperationType {
|
case constvar.BaseOperationTypeIncoming:
|
dictType = constvar.StorageType
|
//dictName = dictName + "入库"
|
case constvar.BaseOperationTypeOutgoing:
|
dictType = constvar.StockoutType
|
//dictName = dictName + "出库"
|
case constvar.BaseOperationTypeInternal:
|
dictType = constvar.TransferType
|
//dictName = dictName + "调拨"
|
case constvar.BaseOperationTypeDisuse:
|
dictType = constvar.DisuseType
|
//dictName = dictName + "报废"
|
case constvar.BaseOperationTypeAdjust:
|
dictType = constvar.TakeStockType
|
//dictName = dictName + "盘点"
|
default:
|
return
|
}
|
miniDict, err := models.NewMiniDictSearch().SetType(dictType).SetName(dictName).First()
|
if err == gorm.ErrRecordNotFound {
|
miniDict = &models.MiniDict{
|
Type: dictType,
|
Name: dictName,
|
}
|
models.NewMiniDictSearch().Create(miniDict)
|
}
|
params.DealerType = miniDict.Name
|
}
|
|
func CheckDetailsRepeat(details []*models.OperationDetails) bool {
|
var detailIDs []string
|
var tempID string
|
for _, v := range details {
|
detailIDs = append(detailIDs, v.ProductId)
|
}
|
sort.Strings(detailIDs)
|
for _, v := range detailIDs {
|
if v != tempID {
|
tempID = v
|
} else {
|
return true
|
}
|
}
|
return false
|
}
|
|
// FormatLocation 位置检查
|
func (slf OperationController) FormatLocation(params *models.Operation) error {
|
operationType, err := models.NewOperationTypeSearch().SetID(uint(params.OperationTypeId)).First()
|
if err != nil {
|
return err
|
}
|
if operationType.BaseOperationType == constvar.BaseOperationTypeIncoming {
|
location, err := models.NewLocationSearch().SetType(int(constvar.LocationTypeVendor)).First()
|
if err != nil {
|
return err
|
}
|
for k, v := range params.Details {
|
params.Details[k].FromLocationID = location.Id
|
if v.ToLocationID == 0 {
|
params.Details[k].ToLocationID = params.LocationID
|
}
|
}
|
|
}
|
if operationType.BaseOperationType == constvar.BaseOperationTypeOutgoing {
|
location, err := models.NewLocationSearch().SetType(int(constvar.LocationTypeCustomer)).First()
|
if err != nil {
|
return err
|
}
|
for k, v := range params.Details {
|
params.Details[k].ToLocationID = location.Id
|
if v.FromLocationID == 0 {
|
return errors.New("请选择出库位置")
|
}
|
}
|
|
}
|
if operationType.BaseOperationType == constvar.BaseOperationTypeInternal {
|
for _, v := range params.Details {
|
if v.ToLocationID == 0 {
|
return errors.New("请选择目标位置")
|
}
|
if v.FromLocationID == 0 {
|
return errors.New("请选择源位置")
|
}
|
}
|
}
|
return nil
|
}
|
|
func (slf OperationController) CheckParams(params models.Operation) error {
|
/*if params.SourceNumber == "" {
|
return errors.New("请填入源单号")
|
}*/
|
|
if params.Number == "" {
|
return errors.New("请填入单号")
|
}
|
|
if params.OperationTypeId == 0 && int(params.BaseOperationType) == 0 {
|
return errors.New("未识别该记录类型1")
|
} else if params.OperationTypeId == 0 && params.BaseOperationType != 0 && params.WarehouseId == 0 {
|
return errors.New("未识别该记录类型2")
|
}
|
|
if params.OperationDate == "" {
|
return errors.New("请选择安排日期")
|
}
|
|
//if params.LocationID == 0 {
|
// return errors.New("请选择源位置")
|
//}
|
|
if len(params.Details) <= 0 {
|
return errors.New("请添加明细信息")
|
}
|
|
//检查明细部分
|
for _, v := range params.Details {
|
if v.ProductId == "" {
|
return errors.New("productID为空")
|
}
|
//if v.ProductName == "" {
|
// return errors.New("产品名称异常")
|
//}
|
if v.Amount.IsNegative() {
|
return errors.New("产品数量出错")
|
}
|
}
|
|
return nil
|
}
|
|
// GetOperationInfo
|
// @Tags 入库/出库
|
// @Summary 操作详情接口
|
// @Produce application/json
|
// @Param id path string true "id"
|
// @Param Authorization header string true "token"
|
// @Success 200 {object} util.Response{data=models.Operation} "成功"
|
// @Router /api-wms/v1/operation/getOperationInfo/{id} [get]
|
func (slf OperationController) GetOperationInfo(c *gin.Context) {
|
number := c.Param("id")
|
if number == "" {
|
util.ResponseFormat(c, code.RequestParamError, "参数解析失败,参数不能为空")
|
return
|
}
|
id, _ := strconv.Atoi(number)
|
operation, err := models.NewOperationSearch().SetID(id).SetPreload(true).First()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
|
if operation.BaseOperationType == constvar.BaseOperationTypeOutgoing || operation.BaseOperationType == constvar.BaseOperationTypeInternal { //查询实时在库库存
|
productIds := make([]string, 0)
|
locationIds := make([]int, 0)
|
for _, v := range operation.Details {
|
productIds = append(productIds, v.ProductId)
|
locationIds = append(locationIds, v.FromLocationID)
|
}
|
locationAmountMap, err := service.GetLocationAmounts(productIds, locationIds)
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "查询产品库存错误")
|
return
|
}
|
for _, v := range operation.Details {
|
if locationAmountMap[v.ProductId] != nil {
|
v.StockAmount = locationAmountMap[v.ProductId][v.FromLocationID]
|
}
|
}
|
}
|
|
util.ResponseFormat(c, code.Success, operation)
|
}
|
|
// List
|
// @Tags 入库/出库
|
// @Summary 入库/出库列表
|
// @Produce application/json
|
// @Param object body request.OperationList true "查询参数"
|
// @Success 200 {object} util.ResponseList{data=[]models.Operation} "成功"
|
// @Router /api-wms/v1/operation/list [post]
|
func (slf OperationController) List(c *gin.Context) {
|
var params request.OperationList
|
if err := c.BindJSON(¶ms); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误:"+err.Error())
|
return
|
}
|
if err := slf.CheckListParams(¶ms); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
search := models.NewOperationSearch()
|
search.SetPage(params.Page, params.PageSize)
|
if params.Number != "" {
|
search.SetKeyword(params.Number)
|
}
|
if int(params.Status) != 0 {
|
search.SetStatus(params.Status)
|
}
|
materials, err := models.NewMaterialSearch().FindNotTotal()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestError, "查找失败:"+err.Error())
|
return
|
}
|
costMap := make(map[string]decimal.Decimal)
|
salePriceMap := make(map[string]decimal.Decimal)
|
for _, material := range materials {
|
costMap[material.ID] = material.Cost
|
salePriceMap[material.ID] = material.SalePrice
|
}
|
list, total, err := search.SetOperationTypeId(params.OperationTypeId).
|
SetBaseOperationType(params.BaseOperationType).
|
SetPreload(true).SetOrder("created_at desc").Find()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestError, "查找失败:"+err.Error())
|
return
|
}
|
//userList, err := user.GetUserList()
|
//userMap := make(map[string]string)
|
//if err == nil {
|
// for _, user := range userList {
|
// userMap[user.UserName] = user.NickName
|
// }
|
//}
|
userInfo := middleware.GetUserInfo(c)
|
for _, v := range list {
|
v.CreatedBy = userInfo.NickName
|
//if err == nil {
|
if userInfo != nil {
|
// v.CreatedBy = userMap[v.CreatedBy]
|
// v.CheckedBy = userMap[v.CheckedBy]
|
v.CheckedBy = userInfo.NickName
|
}
|
for _, v1 := range v.Details {
|
//v1.SalePrice = decimal.NewFromFloat(1.2345)
|
//v1.Cost = decimal.NewFromFloat(9.678)
|
v1.SalePrice = v1.Cost
|
v1.Cost = v1.SalePrice
|
}
|
}
|
|
util.ResponseFormatListWithPage(c, code.Success, list, int(total), params.Page, params.PageSize)
|
}
|
|
func (slf OperationController) CheckListParams(params *request.OperationList) error {
|
if !params.PageInfo.Check() {
|
return errors.New("数据分页信息错误")
|
}
|
if params.OperationTypeId == 0 && params.BaseOperationType == 0 {
|
return errors.New("operationTypeId和baseOperationType不能同时为0")
|
}
|
return nil
|
}
|
|
// Update
|
// @Tags 入库/出库
|
// @Summary 修改入库/出库信息
|
// @Produce application/json
|
// @Param object body request.UpdateOperation true "入库信息"
|
// @Success 200 {object} util.Response "成功"
|
// @Router /api-wms/v1/operation/update [post]
|
func (slf OperationController) Update(c *gin.Context) {
|
var reqParams request.UpdateOperation
|
var params models.Operation
|
if err := c.BindJSON(&reqParams); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误:"+err.Error())
|
return
|
}
|
if reqParams.Status != constvar.OperationStatus_Ready {
|
util.ResponseFormat(c, code.RequestParamError, "该入库信息已完成,无法进行修改")
|
return
|
}
|
if err := structx.AssignTo(reqParams, ¶ms); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "数据转换错误"+err.Error())
|
return
|
}
|
if err := slf.CheckParams(params); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
if CheckDetailsRepeat(params.Details) {
|
util.ResponseFormat(c, code.RequestParamError, "明细中不能存在重复的产品")
|
return
|
}
|
|
if params.BaseOperationType != constvar.BaseOperationTypeAdjust {
|
if err := slf.FormatLocation(¶ms); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
}
|
if err := models.WithTransaction(func(tx *gorm.DB) error {
|
if err := models.NewOperationDetailsSearch().SetOrm(tx).SetOperationId(params.Id).Delete(); err != nil {
|
return err
|
}
|
operationSearch := models.NewOperationSearch().SetOrm(tx)
|
if err := operationSearch.Orm.Model(¶ms).Association("Details").Replace(params.Details); err != nil {
|
return err
|
}
|
if err := models.NewOperationSearch().SetOrm(tx).SetID(params.Id).Save(¶ms); err != nil {
|
return err
|
}
|
/*od := params.Details
|
for _, v := range od {
|
//material, err := models.NewMaterialSearch().SetID(v.ProductId).First()
|
//if err != nil {return err}
|
material := new(models.Material)
|
material.ID = v.ProductId
|
material.Cost = v.Cost
|
material.SalePrice = v.SalePrice
|
if err := models.NewMaterialSearch().SetOrm(tx).Update(material); err != nil {
|
return err
|
}
|
}*/
|
return nil
|
}); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "修改失败:"+err.Error())
|
return
|
}
|
|
util.ResponseFormat(c, code.Success, "修改成功")
|
}
|
|
// Delete
|
//
|
// @Tags 入库/出库
|
// @Summary 删除入库/出库信息
|
// @Produce application/json
|
// @Param id path int true "id"
|
// @Success 200 {object} util.Response "成功"
|
// @Router /api-wms/v1/operation/operation/{id} [delete]
|
func (slf OperationController) Delete(c *gin.Context) {
|
id, err := strconv.Atoi(c.Param("id"))
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "错误的id值")
|
return
|
}
|
if id == 0 {
|
util.ResponseFormat(c, code.RequestParamError, "id为0")
|
return
|
}
|
operation, err := models.NewOperationSearch().SetID(id).First()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "未找到相关出入库单据:"+err.Error())
|
return
|
}
|
userInfo := middleware.GetUserInfo(c)
|
if operation.CreatedBy != userInfo.Username {
|
util.ResponseFormat(c, code.RequestError, "别人的出入库单据无法进行删除")
|
return
|
}
|
if operation.Status != constvar.OperationStatus_Ready {
|
util.ResponseFormat(c, code.RequestError, "该出入库单据无法进行删除")
|
return
|
}
|
if err := models.WithTransaction(func(tx *gorm.DB) error {
|
if err := models.NewOperationDetailsSearch().SetOrm(tx).SetOperationId(id).Delete(); err != nil {
|
return err
|
}
|
if err := models.NewOperationSearch().SetOrm(tx).SetID(id).Delete(); err != nil {
|
return err
|
}
|
return nil
|
}); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "修改失败:"+err.Error())
|
return
|
}
|
util.ResponseFormat(c, code.Success, "删除成功")
|
}
|
|
// Finish
|
//
|
// @Tags 入库/出库
|
// @Summary 更改记录状态
|
// @Produce application/json
|
// @Param id path int true "id"
|
// @Success 200 {object} util.Response "成功"
|
// @Router /api-wms/v1/operation/finish/{id} [put]
|
func (slf OperationController) Finish(c *gin.Context) {
|
id, err := strconv.Atoi(c.Param("id"))
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "错误的id值")
|
return
|
}
|
if id == 0 {
|
util.ResponseFormat(c, code.RequestParamError, "id为0")
|
return
|
}
|
operation, err := models.NewOperationSearch().SetPreload(true).SetID(id).First()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "未找到相关出入库信息:"+err.Error())
|
return
|
}
|
if operation.Status != constvar.OperationStatus_Ready {
|
util.ResponseFormat(c, code.RequestError, "该出入库信息无法完成")
|
return
|
}
|
|
listDetails, err := models.NewOperationDetailsSearch().SetOperationId(operation.Id).SetPreload(true).FindAll()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestError, err.Error())
|
return
|
}
|
|
var mapLocAmount map[string]*models.LocationProductAmount
|
locAmountList, err := models.NewLocationProductAmountSearch().Find()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestError, err.Error())
|
return
|
}
|
if len(locAmountList) > 0 {
|
mapLocAmount = make(map[string]*models.LocationProductAmount)
|
for _, v := range locAmountList {
|
mapLocAmount[strconv.Itoa(v.LocationId)+v.ProductId] = v
|
}
|
}
|
userInfo := middleware.GetUserInfo(c)
|
err = models.WithTransaction(func(tx *gorm.DB) error {
|
if err := models.NewOperationSearch().SetOrm(tx).SetID(id).Update(&models.Operation{
|
Status: constvar.OperationStatus_Finish,
|
CheckedBy: userInfo.Username,
|
AuditDate: time.Now().Format("2006-01-02 15:04:05")}); err != nil {
|
return err
|
}
|
if err := service.AddMoveHistory([]*models.Operation{operation}, tx); err != nil {
|
return err
|
}
|
|
if operation.BaseOperationType == constvar.BaseOperationTypeIncoming {
|
if err := service.FinishOperationInput(c, tx, operation, listDetails, mapLocAmount); err != nil {
|
return err
|
}
|
}
|
|
if operation.BaseOperationType == constvar.BaseOperationTypeOutgoing || operation.BaseOperationType == constvar.BaseOperationTypeDisuse {
|
if err := service.FinishOperationOutput(tx, listDetails, mapLocAmount, operation); err != nil {
|
return err
|
}
|
}
|
|
if operation.BaseOperationType == constvar.BaseOperationTypeInternal {
|
if err := service.FinishOperationInternal(tx, listDetails, operation); err != nil {
|
return err
|
}
|
}
|
|
if operation.BaseOperationType == constvar.BaseOperationTypeAdjust {
|
if err := service.FinishOperationAdjust(tx, listDetails, mapLocAmount, operation); err != nil {
|
return err
|
}
|
}
|
return nil
|
})
|
if err != nil {
|
util.ResponseFormat(c, code.RequestError, err.Error())
|
return
|
}
|
|
//修改其他系统订单状态
|
if operation.BaseOperationType == constvar.BaseOperationTypeIncoming {
|
if operation.Source != "" {
|
go UpdatePurchaseStatus(operation.Source, operation.SourceNumber)
|
go UpdateOutsourceOrder(operation.Source, operation.SourceNumber, operation.Id, listDetails)
|
}
|
} else if operation.BaseOperationType == constvar.BaseOperationTypeOutgoing {
|
if operation.Source != "" {
|
go UpdateOutStatus(operation.Source, operation.SourceNumber, 4)
|
}
|
}
|
|
util.ResponseFormat(c, code.Success, "操作成功")
|
}
|
|
//var (
|
// ProductInventoryServiceConn *grpc.ClientConn
|
// PurchaseServiceConn *grpc.ClientConn
|
//)
|
//
|
//func InitProductInventoryServiceConn() {
|
// var err error
|
// ProductInventoryServiceConn, err = grpc.Dial(conf.GrpcServerConf.CrmAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
// if err != nil {
|
// logx.Errorf("grpc dial product service error: %v", err.Error())
|
// return
|
// }
|
// PurchaseServiceConn, err = grpc.Dial(conf.GrpcServerConf.SrmAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
// if err != nil {
|
// logx.Errorf("grpc dial product service error: %v", err.Error())
|
// return
|
// }
|
//}
|
//
|
//func CloseProductInventoryServiceConn() {
|
// if ProductInventoryServiceConn != nil {
|
// ProductInventoryServiceConn.Close()
|
// }
|
// if PurchaseServiceConn != nil {
|
// PurchaseServiceConn.Close()
|
// }
|
//}
|
|
func UpdateOutStatus(source, number string, status int64) {
|
if source == "CRM" {
|
cl := product_inventory.NewProductInventoryServiceClient(init_client.CrmConn)
|
_, err := cl.UpdateSalesDetailStatus(context.Background(), &product_inventory.UpdateSalesDetailStatusRequest{
|
Number: number,
|
SalesDetailStatus: "已出库",
|
})
|
if err != nil {
|
logx.Errorf("grpc dial UpdateSalesDetailStatus service error: %v", err)
|
}
|
}
|
if source == "APS_APPLY_MATERIAL" {
|
cl := inventory_order.NewInventoryOrderServiceClient(init_client.ApsConn)
|
_, err := cl.UpdateMaterialApplyStatus(context.Background(), &inventory_order.UpdateMaterialApplyStatusRequest{
|
Number: number,
|
Status: status,
|
})
|
if err != nil {
|
logx.Errorf("grpc dial UpdateSalesDetailStatus service error: %v", err)
|
}
|
}
|
}
|
|
func UpdatePurchaseStatus(source, number string) {
|
if source == "SRM_PURCHASE" {
|
count, err := models.NewOperationSearch().SetSourceNumber(number).SetStatus(constvar.OperationStatus_Ready).Count()
|
if err != nil || count > 0 {
|
return
|
}
|
cl := purchase_wms.NewPurchaseServiceClient(init_client.SrmConn)
|
_, err = cl.UpdatePurchaseStatus(context.Background(), &purchase_wms.UpdatePurchaseStatusRequest{Number: number})
|
if err != nil {
|
logx.Errorf("grpc dial UpdatePurchaseStatus service error: %v", err)
|
}
|
}
|
}
|
|
func UpdateOutsourceOrder(source, number string, operationId int, details []*models.OperationDetails) {
|
if source == "APS_OUTSOURCING_RECEIVE" {
|
products := make([]*inventory_order.OperationProduct, 0)
|
for _, detail := range details {
|
if operationId == detail.OperationID {
|
var op inventory_order.OperationProduct
|
op.ProductNumber = detail.ProductId
|
op.Amount = detail.Amount.IntPart()
|
products = append(products, &op)
|
}
|
}
|
cl := inventory_order.NewInventoryOrderServiceClient(init_client.ApsConn)
|
_, err := cl.UpdateOutsourceOrder(context.Background(), &inventory_order.UpdateOutsourceOrderRequest{
|
OutsourceNumber: number,
|
Products: products,
|
})
|
if err != nil {
|
logx.Errorf("grpc dial UpdateOutsourceOrder service error: %v", err)
|
}
|
}
|
}
|
|
// ListTransfer
|
// @Tags 入库/出库
|
// @Summary 库存调拨列表
|
// @Produce application/json
|
// @Param object body request.OperationAllList true "参数"
|
// @Success 200 {object} util.Response "成功"
|
// @Router /api-wms/v1/operation/listTransfer [post]
|
func (slf OperationController) ListTransfer(c *gin.Context) {
|
var params request.OperationAllList
|
if err := c.BindJSON(¶ms); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误:"+err.Error())
|
return
|
}
|
if !params.PageInfo.Check() {
|
util.ResponseFormat(c, code.RequestParamError, "数据分页信息错误")
|
return
|
}
|
search := models.NewOperationSearch()
|
search.SetPage(params.Page, params.PageSize)
|
search.SetPage(params.Page, params.PageSize)
|
if params.Number != "" {
|
search.SetKeyword(params.Number)
|
}
|
list, total, err := search.SetPreload(true).SetBaseOperationType(constvar.BaseOperationTypeInternal).SetOrder("created_at desc").Find()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestError, "查找失败:"+err.Error())
|
return
|
}
|
util.ResponseFormatListWithPage(c, code.Success, list, int(total), params.Page, params.PageSize)
|
}
|
|
// GetLogisticCompanyList
|
// @Tags 入库/出库
|
// @Summary 获取物流公司列表
|
// @Produce application/json
|
// @Success 200 {object} util.ResponseList{data=[]models.LogisticCompany} "成功"
|
// @Router /api-wms/v1/operation/getLogisticCompanyList [get]
|
func (slf OperationController) GetLogisticCompanyList(c *gin.Context) {
|
companies, err := models.NewLogisticCompanySearch().FindNotTotal()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestError, "查找失败:"+err.Error())
|
return
|
}
|
util.ResponseFormat(c, code.Success, companies)
|
}
|
|
// Cancel
|
//
|
// @Tags 入库/出库
|
// @Summary 取消
|
// @Produce application/json
|
// @Param id path int true "id"
|
// @Success 200 {object} util.Response "成功"
|
// @Router /api-wms/v1/operation/cancel/{id} [put]
|
func (slf OperationController) Cancel(c *gin.Context) {
|
id, err := strconv.Atoi(c.Param("id"))
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "错误的id值")
|
return
|
}
|
if id == 0 {
|
util.ResponseFormat(c, code.RequestParamError, "id为0")
|
return
|
}
|
operation, err := models.NewOperationSearch().SetPreload(true).SetID(id).First()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "未找到相关出入库信息:"+err.Error())
|
return
|
}
|
if operation.Status != constvar.OperationStatus_Ready {
|
util.ResponseFormat(c, code.RequestError, "该出入库信息无法取消")
|
return
|
}
|
operation.Status = constvar.OperationStatus_Cancel
|
operation.AuditDate = time.Now().Format("2006-01-02 15:04:05")
|
if err := models.NewOperationSearch().SetID(operation.Id).Save(operation); err != nil {
|
util.ResponseFormat(c, code.SaveFail, err.Error())
|
return
|
}
|
//更新aps物料申请状态
|
if operation.Source == "APS_APPLY_MATERIAL" {
|
go UpdateOutStatus(operation.Source, operation.SourceNumber, 3)
|
}
|
util.ResponseFormat(c, code.Success, "操作成功")
|
}
|
|
// OutputOperation
|
//
|
// @Tags 入库/出库
|
// @Summary 打印
|
// @Produce application/json
|
// @Param id path int true "id"
|
// @Success 200 {object} util.Response "成功"
|
// @Router /api-wms/v1/operation/outputOperation/{id} [put]
|
func (slf OperationController) OutputOperation(c *gin.Context) {
|
id, err := strconv.Atoi(c.Param("id"))
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "错误的id值")
|
return
|
}
|
if id == 0 {
|
util.ResponseFormat(c, code.RequestParamError, "id为0")
|
return
|
}
|
// 获取操作消息
|
operation, err := models.NewOperationSearch().SetPreload(true).SetID(id).First()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "未找到相关出入库信息:"+err.Error())
|
return
|
}
|
if len(operation.Details) == 0 {
|
util.ResponseFormat(c, code.RequestParamError, "没有相关产品明细的信息")
|
return
|
}
|
|
var fileUrl string
|
// 获取公司名称
|
companyName := conf.WebConf.CompanyName
|
if companyName == "" {
|
util.ResponseFormat(c, code.RequestParamError, "缺少工厂名称配置")
|
return
|
}
|
// BaseOperationTypeIncoming 收货
|
if operation.BaseOperationType == constvar.BaseOperationTypeIncoming {
|
if companyName == "jialian" {
|
// 入库
|
oT, err := models.NewOperationTypeSearch().SetID(uint(operation.OperationTypeId)).First()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
warehouse, err := models.NewWarehouseSearch().SetID(oT.WarehouseId).First()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
|
if warehouse.FileTemplateCategoryIn == constvar.FileWarehouseCategory_JialianInput2 {
|
fileUrl, err = JialianOperation1(warehouse.FileTemplateCategoryIn, operation)
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
} else {
|
fileUrl, err = JialianOperation2(constvar.FileTemplateCategory_JialianInput1, operation)
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
}
|
} else if companyName == "geruimi" {
|
fileUrl, err = ExportInputSelfmade(constvar.FileTemplateCategory_Selfmade, operation)
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
}
|
} else if operation.BaseOperationType == constvar.BaseOperationTypeOutgoing { // 交货
|
if companyName == "jialian" {
|
oT, err := models.NewOperationTypeSearch().SetID(uint(operation.OperationTypeId)).First()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
warehouse, err := models.NewWarehouseSearch().SetID(oT.WarehouseId).First()
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
|
if warehouse.FileTemplateCategoryOut == constvar.FileWarehouseCategory_JialianOutput2 {
|
fileUrl, err = JialianOperation1(warehouse.FileTemplateCategoryOut, operation)
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
|
} else {
|
fileUrl, err = JialianOperation2(constvar.FileTemplateCategory_JialianOutput1, operation)
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
|
}
|
} else if companyName == "geruimi" {
|
fileUrl, err = ExportInputSelfmade(constvar.FileTemplateCategory_Output, operation)
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
}
|
} else {
|
util.ResponseFormat(c, code.RequestParamError, "该记录不支持打印")
|
return
|
}
|
|
m := make(map[string]string)
|
m["url"] = fileUrl
|
m["name"] = companyName
|
util.ResponseFormat(c, code.Success, m)
|
}
|
|
func JialianOperation1(category constvar.FileTemplateCategory, operation *models.Operation) (string, error) {
|
// 获取模板记录
|
template, err := models.NewFileTemplateAttachmentSearch().SetCategory(category).First()
|
if err != nil {
|
return "", errors.New("获取模版记录失败:" + err.Error())
|
}
|
fmt.Println(template)
|
// 根据模板路径获取模板消息
|
readerCloser, err := http.HttpGetWithReadCloser(template.FileUrl)
|
if err != nil {
|
return "", errors.New("获取模版失败:" + err.Error())
|
}
|
|
// 读取模板内容
|
f, err := excelize.OpenReader(readerCloser)
|
if err != nil {
|
return "", errors.New("读取excel模版失败:" + err.Error())
|
}
|
readerCloser.Close()
|
|
defer f.Close()
|
|
sheet := "Sheet1"
|
if category == constvar.FileWarehouseCategory_JialianInput2 {
|
sheet = "入库单"
|
} else if category == constvar.FileWarehouseCategory_JialianOutput2 {
|
sheet = "出库单"
|
}
|
|
// 第二行
|
f.SetCellValue(sheet, "K2", operation.Number) // 单号
|
// 第三行
|
f.SetCellValue(sheet, "D3", operation.CompanyName) // 公司
|
f.SetCellValue(sheet, "G3", "") // 部门
|
|
// 时间
|
date := operation.OperationDate
|
f.SetCellValue(sheet, "I3", date[0:4]) // 年
|
f.SetCellValue(sheet, "L3", date[5:7]) // 月
|
f.SetCellValue(sheet, "N3", date[8:10]) // 日
|
|
var entityIDs []string
|
for _, v := range operation.Details {
|
entityIDs = append(entityIDs, v.ProductId)
|
}
|
attributeMap := make(map[string]uint)
|
attributeValueMap := make(map[string]string)
|
attributes, err := models.NewAttributeSearch().SetEntityType(1).FindNotTotal()
|
if err != nil {
|
return "", errors.New("获取动态属性失败:" + err.Error())
|
}
|
for _, v := range attributes {
|
attributeMap[v.Name] = v.ID
|
}
|
attributeValues, err := models.NewAttributeValueSearch().SetEntityIDs(entityIDs).FindNotTotal()
|
if err != nil {
|
return "", errors.New("获取动态属性值失败:" + err.Error())
|
}
|
for _, v := range attributeValues {
|
attributeValueMap[fmt.Sprintf("%d%s", v.AttributeID, v.EntityID)] = v.Value
|
}
|
|
// 第六行 循环填值
|
totalAmount := decimal.NewFromInt(0) // 总金额
|
totalPrice := decimal.NewFromInt(0) // 总价
|
rowIndex := 6
|
str := ""
|
for i, v := range operation.Details {
|
//设置表单最多6条数据
|
if i > 6 {
|
break
|
}
|
str += v.Remark
|
f.SetCellValue(sheet, "B"+strconv.Itoa(rowIndex), v.Product.Name) // 产品名称
|
f.SetCellValue(sheet, "C"+strconv.Itoa(rowIndex), v.Product.Specs) //规格
|
f.SetCellValue(sheet, "D"+strconv.Itoa(rowIndex), attributeValueMap[fmt.Sprintf("%d%s", attributeMap["颜色"], v.ProductId)]) //颜色
|
f.SetCellValue(sheet, "E"+strconv.Itoa(rowIndex), attributeValueMap[fmt.Sprintf("%d%s", attributeMap["面料"], v.ProductId)]) //面料
|
f.SetCellValue(sheet, "F"+strconv.Itoa(rowIndex), v.TotalGrossWeight.String()) //重量
|
f.SetCellValue(sheet, "G"+strconv.Itoa(rowIndex), v.Amount.String()) //数量
|
f.SetCellValue(sheet, "H"+strconv.Itoa(rowIndex), v.Product.SalePrice.String()) // 单价
|
|
// 金额
|
if !v.Product.SalePrice.IsZero() {
|
ap := v.Amount.Mul(v.Product.SalePrice)
|
totalPrice = totalPrice.Add(ap)
|
price := ap.String()
|
split := strings.Split(price, ".")
|
if len(split) == 2 {
|
for n, a := range split[1] {
|
f.SetCellValue(sheet, string('N'+n)+strconv.Itoa(rowIndex), string(a))
|
}
|
}
|
s := split[0]
|
n := 0
|
for j := len(s) - 1; j >= 0; j-- {
|
if n == 6 {
|
f.SetCellValue(sheet, string('M'-n)+strconv.Itoa(rowIndex), s[:j])
|
break
|
}
|
f.SetCellValue(sheet, string('M'-n)+strconv.Itoa(rowIndex), string(s[j]))
|
n++
|
}
|
}
|
rowIndex++
|
totalAmount = totalAmount.Add(v.Amount)
|
}
|
|
//合计
|
if !totalPrice.IsZero() {
|
price := totalPrice.String()
|
split := strings.Split(price, ".")
|
if len(split) == 2 {
|
for n, a := range split[1] {
|
f.SetCellValue(sheet, string('M'+n)+"12", string(a))
|
}
|
} else {
|
f.SetCellValue(sheet, "N12", "0")
|
f.SetCellValue(sheet, "O12", "0")
|
}
|
s := split[0]
|
n := 0
|
for j := len(s) - 1; j >= 0; j-- {
|
if n == 6 {
|
f.SetCellValue(sheet, string('M'-n)+"12", s[:j])
|
break
|
}
|
f.SetCellValue(sheet, string('M'-n)+"12", string(s[j]))
|
n++
|
}
|
}
|
|
// 备注 第13行
|
//f.SetCellValue(sheet, "B13", "备注:"+operation.Comment)
|
f.SetCellValue(sheet, "B13", "备注:"+str)
|
// 第14行
|
f.SetCellValue(sheet, "C14", operation.Manager) // 审核
|
f.SetCellValue(sheet, "F14", operation.Accountant) // 保管
|
f.SetCellValue(sheet, "I14", operation.Custodian) //经办人
|
buf, err := f.WriteToBuffer()
|
if err != nil {
|
return "", err
|
}
|
|
fileUrl, err := upload.UploadFileToSeaWeed(string(constvar.FileType_File), uuid.NewV4().String()+".xlsx", buf.Bytes())
|
if err != nil {
|
logx.Errorf("file upload err: %v", err)
|
return "", err
|
}
|
return fileUrl, nil
|
}
|
|
func JialianOperation2(category constvar.FileTemplateCategory, operation *models.Operation) (string, error) {
|
// 获取模板记录
|
template, err := models.NewFileTemplateAttachmentSearch().SetCategory(category).First()
|
if err != nil {
|
return "", errors.New("获取模版记录失败:" + err.Error())
|
}
|
fmt.Println(template)
|
// 根据模板路径获取模板消息
|
readerCloser, err := http.HttpGetWithReadCloser(template.FileUrl)
|
if err != nil {
|
return "", errors.New("获取模版失败:" + err.Error())
|
}
|
|
// 读取模板内容
|
f, err := excelize.OpenReader(readerCloser)
|
if err != nil {
|
return "", errors.New("读取excel模版失败:" + err.Error())
|
}
|
readerCloser.Close()
|
|
defer f.Close()
|
|
sheet := "Sheet1"
|
f.SetCellValue(sheet, "A2", "单位(部门):"+operation.CompanyName) // 单位部门
|
f.SetCellValue(sheet, "J2", operation.OperationDate) // 时间
|
f.SetCellValue(sheet, "Q2", operation.Number) // 编号
|
|
totalAmount := decimal.NewFromInt(0) // 总金额
|
totalPrice := decimal.NewFromInt(0) // 总价
|
rowIndex := 5
|
str := ""
|
for i, v := range operation.Details {
|
//设置表单最多9条数据
|
if i > 9 {
|
break
|
}
|
str += v.Remark
|
f.SetCellValue(sheet, "A"+strconv.Itoa(rowIndex), v.Product.Name) // 品名
|
f.SetCellValue(sheet, "B"+strconv.Itoa(rowIndex), v.Product.Type) // 型号
|
f.SetCellValue(sheet, "C"+strconv.Itoa(rowIndex), v.Product.Unit) // 单位
|
f.SetCellValue(sheet, "D"+strconv.Itoa(rowIndex), v.Amount.String()) // 数量
|
unit := service.CreateMoreUnit(v.Amount, v.Product.MoreUnitList)
|
for _, v1 := range unit {
|
if !v1.Amount.IsZero() {
|
f.SetCellValue(sheet, "E"+strconv.Itoa(rowIndex), v1.Amount) // 辅数量
|
f.SetCellValue(sheet, "F"+strconv.Itoa(rowIndex), v1.Unit) // 辅单位
|
break
|
}
|
}
|
f.SetCellValue(sheet, "G"+strconv.Itoa(rowIndex), v.Product.SalePrice.String()) // 单价
|
// 金额
|
if !v.Product.SalePrice.IsZero() {
|
ap := v.Amount.Mul(v.Product.SalePrice)
|
totalPrice = totalPrice.Add(ap)
|
price := ap.String()
|
split := strings.Split(price, ".")
|
if len(split) == 2 {
|
for n, a := range split[1] {
|
f.SetCellValue(sheet, string('O'+n)+strconv.Itoa(rowIndex), string(a))
|
}
|
}
|
s := split[0]
|
n := 0
|
for j := len(s) - 1; j >= 0; j-- {
|
if n == 6 {
|
f.SetCellValue(sheet, string('N'-n)+strconv.Itoa(rowIndex), s[:j])
|
break
|
}
|
f.SetCellValue(sheet, string('N'-n)+strconv.Itoa(rowIndex), string(s[j]))
|
n++
|
}
|
}
|
rowIndex++
|
totalAmount = totalAmount.Add(v.Amount)
|
}
|
|
//合计
|
if !totalPrice.IsZero() {
|
price := totalPrice.String()
|
split := strings.Split(price, ".")
|
if len(split) == 2 {
|
for n, a := range split[1] {
|
f.SetCellValue(sheet, string('N'+n)+"14", string(a))
|
}
|
} else {
|
f.SetCellValue(sheet, "O14", "0")
|
f.SetCellValue(sheet, "P14", "0")
|
}
|
s := split[0]
|
n := 0
|
for j := len(s) - 1; j >= 0; j-- {
|
if n == 6 {
|
f.SetCellValue(sheet, string('N'-n)+"14", s[:j])
|
break
|
}
|
f.SetCellValue(sheet, string('N'-n)+"14", string(s[j]))
|
n++
|
}
|
}
|
|
//f.SetCellValue(sheet, "Q5", operation.Comment) // 备注
|
f.SetCellValue(sheet, "Q5", str) // 备注
|
|
// 第14行
|
f.SetCellValue(sheet, "B15", operation.Manager) // 主管
|
f.SetCellValue(sheet, "D15", operation.Accountant) // 会计
|
f.SetCellValue(sheet, "H15", operation.Custodian) //保管员
|
f.SetCellValue(sheet, "Q15", operation.Custodian) //经手
|
buf, err := f.WriteToBuffer()
|
if err != nil {
|
return "", err
|
}
|
|
fileUrl, err := upload.UploadFileToSeaWeed(string(constvar.FileType_File), uuid.NewV4().String()+".xlsx", buf.Bytes())
|
if err != nil {
|
logx.Errorf("file upload err: %v", err)
|
return "", err
|
}
|
return fileUrl, nil
|
}
|
|
func ExportInputSelfmade(category constvar.FileTemplateCategory, operation *models.Operation) (string, error) {
|
template, err := models.NewFileTemplateAttachmentSearch().SetCategory(category).First()
|
if err != nil {
|
return "", errors.New("获取模版记录失败:" + err.Error())
|
}
|
readerCloser, err := http.HttpGetWithReadCloser(template.FileUrl)
|
if err != nil {
|
return "", errors.New("获取模版失败:" + err.Error())
|
}
|
|
f, err := excelize.OpenReader(readerCloser)
|
if err != nil {
|
return "", errors.New("读取excel模版失败:" + err.Error())
|
}
|
readerCloser.Close()
|
defer f.Close()
|
|
style, _ := f.NewStyle(&excelize.Style{
|
Border: []excelize.Border{
|
{Type: "left", Color: "#000000", Style: 2},
|
{Type: "top", Color: "#000000", Style: 2},
|
{Type: "bottom", Color: "#000000", Style: 2},
|
{Type: "right", Color: "#000000", Style: 2},
|
},
|
Alignment: &excelize.Alignment{
|
Horizontal: "center",
|
Vertical: "center",
|
},
|
})
|
styleLeft, _ := f.NewStyle(&excelize.Style{
|
Alignment: &excelize.Alignment{
|
Horizontal: "left",
|
Vertical: "center",
|
},
|
})
|
|
f.SetCellValue("Sheet1", "B3", operation.CompanyName)
|
f.SetCellValue("Sheet1", "E3", operation.OperationDate)
|
f.SetCellValue("Sheet1", "H3", operation.Number)
|
|
rowIndex := 5
|
totalAmount := decimal.NewFromInt(0)
|
for _, v := range operation.Details {
|
f.SetCellValue("Sheet1", "A"+strconv.Itoa(rowIndex), v.ProductId)
|
f.SetCellValue("Sheet1", "B"+strconv.Itoa(rowIndex), v.Product.Name)
|
f.SetCellValue("Sheet1", "C"+strconv.Itoa(rowIndex), v.Product.Specs)
|
f.SetCellValue("Sheet1", "D"+strconv.Itoa(rowIndex), v.Product.Unit)
|
f.SetCellValue("Sheet1", "E"+strconv.Itoa(rowIndex), v.Amount.String())
|
f.SetCellValue("Sheet1", "H"+strconv.Itoa(rowIndex), v.ToLocation.Name)
|
f.SetCellValue("Sheet1", "I"+strconv.Itoa(rowIndex), operation.Comment)
|
rowIndex++
|
totalAmount = totalAmount.Add(v.Amount)
|
}
|
if err := f.MergeCell("Sheet1", "A"+strconv.Itoa(rowIndex), "C"+strconv.Itoa(rowIndex)); err != nil {
|
return "", err
|
}
|
f.SetCellValue("Sheet1", "A"+strconv.Itoa(rowIndex), "合计")
|
f.SetCellValue("Sheet1", "E"+strconv.Itoa(rowIndex), totalAmount.String())
|
f.SetCellStyle("Sheet1", "A4", "I"+strconv.Itoa(rowIndex), style)
|
rowIndex++
|
|
f.SetCellValue("Sheet1", "A"+strconv.Itoa(rowIndex), "审核:")
|
f.SetCellValue("Sheet1", "D"+strconv.Itoa(rowIndex), "检验:")
|
f.SetCellValue("Sheet1", "G"+strconv.Itoa(rowIndex), "保管:")
|
f.SetCellStyle("Sheet1", "A"+strconv.Itoa(rowIndex), "G"+strconv.Itoa(rowIndex), styleLeft)
|
|
buf, err := f.WriteToBuffer()
|
if err != nil {
|
return "", err
|
}
|
|
fileUrl, err := upload.UploadFileToSeaWeed(string(constvar.FileType_File), uuid.NewV4().String()+".xlsx", buf.Bytes())
|
if err != nil {
|
logx.Errorf("file upload err: %v", err)
|
return "", err
|
}
|
return fileUrl, nil
|
}
|
|
func ExportOutputOperation(category constvar.FileTemplateCategory, operation *models.Operation) (string, error) {
|
repositoryLevels := strings.Split(operation.Location.JointName, "/")
|
template, err := models.NewFileTemplateAttachmentSearch().SetCategory(category).First()
|
if err != nil {
|
return "", errors.New("获取模版记录失败:" + err.Error())
|
}
|
readerCloser, err := http.HttpGetWithReadCloser(template.FileUrl)
|
if err != nil {
|
return "", errors.New("获取模版失败:" + err.Error())
|
}
|
|
f, err := excelize.OpenReader(readerCloser)
|
if err != nil {
|
return "", errors.New("读取excel模版失败:" + err.Error())
|
}
|
readerCloser.Close()
|
defer f.Close()
|
|
style, _ := f.NewStyle(&excelize.Style{
|
Border: []excelize.Border{
|
{Type: "left", Color: "#000000", Style: 1},
|
{Type: "top", Color: "#000000", Style: 1},
|
{Type: "bottom", Color: "#000000", Style: 1},
|
{Type: "right", Color: "#000000", Style: 1},
|
},
|
Alignment: &excelize.Alignment{
|
Horizontal: "center",
|
Vertical: "center",
|
},
|
})
|
|
f.SetCellValue("Sheet1", "C2", repositoryLevels[0])
|
f.SetCellValue("Sheet1", "H2", operation.WaybillNumber)
|
f.SetCellValue("Sheet1", "K2", operation.AuditDate)
|
f.SetCellValue("Sheet1", "H3", operation.SourceNumber)
|
f.SetCellValue("Sheet1", "K3", operation.Number)
|
f.SetCellValue("Sheet1", "C4", operation.CompanyName)
|
f.SetCellValue("Sheet1", "I4", operation.ReceiverAddr)
|
f.SetCellValue("Sheet1", "C5", operation.ReceiverName)
|
f.SetCellValue("Sheet1", "H5", operation.ReceiverPhone)
|
|
rowIndex := 8
|
totalAmount := decimal.NewFromInt(0)
|
totalWeight := decimal.NewFromInt(0)
|
|
addRows := len(operation.Details) - 1
|
if addRows > 0 {
|
f.InsertRows("Sheet1", 9, addRows)
|
f.SetCellStyle("Sheet1", "A9", "K"+strconv.Itoa(rowIndex+addRows), style)
|
}
|
|
for k, v := range operation.Details {
|
productTotalWeight := v.Amount.Mul(v.Product.Weight).Div(decimal.NewFromInt(1000))
|
f.SetCellValue("Sheet1", "A"+strconv.Itoa(rowIndex), k+1)
|
f.SetCellValue("Sheet1", "B"+strconv.Itoa(rowIndex), v.Product.Name)
|
f.SetCellValue("Sheet1", "H"+strconv.Itoa(rowIndex), v.Amount)
|
f.SetCellValue("Sheet1", "I"+strconv.Itoa(rowIndex), v.Product.Weight)
|
f.SetCellValue("Sheet1", "J"+strconv.Itoa(rowIndex), productTotalWeight)
|
rowIndex++
|
totalAmount = totalAmount.Add(v.Amount)
|
totalWeight = totalWeight.Add(productTotalWeight)
|
}
|
|
buf, err := f.WriteToBuffer()
|
if err != nil {
|
return "", err
|
}
|
|
fileUrl, err := upload.UploadFileToSeaWeed(string(constvar.FileType_File), uuid.NewV4().String()+".xlsx", buf.Bytes())
|
if err != nil {
|
logx.Errorf("file upload err: %v", err)
|
return "", err
|
}
|
|
return fileUrl, nil
|
|
}
|
|
// GetSupplierList
|
// @Tags 入库/出库
|
// @Summary 获取物流公司列表
|
// @Produce application/json
|
//
|
// @Success 200 {object} util.Response "成功"
|
//
|
// @Router /api-wms/v1/operation/getSupplierList [get]
|
func (slf OperationController) GetSupplierList(c *gin.Context) {
|
cli := supplier.NewSupplierServiceClient(init_client.SrmConn)
|
resp, err := cli.GetSupplierList(c, &supplier.SupplierListRequest{Status: 1})
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "grpc调用失败:"+err.Error())
|
return
|
}
|
util.ResponseFormat(c, code.Success, resp.List)
|
}
|
|
// GetClientList
|
// @Tags 入库/出库
|
// @Summary 获取物流公司列表
|
// @Produce application/json
|
//
|
// @Success 200 {object} util.Response "成功"
|
//
|
// @Router /api-wms/v1/operation/getClientList [get]
|
func (slf OperationController) GetClientList(c *gin.Context) {
|
cli := client.NewClientServiceClient(init_client.CrmConn)
|
resp, err := cli.GetClientList(c, &client.ClientListRequest{})
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "grpc调用失败:"+err.Error())
|
return
|
}
|
util.ResponseFormat(c, code.Success, resp.List)
|
}
|
|
// ListByCondition
|
// @Tags 入库/出库
|
// @Summary 出入库明细
|
// @Produce application/json
|
// @Param object body request.OperationCondition true "参数"
|
// @Success 200 {object} util.Response "成功"
|
// @Router /api-wms/v1/operation/listByCondition [post]
|
func (slf OperationController) ListByCondition(c *gin.Context) {
|
var params request.OperationCondition
|
if err := c.BindJSON(¶ms); err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "参数解析失败,数据类型错误:"+err.Error())
|
return
|
}
|
if !params.PageInfo.Check() {
|
util.ResponseFormat(c, code.RequestParamError, "数据分页信息错误")
|
return
|
}
|
|
db := mysqlx.GetDB().Table("wms_operation").
|
Select("wms_operation.id as operation_id,wms_operation.number,wms_operation.base_operation_type,material.id AS product_id," +
|
"material.`name` AS product_name,wms_operation_details.amount,material.unit,wms_operation_details.from_location_id," +
|
"from_location.`name` AS from_location,wms_operation_details.to_location_id,to_location.`name` AS to_location," +
|
"wms_operation.operation_date as date,wms_operation.`status`,material.weight,wms_operation.operation_type_name").
|
InnerJoins("inner join wms_operation_details ON wms_operation_details.operation_id = wms_operation.id").
|
InnerJoins("INNER JOIN material ON material.id = wms_operation_details.product_id").
|
InnerJoins("INNER JOIN wms_location AS from_location ON from_location.id = wms_operation_details.from_location_id").
|
InnerJoins("INNER JOIN wms_location AS to_location ON to_location.id = wms_operation_details.to_location_id")
|
if params.Condition != "" {
|
db = db.Where("wms_operation.number like ? or wms_operation.source_number like ? or from_location.`name` like ? or to_location.`name` like ? or material.`name` like ? ", "%"+params.Condition+"%", "%"+params.Condition+"%", "%"+params.Condition+"%", "%"+params.Condition+"%", "%"+params.Condition+"%")
|
}
|
if params.WarehouseId != 0 {
|
db = db.Where("warehouse_id = ?", params.WarehouseId)
|
}
|
if params.LocationId != 0 {
|
db = db.Where("location_id = ?", params.LocationId)
|
}
|
var (
|
records = make([]*response.InventoryHistory, 0)
|
total int64
|
)
|
|
if err := db.Count(&total).Error; err != nil {
|
util.ResponseFormat(c, code.RequestError, "查找失败:"+err.Error())
|
return
|
}
|
|
if err := db.Offset((params.Page - 1) * params.PageSize).Limit(params.PageSize).Order("wms_operation.created_at desc").Find(&records).Error; err != nil {
|
util.ResponseFormat(c, code.RequestError, "查找失败:"+err.Error())
|
return
|
}
|
util.ResponseFormatListWithPage(c, code.Success, records, int(total), params.Page, params.PageSize)
|
}
|
|
// GetPersonnelList
|
// @Tags 入库/出库
|
// @Summary 获取人员列表
|
// @Produce application/json
|
// @Success 200 {object} util.Response "成功"
|
// @Router /api-wms/v1/operation/getPersonnelList [get]
|
func (slf OperationController) GetPersonnelList(c *gin.Context) {
|
cli := inventory_order.NewInventoryOrderServiceClient(init_client.ApsConn)
|
list, err := cli.GetWorkerList(context.Background(), &inventory_order.GetWorkerListRequest{})
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "内部错误")
|
logx.Error("grpc调用失败, GetPersonnelList err : " + err.Error())
|
return
|
}
|
util.ResponseFormat(c, code.Success, list.List)
|
}
|