1.新增产品入库相关接口(新增、编辑、审核、删除、列表、详情);

This commit is contained in:
chenlin 2024-04-10 14:17:19 +08:00
parent ffcff20590
commit e5367b8c4e
18 changed files with 8644 additions and 170 deletions

View File

@ -0,0 +1,27 @@
package decision
import (
"errors"
"github.com/gin-gonic/gin"
model "go-admin/app/admin/models"
"go-admin/logger"
"go-admin/tools/app"
"net/http"
)
// ErpDecisionReport 进销存报表
// @Summary 进销存报表
// @Tags 决策中心, V1.4.0
// @Produce json
// @Accept json
// @Param request body models.ErpDecisionReportReq true "进销存报表模型"
// @Success 200 {object} models.ErpDecisionReportResp
// @Router /api/v1/decision/report [post]
func ErpDecisionReport(c *gin.Context) {
req := new(model.ErpDecisionReportReq)
if err := c.ShouldBindJSON(&req); err != nil {
logger.Error("ShouldBindJSON err:", logger.Field("err", err))
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误"+err.Error())
return
}
}

View File

@ -16,7 +16,7 @@ import (
// @Produce json
// @Accept json
// @Param request body models.InventoryAllotAddReq true "新增模型"
// @Success 200 {object} models.InventoryAllotOrder
// @Success 200 {object} models.ErpInventoryAllotOrder
// @Router /api/v1/inventory/allot/add [post]
func InventoryAllotAdd(c *gin.Context) {
req := &models.ErpStockListReq{}
@ -36,7 +36,7 @@ func InventoryAllotAdd(c *gin.Context) {
// @Produce json
// @Accept json
// @Param request body models.InventoryAllotEditReq true "编辑模型"
// @Success 200 {object} models.InventoryAllotOrder
// @Success 200 {object} models.ErpInventoryAllotOrder
// @Router /api/v1/inventory/allot/edit [post]
func InventoryAllotEdit(c *gin.Context) {
req := &models.ErpStockListReq{}
@ -79,7 +79,7 @@ func InventoryAllotAudit(c *gin.Context) {
// @Success 200 {object} app.Response
// @Router /api/v1/inventory/allot/delete [post]
func InventoryAllotDelete(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryAllotDeleteReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -99,7 +99,7 @@ func InventoryAllotDelete(c *gin.Context) {
// @Success 200 {object} models.InventoryAllotListResp
// @Router /api/v1/inventory/allot/list [post]
func InventoryAllotList(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryAllotListReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -116,10 +116,10 @@ func InventoryAllotList(c *gin.Context) {
// @Produce json
// @Accept json
// @Param request body models.InventoryAllotDetailReq true "库存调拨详情模型"
// @Success 200 {object} models.InventoryAllotOrder
// @Success 200 {object} models.ErpInventoryAllotOrder
// @Router /api/v1/inventory/allot/detail [post]
func InventoryAllotDetail(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryAllotDetailReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -139,7 +139,7 @@ func InventoryAllotDetail(c *gin.Context) {
// @Success 200 {object} app.Response
// @Router /api/v1/inventory/allot/deliver [post]
func InventoryAllotDeliver(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryAllotDeliverReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -159,7 +159,7 @@ func InventoryAllotDeliver(c *gin.Context) {
// @Success 200 {object} app.Response
// @Router /api/v1/inventory/allot/receive [post]
func InventoryAllotReceive(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryAllotReceiveReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")

View File

@ -16,10 +16,10 @@ import (
// @Produce json
// @Accept json
// @Param request body models.InventoryChangeAddReq true "新增模型"
// @Success 200 {object} models.InventoryChangeOrder
// @Success 200 {object} models.ErpInventoryChangeOrder
// @Router /api/v1/inventory/change/add [post]
func InventoryChangeAdd(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryChangeAddReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -36,10 +36,10 @@ func InventoryChangeAdd(c *gin.Context) {
// @Produce json
// @Accept json
// @Param request body models.InventoryChangeEditReq true "编辑模型"
// @Success 200 {object} models.InventoryChangeOrder
// @Success 200 {object} models.ErpInventoryChangeOrder
// @Router /api/v1/inventory/change/edit [post]
func InventoryChangeEdit(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryChangeEditReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -59,7 +59,7 @@ func InventoryChangeEdit(c *gin.Context) {
// @Success 200 {object} app.Response
// @Router /api/v1/inventory/change/audit [post]
func InventoryChangeAudit(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryChangeAuditReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -79,7 +79,7 @@ func InventoryChangeAudit(c *gin.Context) {
// @Success 200 {object} app.Response
// @Router /api/v1/inventory/change/delete [post]
func InventoryChangeDelete(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryChangeDeleteReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -99,7 +99,7 @@ func InventoryChangeDelete(c *gin.Context) {
// @Success 200 {object} models.InventoryChangeListResp
// @Router /api/v1/inventory/change/list [post]
func InventoryChangeList(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryChangeListReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -116,10 +116,10 @@ func InventoryChangeList(c *gin.Context) {
// @Produce json
// @Accept json
// @Param request body models.InventoryChangeDetailReq true "库存变动详情模型"
// @Success 200 {object} models.InventoryChangeOrder
// @Success 200 {object} models.ErpInventoryChangeOrder
// @Router /api/v1/inventory/change/detail [post]
func InventoryChangeDetail(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryChangeDetailReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")

View File

@ -2,8 +2,12 @@ package inventorymanage
import (
"errors"
"fmt"
"github.com/gin-gonic/gin"
"go-admin/app/admin/models"
orm "go-admin/common/global"
"go-admin/logger"
"go-admin/tools"
"go-admin/tools/app"
"net/http"
)
@ -16,17 +20,36 @@ import (
// @Produce json
// @Accept json
// @Param request body models.ProductInventoryAddReq true "新增模型"
// @Success 200 {object} models.ProductInventoryOrder
// @Success 200 {object} models.ErpInventoryProductOrder
// @Router /api/v1/inventory/product/add [post]
func ProductInventoryAdd(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.ProductInventoryAddReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误:"+err.Error())
return
}
app.OK(c, "", "OK")
err := tools.Validate(req) //必填参数校验
if err != nil {
app.Error(c, http.StatusBadRequest, err, err.Error())
return
}
sysUser, err := models.GetSysUserByCtx(c)
if err != nil {
logger.Error("sys user err:", logger.Field("err", err))
app.Error(c, http.StatusInternalServerError, err, "操作失败")
return
}
inventoryProductOrder, err := models.AddProductInventory(req, sysUser)
if err != nil {
logger.Error("ProductInventoryAdd err:", logger.Field("err", err))
app.Error(c, http.StatusInternalServerError, err, "新增失败:"+err.Error())
return
}
app.OK(c, inventoryProductOrder, "新增成功")
return
}
@ -36,17 +59,30 @@ func ProductInventoryAdd(c *gin.Context) {
// @Produce json
// @Accept json
// @Param request body models.ProductInventoryEditReq true "编辑模型"
// @Success 200 {object} models.ProductInventoryOrder
// @Success 200 {object} models.ErpInventoryProductOrder
// @Router /api/v1/inventory/product/edit [post]
func ProductInventoryEdit(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.ProductInventoryEditReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误:"+err.Error())
return
}
app.OK(c, "", "OK")
err := tools.Validate(req) //必填参数校验
if err != nil {
app.Error(c, http.StatusBadRequest, err, err.Error())
return
}
inventoryProductOrder, err := models.EditProductInventory(req)
if err != nil {
logger.Error("ProductInventoryAdd err:", logger.Field("err", err))
app.Error(c, http.StatusInternalServerError, err, "编辑失败:"+err.Error())
return
}
app.OK(c, inventoryProductOrder, "编辑成功")
return
}
@ -59,14 +95,27 @@ func ProductInventoryEdit(c *gin.Context) {
// @Success 200 {object} app.Response
// @Router /api/v1/inventory/product/audit [post]
func ProductInventoryAudit(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.ProductInventoryAuditReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
return
}
app.OK(c, "", "OK")
sysUser, err := models.GetSysUserByCtx(c)
if err != nil {
logger.Error("sys user err:", logger.Field("err", err))
app.Error(c, http.StatusInternalServerError, err, "操作失败")
return
}
err = models.AuditProductInventory(req, sysUser)
if err != nil {
app.Error(c, http.StatusInternalServerError, err, "审核失败:"+err.Error())
return
}
app.OK(c, nil, "操作成功")
return
}
@ -79,14 +128,80 @@ func ProductInventoryAudit(c *gin.Context) {
// @Success 200 {object} app.Response
// @Router /api/v1/inventory/product/delete [post]
func ProductInventoryDelete(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.ProductInventoryDeleteReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
return
}
app.OK(c, "", "OK")
err := tools.Validate(req) //必填参数校验
if err != nil {
app.Error(c, http.StatusBadRequest, err, err.Error())
return
}
// todo 需要校验当前用户是否有权限
var inventoryProductOrder models.ErpInventoryProductOrder
err = orm.Eloquent.Table("erp_inventory_product_order").Where("serial_number = ?", req.SerialNumber).
Find(&inventoryProductOrder).Error
if err != nil {
logger.Error("order err:", logger.Field("err", err))
app.Error(c, http.StatusInternalServerError, err, "删除失败:"+err.Error())
return
}
if inventoryProductOrder.SerialNumber == "" {
logger.Error("order is null")
app.Error(c, http.StatusInternalServerError, err, "删除失败:订单不存在")
return
}
// 仅待审核订单可删除
if inventoryProductOrder.State != models.ErpInventoryProductOrderUnAudit {
logger.Error("order err, erpPurchaseOrder.State is:", logger.Field("inventoryProductOrder.State",
inventoryProductOrder.State))
app.Error(c, http.StatusInternalServerError, err, "删除失败:仅待审核订单可删除")
return
}
begin := orm.Eloquent.Begin()
// 1-删除采购订单表
err = begin.Delete(inventoryProductOrder).Error
if err != nil {
logger.Error("order delete1 err:", logger.Field("err", err))
app.Error(c, http.StatusInternalServerError, err, "删除失败:"+err.Error())
return
}
// 2-删除采购订单商品表
var commodities []models.ErpInventoryProductCommodity
err = orm.Eloquent.Table("erp_inventory_product_commodity").Where("product_order_id = ?",
inventoryProductOrder.ID).Find(&commodities).Error
if err != nil {
logger.Error("query erp_inventory_product_commodity err:", logger.Field("err", err))
app.Error(c, http.StatusInternalServerError, err, "删除失败:"+err.Error())
return
}
if len(commodities) != 0 {
err = begin.Delete(&commodities).Error
if err != nil {
logger.Error("更新商品订单信息-删除 error")
app.Error(c, http.StatusInternalServerError, err, "删除失败:"+err.Error())
return
}
}
err = begin.Commit().Error
if err != nil {
begin.Rollback()
logger.Error("commit err:", logger.Field("err", err))
return
}
app.OK(c, nil, "删除成功")
return
}
@ -99,14 +214,20 @@ func ProductInventoryDelete(c *gin.Context) {
// @Success 200 {object} models.ProductInventoryListResp
// @Router /api/v1/inventory/product/list [post]
func ProductInventoryList(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.ProductInventoryListReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
return
}
app.OK(c, "", "OK")
resp, err := req.List()
if err != nil {
app.Error(c, http.StatusInternalServerError, err, "获取失败:"+err.Error())
return
}
app.OK(c, resp, "查询成功")
return
}
@ -116,16 +237,47 @@ func ProductInventoryList(c *gin.Context) {
// @Produce json
// @Accept json
// @Param request body models.ProductInventoryDetailReq true "产品入库详情模型"
// @Success 200 {object} models.ProductInventoryOrder
// @Success 200 {object} models.ErpInventoryProductOrder
// @Router /api/v1/inventory/product/detail [post]
func ProductInventoryDetail(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.ProductInventoryDetailReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
return
}
app.OK(c, "", "OK")
var productOrder models.ErpInventoryProductOrder
err := orm.Eloquent.Table("erp_inventory_product_order").Where("serial_number=?", req.SerialNumber).Find(&productOrder).Error
if err != nil {
logger.Error("product order err:", logger.Field("err", err))
app.Error(c, http.StatusBadRequest, err, "获取失败")
return
}
if productOrder.ID == 0 {
logger.Error("product commodities err:", logger.Field("err", err))
app.Error(c, http.StatusBadRequest, err, fmt.Sprintf("未查询到订单[%s]", req.SerialNumber))
return
}
// 校验时间如果为01-01-01 08:05则赋值为空
if productOrder.MakerTime != nil && productOrder.MakerTime.IsZero() {
productOrder.MakerTime = nil
}
if productOrder.AuditTime != nil && productOrder.AuditTime.IsZero() {
productOrder.AuditTime = nil
}
var productCommodities []models.ErpInventoryProductCommodity
err = orm.Eloquent.Table("erp_inventory_product_commodity").Where("product_order_id=?", productOrder.ID).
Find(&productCommodities).Error
if err != nil {
logger.Error("product commodities err:", logger.Field("err", err))
app.Error(c, http.StatusBadRequest, err, "获取失败")
return
}
productOrder.Commodities = productCommodities
app.OK(c, productOrder, "查询成功")
return
}

View File

@ -19,7 +19,7 @@ import (
// @Success 200 {object} models.InventoryReportByProductResp
// @Router /api/v1/inventory/report/product [post]
func InventoryReportByProduct(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryReportByProductReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -39,7 +39,7 @@ func InventoryReportByProduct(c *gin.Context) {
// @Success 200 {object} models.InventoryReportByAllotResp
// @Router /api/v1/inventory/report/allot [post]
func InventoryReportByAllot(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryReportByAllotReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -59,7 +59,7 @@ func InventoryReportByAllot(c *gin.Context) {
// @Success 200 {object} models.InventoryReportAllotDetailResp
// @Router /api/v1/inventory/report/allot_detail [post]
func InventoryReportAllotDetail(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryReportAllotDetailReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -79,7 +79,7 @@ func InventoryReportAllotDetail(c *gin.Context) {
// @Success 200 {object} models.InventoryReportByOtherResp
// @Router /api/v1/inventory/report/other [post]
func InventoryReportByOther(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryReportByOtherReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
@ -99,7 +99,7 @@ func InventoryReportByOther(c *gin.Context) {
// @Success 200 {object} models.InventoryReportOtherDetailResp
// @Router /api/v1/inventory/report/other_detail [post]
func InventoryReportOtherDetail(c *gin.Context) {
req := &models.ErpStockListReq{}
req := &models.InventoryReportOtherDetailReq{}
if err := c.ShouldBindJSON(&req); err != nil {
//logger.Error(err)
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")

View File

@ -20,12 +20,14 @@ import (
const (
NoIMEICommodity = 1 // 非串码商品类型
PurchaseInventory = 2 // 采购入库
ProductInventory = 3 // 产品入库
InStock = 1 // 在库
SoldOut = 2 // 已售
PurchaseReturn = 3 // 采购退货
InAllot = 4 // 调拨中
OnSale = 5 // 销售锁定中
ProductReturn = 6 // 产品出库
)
// ErpStock 库存列表
@ -72,7 +74,7 @@ type ErpStockCommodity struct {
MemberDiscount float64 `json:"member_discount"` // 会员优惠
State uint32 `json:"state"` // 状态:1-在库 2-已售 3-采购退货 4-调拨中 5-销售锁定中
Count uint32 `json:"count"` // 数量
StorageType uint32 `json:"storage_type"` // 入库方式1-系统入库 2-采购入库
StorageType uint32 `json:"storage_type"` // 入库方式1-系统入库 2-采购入库 3-产品入库
FirstStockTime time.Time `json:"first_stock_time"` // 首次入库时间
StockSn string `json:"stock_sn"` // 库存订单编号(跟采购入库的入库编号关联)
OriginalSn string `json:"original_sn" gorm:"index"` // 首次入库订单编号(单据编号)
@ -1764,7 +1766,7 @@ type ErpStockCommodityListReq struct {
SerialNumber string `json:"serial_number"` // 商品编号
CommodityName string `json:"commodity_name"` // 商品名称
ErpCategoryId uint32 `json:"erp_category_id"` // 商品分类Id
IsIMEI uint32 `json:"is_imei""` // 是否串码0-查全部 1-查串码类 2-查非串码
IsIMEI uint32 `json:"is_imei"` // 是否串码0-查全部 1-查串码类 2-查非串码
IMEI string `json:"imei"` // 串码
StoreId uint32 `json:"store_id"` // 门店编号
SupplierId uint32 `json:"supplier_id"` // 供应商id

View File

@ -0,0 +1,67 @@
package models
// ErpDecisionReportReq 进销存报表入参
type ErpDecisionReportReq struct {
StoreId []uint32 `json:"store_id"` // 门店id
CommodityName []string `json:"commodity_name"` // 商品名称
CategoryID []uint32 `json:"category_id"` // 商品分类id
StartTime string `json:"start_time"` // 开始时间
EndTime string `json:"end_time"` // 结束时间
IsExport uint32 `json:"is_export"` // 1-导出
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
}
// ErpDecisionReportResp 进销存报表出参
type ErpDecisionReportResp struct {
Total int `json:"total"` // 总条数/记录数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
DecisionSumData
ExportUrl string `json:"export_url"` // 导出excel路径
List []DecisionReportData `json:"list"` //
}
// DecisionSumData 进销存汇总数据
type DecisionSumData struct {
TotalBeginStock uint32 `json:"total_begin_stock"` // 期初库存
TotalBeginAmount float64 `json:"total_begin_amount"` // 期初金额
TotalPurchaseStock uint32 `json:"total_purchase_stock"` // 采购进货
TotalPurchaseReturn uint32 `json:"total_purchase_return"` // 采购退货
TotalOrderSale uint32 `json:"total_order_sale"` // 零售销售
TotalOrderReject uint32 `json:"total_order_reject"` // 零售退货
TotalAllotIn uint32 `json:"total_allot_in"` // 调拨入库
TotalAllotWaitIn uint32 `json:"total_allot_wait_in"` // 在途库存(入库)
TotalAllotOut uint32 `json:"total_allot_out"` // 调拨出库
TotalAllotWaitOut uint32 `json:"total_allot_wait_out"` // 在途库存(出库)
TotalProductIn uint32 `json:"total_product_in"` // 产品入库
TotalSystemOut uint32 `json:"total_system_out"` // 系统出库
TotalCheckIn uint32 `json:"total_check_in"` // 盘点入库
TotalCheckOut uint32 `json:"total_check_out"` // 盘点出库
TotalEndStock uint32 `json:"total_end_stock"` // 期末数量
TotalEndAmount float64 `json:"total_end_amount"` // 期末金额
}
// DecisionReportData 进销存报表数据
type DecisionReportData struct {
CommodityId uint32 `json:"commodity_id"` // 商品id
CommodityName string `json:"commodity_name"` // 商品名称
CategoryID uint32 `json:"category_id"` // 商品分类id
CategoryName string `json:"category_name"` // 商品分类名称
BeginStock uint32 `json:"begin_stock"` // 期初库存
BeginAmount float64 `json:"begin_amount"` // 期初金额
PurchaseStock uint32 `json:"purchase_stock"` // 采购进货
PurchaseReturn uint32 `json:"purchase_return"` // 采购退货
OrderSale uint32 `json:"order_sale"` // 零售销售
OrderReject uint32 `json:"order_reject"` // 零售退货
AllotIn uint32 `json:"allot_in"` // 调拨入库
AllotWaitIn uint32 `json:"allot_wait_in"` // 在途库存(入库)
AllotOut uint32 `json:"allot_out"` // 调拨出库
AllotWaitOut uint32 `json:"allot_wait_out"` // 在途库存(出库)
ProductIn uint32 `json:"product_in"` // 产品入库
SystemOut uint32 `json:"system_out"` // 系统出库
CheckIn uint32 `json:"check_in"` // 盘点入库
CheckOut uint32 `json:"check_out"` // 盘点出库
EndStock uint32 `json:"end_stock"` // 期末数量
EndAmount float64 `json:"end_amount"` // 期末金额
}

View File

@ -2,51 +2,52 @@ package models
import "time"
// InventoryAllotOrder 库存调拨订单表
type InventoryAllotOrder struct {
// ErpInventoryAllotOrder 库存调拨订单表
type ErpInventoryAllotOrder struct {
Model
SerialNumber string `json:"serial_number" gorm:"index"` // 单据编号
DeliverStoreId uint32 `json:"deliver_store_id" gorm:"index"` // 调出门店id
DeliverStoreName string `json:"deliver_store_name"` // 调出门店名称
ReceiveStoreId uint32 `json:"receive_store_id" gorm:"index"` // 调入门店id
ReceiveStoreName string `json:"receive_store_name"` // 调入门店名称
HandlerId uint32 `json:"handler_id" gorm:"index"` // 经手人id
HandlerName string `json:"handler_name"` // 经手人名称
MakerTime *time.Time `json:"maker_time"` // 制单时间
MakerId uint32 `json:"maker_id" gorm:"index"` // 制单人id
MakerName string `json:"maker_name"` // 制单人名称
AuditTime *time.Time `json:"audit_time"` // 审核时间
AuditorId uint32 `json:"auditor_id" gorm:"index"` // 审核人id
AuditorName string `json:"auditor_name"` // 审核人名称
DeliverTime *time.Time `json:"deliver_time"` // 发货时间
ReceiveTime *time.Time `json:"receive_time"` // 收货时间/调入时间
LogisticsNumber string `json:"logistics_number"` // 物流单号
State uint32 `json:"state"` // 1-待审核 2-待发货 3-待收货 4-已完成
TotalCount uint32 `json:"total_count"` // 商品总数量
Commodities []InventoryAllotCommodity `json:"commodities" gorm:"-"` // 库存调拨商品信息
SerialNumber string `json:"serial_number" gorm:"index"` // 单据编号
DeliverStoreId uint32 `json:"deliver_store_id" gorm:"index"` // 调出门店id
DeliverStoreName string `json:"deliver_store_name"` // 调出门店名称
ReceiveStoreId uint32 `json:"receive_store_id" gorm:"index"` // 调入门店id
ReceiveStoreName string `json:"receive_store_name"` // 调入门店名称
HandlerId uint32 `json:"handler_id" gorm:"index"` // 经手人id
HandlerName string `json:"handler_name"` // 经手人名称
MakerTime *time.Time `json:"maker_time"` // 制单时间
MakerId uint32 `json:"maker_id" gorm:"index"` // 制单人id
MakerName string `json:"maker_name"` // 制单人名称
AuditTime *time.Time `json:"audit_time"` // 审核时间
AuditorId uint32 `json:"auditor_id" gorm:"index"` // 审核人id
AuditorName string `json:"auditor_name"` // 审核人名称
DeliverTime *time.Time `json:"deliver_time"` // 发货时间
ReceiveTime *time.Time `json:"receive_time"` // 收货时间/调入时间
LogisticsNumber string `json:"logistics_number"` // 物流单号
State uint32 `json:"state"` // 1-待审核 2-待发货 3-待收货 4-已完成
TotalCount uint32 `json:"total_count"` // 商品总数量
Remark string `json:"remark"` // 备注
Commodities []ErpInventoryAllotCommodity `json:"commodities" gorm:"-"` // 库存调拨商品信息
}
// InventoryAllotCommodity 库存调拨商品信息表
type InventoryAllotCommodity struct {
// ErpInventoryAllotCommodity 库存调拨商品信息表
type ErpInventoryAllotCommodity struct {
Model
ProductOrderId uint32 `json:"product_order_id" gorm:"index"` // 库存调拨订单表id
CommodityId uint32 `json:"commodity_id" gorm:"index"` // 商品id
CommodityName string `json:"commodity_name"` // 商品名称
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
IMEI string `json:"imei"` // 商品串码
Count uint32 `json:"count"` // 数量
Remark string `json:"remark"` // 备注
AllotOrderId uint32 `json:"allot_order_id" gorm:"index"` // 库存调拨订单表id
CommodityId uint32 `json:"commodity_id" gorm:"index"` // 商品id
CommodityName string `json:"commodity_name"` // 商品名称
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
IMEI string `json:"imei"` // 商品串码
Count uint32 `json:"count"` // 数量
Remark string `json:"remark"` // 备注
}
// InventoryAllotAddReq 新增库存调拨入参
type InventoryAllotAddReq struct {
DeliverStoreId uint32 `json:"deliver_store_id" binding:"required"` // 调出门店id
DeliverStoreName string `json:"deliver_store_name" binding:"required"` // 调出门店名称
ReceiveStoreId uint32 `json:"receive_store_id" binding:"required"` // 调入门店id
ReceiveStoreName string `json:"receive_store_name" binding:"required"` // 调入门店名称
HandlerId uint32 `json:"handler_id" binding:"required"` // 经手人id
HandlerName string `json:"handler_name" binding:"required"` // 经手人名称
Commodities []InventoryAllotCommodity `json:"commodities" binding:"required"` // 库存调拨商品信息
DeliverStoreId uint32 `json:"deliver_store_id" binding:"required"` // 调出门店id
DeliverStoreName string `json:"deliver_store_name" binding:"required"` // 调出门店名称
ReceiveStoreId uint32 `json:"receive_store_id" binding:"required"` // 调入门店id
ReceiveStoreName string `json:"receive_store_name" binding:"required"` // 调入门店名称
HandlerId uint32 `json:"handler_id" binding:"required"` // 经手人id
HandlerName string `json:"handler_name" binding:"required"` // 经手人名称
Commodities []ErpInventoryAllotCommodity `json:"commodities" binding:"required"` // 库存调拨商品信息
}
// InventoryAllotEditReq 编辑库存调拨入参
@ -81,10 +82,10 @@ type InventoryAllotListReq struct {
// InventoryAllotListResp 查询库存调拨列表出参
type InventoryAllotListResp struct {
List []InventoryAllotOrder `json:"list"`
Total int `json:"total"` // 总条数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
List []ErpInventoryAllotOrder `json:"list"`
Total int `json:"total"` // 总条数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
}
// InventoryAllotDetailReq 查询库存调拨详情入参
@ -94,8 +95,9 @@ type InventoryAllotDetailReq struct {
// InventoryAllotDeliverReq 调拨发货入参
type InventoryAllotDeliverReq struct {
LogisticsNumber string `json:"logistics_number"` // 物流单号
Remark string `json:"remark"` // 备注
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
LogisticsNumber string `json:"logistics_number"` // 物流单号
Remark string `json:"remark"` // 备注
}
// InventoryAllotReceiveReq 调拨收货入参

View File

@ -2,51 +2,51 @@ package models
import "time"
// InventoryChangeOrder 库存变动订单表
type InventoryChangeOrder struct {
// ErpInventoryChangeOrder 库存变动订单表
type ErpInventoryChangeOrder struct {
Model
SerialNumber string `json:"serial_number" gorm:"index"` // 单据编号
ChangeType string `json:"change_type"` // 类型:add-增加reduce-减少
StoreId uint32 `json:"store_id" gorm:"index"` // 门店id
StoreName string `json:"store_name"` // 门店名称
HandlerId uint32 `json:"handler_id" gorm:"index"` // 经手人id
HandlerName string `json:"handler_name"` // 经手人名称
MakerTime *time.Time `json:"maker_time"` // 制单时间
MakerId uint32 `json:"maker_id" gorm:"index"` // 制单人id
MakerName string `json:"maker_name"` // 制单人名称
AuditTime *time.Time `json:"audit_time"` // 审核时间
AuditorId uint32 `json:"auditor_id" gorm:"index"` // 审核人id
AuditorName string `json:"auditor_name"` // 审核人名称
State uint32 `json:"state"` // 1-待审核 2-已完成
TotalCount uint32 `json:"total_count"` // 总数量
TotalAmount float64 `json:"total_amount"` // 总金额
Commodities []InventoryChangeCommodity `json:"commodities" gorm:"-"` // 库存变动商品信息
SerialNumber string `json:"serial_number" gorm:"index"` // 单据编号
ChangeType string `json:"change_type"` // 类型:add-增加reduce-减少
StoreId uint32 `json:"store_id" gorm:"index"` // 门店id
StoreName string `json:"store_name"` // 门店名称
HandlerId uint32 `json:"handler_id" gorm:"index"` // 经手人id
HandlerName string `json:"handler_name"` // 经手人名称
MakerTime *time.Time `json:"maker_time"` // 制单时间
MakerId uint32 `json:"maker_id" gorm:"index"` // 制单人id
MakerName string `json:"maker_name"` // 制单人名称
AuditTime *time.Time `json:"audit_time"` // 审核时间
AuditorId uint32 `json:"auditor_id" gorm:"index"` // 审核人id
AuditorName string `json:"auditor_name"` // 审核人名称
State uint32 `json:"state"` // 1-待审核 2-已完成
TotalCount uint32 `json:"total_count"` // 总数量
TotalAmount float64 `json:"total_amount"` // 总金额
Commodities []ErpInventoryChangeCommodity `json:"commodities" gorm:"-"` // 库存变动商品信息
}
// InventoryChangeCommodity 库存变动商品信息表
type InventoryChangeCommodity struct {
// ErpInventoryChangeCommodity 库存变动商品信息表
type ErpInventoryChangeCommodity struct {
Model
ProductOrderId uint32 `json:"product_order_id" gorm:"index"` // 库存变动订单表id
CommodityId uint32 `json:"commodity_id" gorm:"index"` // 商品id
CommodityName string `json:"commodity_name"` // 商品名称
SupplierId uint32 `json:"supplier_id" gorm:"index"` // 供应商id
SupplierName string `json:"supplier_name"` // 供应商名称
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
IMEI string `json:"imei"` // 商品串码
Count uint32 `json:"count"` // 计划数量
Price float64 `json:"price"` // 采购单价
EmployeePrice float64 `json:"employee_price"` // 员工成本价
Amount float64 `json:"amount"` // 金额
Remark string `json:"remark"` // 备注
ChangeOrderId uint32 `json:"change_order_id" gorm:"index"` // 库存变动订单表id
CommodityId uint32 `json:"commodity_id" gorm:"index"` // 商品id
CommodityName string `json:"commodity_name"` // 商品名称
SupplierId uint32 `json:"supplier_id" gorm:"index"` // 供应商id
SupplierName string `json:"supplier_name"` // 供应商名称
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
IMEI string `json:"imei"` // 商品串码
Count uint32 `json:"count"` // 计划数量
Price float64 `json:"price"` // 采购单价
EmployeePrice float64 `json:"employee_price"` // 员工成本价
Amount float64 `json:"amount"` // 金额
Remark string `json:"remark"` // 备注
}
// InventoryChangeAddReq 新增库存变动入参
type InventoryChangeAddReq struct {
StoreId uint32 `json:"store_id" binding:"required"` // 门店id
StoreName string `json:"store_name" binding:"required"` // 门店名称
HandlerId uint32 `json:"handler_id" binding:"required"` // 经手人id
HandlerName string `json:"handler_name" binding:"required"` // 经手人名称
Commodities []InventoryChangeCommodity `json:"commodities" binding:"required"` // 库存变动商品信息
StoreId uint32 `json:"store_id" binding:"required"` // 门店id
StoreName string `json:"store_name" binding:"required"` // 门店名称
HandlerId uint32 `json:"handler_id" binding:"required"` // 经手人id
HandlerName string `json:"handler_name" binding:"required"` // 经手人名称
Commodities []ErpInventoryChangeCommodity `json:"commodities" binding:"required"` // 库存变动商品信息
}
// InventoryChangeEditReq 编辑库存变动入参
@ -81,10 +81,10 @@ type InventoryChangeListReq struct {
// InventoryChangeListResp 查询库存变动列表出参
type InventoryChangeListResp struct {
List []InventoryChangeOrder `json:"list"`
Total int `json:"total"` // 总条数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
List []ErpInventoryChangeOrder `json:"list"`
Total int `json:"total"` // 总条数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
}
// InventoryChangeDetailReq 查询库存变动详情入参

View File

@ -1,29 +1,42 @@
package models
import "time"
import (
"errors"
"fmt"
orm "go-admin/common/global"
"go-admin/logger"
"gorm.io/gorm"
"math/rand"
"time"
)
// ProductInventoryOrder 产品入库订单表
type ProductInventoryOrder struct {
const (
ErpInventoryProductOrderUnAudit = 1 // 待审核
ErpInventoryProductOrderFinished = 2 // 已完成
)
// ErpInventoryProductOrder 产品入库订单表
type ErpInventoryProductOrder struct {
Model
SerialNumber string `json:"serial_number" gorm:"index"` // 单据编号
StoreId uint32 `json:"store_id" gorm:"index"` // 门店id
StoreName string `json:"store_name"` // 门店名称
HandlerId uint32 `json:"handler_id" gorm:"index"` // 经手人id
HandlerName string `json:"handler_name"` // 经手人名称
MakerTime *time.Time `json:"maker_time"` // 制单时间
MakerId uint32 `json:"maker_id" gorm:"index"` // 制单人id
MakerName string `json:"maker_name"` // 制单人名称
AuditTime *time.Time `json:"audit_time"` // 审核时间
AuditorId uint32 `json:"auditor_id" gorm:"index"` // 审核人id
AuditorName string `json:"auditor_name"` // 审核人名称
State uint32 `json:"state"` // 1-待审核 2-已完成
TotalCount uint32 `json:"total_count"` // 总数量
TotalAmount float64 `json:"total_amount"` // 总金额
Commodities []ProductInventoryCommodity `json:"commodities" gorm:"-"` // 产品入库商品信息
SerialNumber string `json:"serial_number" gorm:"index"` // 单据编号
StoreId uint32 `json:"store_id" gorm:"index"` // 门店id
StoreName string `json:"store_name"` // 门店名称
HandlerId uint32 `json:"handler_id" gorm:"index"` // 经手人id
HandlerName string `json:"handler_name"` // 经手人名称
MakerTime *time.Time `json:"maker_time"` // 制单时间
MakerId uint32 `json:"maker_id" gorm:"index"` // 制单人id
MakerName string `json:"maker_name"` // 制单人名称
AuditTime *time.Time `json:"audit_time"` // 审核时间
AuditorId uint32 `json:"auditor_id" gorm:"index"` // 审核人id
AuditorName string `json:"auditor_name"` // 审核人名称
State uint32 `json:"state"` // 1-待审核 2-已完成
TotalCount uint32 `json:"total_count"` // 总数量
TotalAmount float64 `json:"total_amount"` // 总金额
Commodities []ErpInventoryProductCommodity `json:"commodities" gorm:"-"` // 产品入库商品信息
}
// ProductInventoryCommodity 产品入库商品信息表
type ProductInventoryCommodity struct {
// ErpInventoryProductCommodity 产品入库商品信息表
type ErpInventoryProductCommodity struct {
Model
ProductOrderId uint32 `json:"product_order_id" gorm:"index"` // 产品入库订单表id
CommodityId uint32 `json:"commodity_id" gorm:"index"` // 商品id
@ -41,11 +54,11 @@ type ProductInventoryCommodity struct {
// ProductInventoryAddReq 新增产品入库入参
type ProductInventoryAddReq struct {
StoreId uint32 `json:"store_id" binding:"required"` // 门店id
StoreName string `json:"store_name" binding:"required"` // 门店名称
HandlerId uint32 `json:"handler_id" binding:"required"` // 经手人id
HandlerName string `json:"handler_name" binding:"required"` // 经手人名称
Commodities []ProductInventoryCommodity `json:"commodities" binding:"required"` // 产品入库商品信息
StoreId uint32 `json:"store_id" binding:"required"` // 门店id
StoreName string `json:"store_name" binding:"required"` // 门店名称
HandlerId uint32 `json:"handler_id" binding:"required"` // 经手人id
HandlerName string `json:"handler_name" binding:"required"` // 经手人名称
Commodities []ErpInventoryProductCommodity `json:"commodities" binding:"required"` // 产品入库商品信息
}
// ProductInventoryEditReq 编辑产品入库入参
@ -79,13 +92,646 @@ type ProductInventoryListReq struct {
// ProductInventoryListResp 查询产品入库列表出参
type ProductInventoryListResp struct {
List []ProductInventoryOrder `json:"list"`
Total int `json:"total"` // 总条数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
List []ErpInventoryProductOrder `json:"list"`
Total int `json:"total"` // 总条数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
}
// ProductInventoryDetailReq 查询产品入库详情入参
type ProductInventoryDetailReq struct {
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
}
// NewProductInventorySn 生成产品入库订单号
func NewProductInventorySn() string {
nowTime := time.Now()
rand.Seed(nowTime.UnixNano())
max := 1
for {
if max > 5 {
logger.Error("create NewProductInventorySn err")
return ""
}
random := rand.Intn(9000) + 1000
sn := fmt.Sprintf("%s%d", nowTime.Format("060102"), random)
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_inventory_product_order WHERE serial_number='%s'", sn))
if err != nil {
logger.Error("exist sn err")
}
if !exist {
return sn
}
max++
}
}
// CheckProductInventoryParam 检查新增产品入库参数
func CheckProductInventoryParam(req *ProductInventoryAddReq, editFlag bool) error {
if len(req.Commodities) == 0 {
return errors.New("商品信息为空")
}
noIMEICommodityMap := make(map[uint32]bool, 0)
for _, item := range req.Commodities {
// 校验商品是否存在
commodityInfo, err := GetCommodity(item.CommodityId)
if err != nil {
return err
}
if commodityInfo.Name == "" {
return fmt.Errorf("商品[%s]不存在", item.CommodityName)
}
// 校验供应商是否存在
supplierInfo, err := GetErpSupplier(item.SupplierId)
if err != nil {
return err
}
if supplierInfo.Name == "" {
return fmt.Errorf("供应商[%s]不存在", item.SupplierName)
}
if editFlag {
if item.ID == 0 {
return fmt.Errorf("商品[%s]ID为空", item.CommodityName)
}
}
// 校验采购单价
if item.Price <= 0 {
return fmt.Errorf("商品[%s]采购单价[%f]错误需大于0", item.CommodityName, item.Price)
}
// 校验数量
if item.Count <= 0 {
return fmt.Errorf("商品[%s]数量[%d]错误需大于0", item.CommodityName, item.Count)
} else {
if item.Count != 1 && item.IMEIType != NoIMEICommodity { // 串码商品数量不为1则报错
return fmt.Errorf("串码商品[%s]数量[%d]错误需为1", item.CommodityName, item.Count)
}
}
// 校验金额
if item.Amount <= 0 {
return fmt.Errorf("商品[%s]金额[%f]错误需大于0", item.CommodityName, item.Amount)
}
// 校验员工成本价
if item.EmployeePrice <= 0 {
return fmt.Errorf("商品[%s]员工成本价[%f]错误需大于0", item.CommodityName, item.EmployeePrice)
}
// 校验数量和金额是否对应
if float64(item.Count)*item.Price != item.Amount {
return fmt.Errorf("商品[%s]数据有误,数量和金额不符", item.CommodityName)
}
// 校验串码类型
switch item.IMEIType {
case 1, 2, 3:
// 串码商品校验串码是否为空
if item.IMEIType != NoIMEICommodity && item.IMEI == "" {
return fmt.Errorf("[%s]是串码商品,其串码不能为空", item.CommodityName)
}
default:
return fmt.Errorf("商品[%s]串码类型[%d]错误", item.CommodityName, item.IMEIType)
}
if item.IMEIType == NoIMEICommodity {
_, ok := noIMEICommodityMap[item.CommodityId]
if !ok {
noIMEICommodityMap[item.CommodityId] = true
} else {
return fmt.Errorf("商品[%s]重复相同的非串码商品只能有1条数据", item.CommodityName)
}
}
}
return nil
}
// AddProductInventory 新增产品入库
func AddProductInventory(req *ProductInventoryAddReq, sysUser *SysUser) (*ErpInventoryProductOrder, error) {
// 检查新增产品入库信息
if err := CheckProductInventoryParam(req, false); err != nil {
return nil, err
}
var err error
nowTime := time.Now()
// 计算产品入库的总数量和总金额
var nTotalCount uint32
var nTotalAmount float64
for i, _ := range req.Commodities {
nTotalCount += req.Commodities[i].Count // 数量
nTotalAmount += req.Commodities[i].Amount // 金额
}
// 组合产品入库订单数据
inventoryProductOrder := &ErpInventoryProductOrder{
SerialNumber: "cpr" + NewProductInventorySn(),
StoreId: req.StoreId,
StoreName: req.StoreName,
HandlerId: req.HandlerId,
HandlerName: req.HandlerName,
MakerTime: &nowTime,
MakerId: uint32(sysUser.UserId),
MakerName: sysUser.NickName,
State: ErpInventoryProductOrderUnAudit,
TotalCount: nTotalCount,
TotalAmount: nTotalAmount,
}
// 创建产品入库订单
begin := orm.Eloquent.Begin()
err = begin.Create(inventoryProductOrder).Error
if err != nil {
begin.Rollback()
logger.Error("create product order err:", logger.Field("err", err))
return nil, err
}
// 创建产品入库商品信息添加产品入库订单id
for i, _ := range req.Commodities {
req.Commodities[i].ProductOrderId = inventoryProductOrder.ID
err = begin.Create(&req.Commodities[i]).Error
if err != nil {
begin.Rollback()
logger.Error("create product commodity err:", logger.Field("err", err))
return nil, err
}
}
err = begin.Commit().Error
if err != nil {
begin.Rollback()
logger.Error("commit product commodity err:", logger.Field("err", err))
return nil, err
}
return inventoryProductOrder, nil
}
// EditProductInventory 编辑产品入库
func EditProductInventory(req *ProductInventoryEditReq) (*ErpInventoryProductOrder, error) {
// 查询订单信息
var inventoryProductOrder ErpInventoryProductOrder
err := orm.Eloquent.Table("erp_inventory_product_order").Where("serial_number = ?", req.SerialNumber).
Find(&inventoryProductOrder).Error
if err != nil {
logger.Error("product order err:", logger.Field("err", err))
return nil, err
}
// 未找到订单
if inventoryProductOrder.ID == 0 {
return nil, fmt.Errorf("未找到该订单,请检查单据编号[%s]", req.SerialNumber)
}
if inventoryProductOrder.State != ErpInventoryProductOrderUnAudit { // 只有待审核的订单才能编辑
return nil, errors.New("订单不是待审核状态")
}
// 检查新增产品入库信息
if err = CheckProductInventoryParam(&req.ProductInventoryAddReq, true); err != nil {
return nil, err
}
// 计算产品入库的总数量和总金额
var nTotalCount uint32
var nTotalAmount float64
for i, _ := range req.Commodities {
nTotalCount += req.Commodities[i].Count // 数量
nTotalAmount += req.Commodities[i].Amount // 金额
}
begin := orm.Eloquent.Begin()
// 1-更新产品订单信息
inventoryProductOrder.StoreId = req.StoreId
inventoryProductOrder.StoreName = req.StoreName
inventoryProductOrder.HandlerId = req.HandlerId
inventoryProductOrder.HandlerName = req.HandlerName
inventoryProductOrder.TotalCount = nTotalCount
inventoryProductOrder.TotalAmount = nTotalAmount
err = begin.Model(&ErpInventoryProductOrder{}).Where("id = ?", inventoryProductOrder.ID).
Updates(inventoryProductOrder).Error
if err != nil {
begin.Rollback()
logger.Error("update erp_order err:", logger.Field("err", err))
return nil, err
}
// 2-更新产品订单商品表
err = updateProductCommodityData(begin, inventoryProductOrder.ID, req)
if err != nil {
begin.Rollback()
logger.Error("update erp_purchase_commodity err:", logger.Field("err", err))
return nil, err
}
err = begin.Commit().Error
if err != nil {
begin.Rollback()
logger.Error("commit err:", logger.Field("err", err))
return nil, err
}
return &inventoryProductOrder, nil
}
// updateProductCommodityData 更新采购订单商品信息
func updateProductCommodityData(gdb *gorm.DB, orderId uint32, req *ProductInventoryEditReq) error {
// 查询现有的零售订单信息
var commodities []ErpInventoryProductCommodity
err := orm.Eloquent.Table("erp_inventory_product_commodity").Where("product_order_id = ?", orderId).Find(&commodities).Error
if err != nil {
logger.Error("query erp_inventory_product_commodity err:", logger.Field("err", err))
return err
}
var newCommodities []ErpInventoryProductCommodity
var deletedCommodities []ErpInventoryProductCommodity
var matchingCommodities []ErpInventoryProductCommodity
// 找到新增的商品
for i, reqCommodity := range req.Commodities {
// 订单商品表信息添加零售订单id
req.Commodities[i].ProductOrderId = orderId
var found bool
for _, dbCommodity := range commodities {
if reqCommodity.CommodityId == dbCommodity.CommodityId && reqCommodity.IMEI == dbCommodity.IMEI {
found = true
break
}
}
if !found {
newCommodities = append(newCommodities, reqCommodity)
}
}
// 找到删除的商品
for _, dbCommodity := range commodities {
var found bool
for _, reqCommodity := range req.Commodities {
if reqCommodity.CommodityId == dbCommodity.CommodityId && reqCommodity.IMEI == dbCommodity.IMEI {
found = true
// 找到匹配的商品,加入匹配列表
matchingCommodities = append(matchingCommodities, reqCommodity)
break
}
}
if !found {
deletedCommodities = append(deletedCommodities, dbCommodity)
}
}
// 2-更新商品订单信息-更新
for _, commodity := range matchingCommodities {
if err := gdb.Model(&ErpInventoryProductCommodity{}).Where("id = ?", commodity.ID).Updates(commodity).Error; err != nil {
logger.Error("更新商品订单信息-更新 error")
return errors.New("操作失败:" + err.Error())
}
}
// 2-更新商品订单信息-新增
if len(newCommodities) != 0 {
err = gdb.Create(&newCommodities).Error
if err != nil {
logger.Error("更新商品订单信息-新增 error")
return errors.New("操作失败:" + err.Error())
}
}
//2-更新商品订单信息-删除
if len(deletedCommodities) != 0 {
err = gdb.Delete(&deletedCommodities).Error
if err != nil {
logger.Error("更新商品订单信息-删除 error")
return errors.New("操作失败:" + err.Error())
}
}
return nil
}
// AuditProductInventory 审核产品入库 state1-审核2-取消审核
func AuditProductInventory(req *ProductInventoryAuditReq, sysUser *SysUser) error {
// 查询订单信息
var inventoryProductOrder ErpInventoryProductOrder
err := orm.Eloquent.Table("erp_inventory_product_order").Where("serial_number = ?", req.SerialNumber).
Find(&inventoryProductOrder).Error
if err != nil {
logger.Error("order err:", logger.Field("err", err))
return err
}
begin := orm.Eloquent.Begin()
// 判断入参state1-审核2-取消审核
orderState := 0
switch req.State {
case 1: // 1-审核:待审核状态可以审核
if inventoryProductOrder.State == ErpInventoryProductOrderFinished { // 订单已审核
return errors.New("订单已完成,无需再次审核")
}
orderState = ErpInventoryProductOrderFinished
// 入库-更新库存信息
err = productAuditAndUpdateStock(begin, inventoryProductOrder)
if err != nil {
begin.Rollback()
logger.Error("ProductAuditAndUpdateStock err:", logger.Field("err", err))
return err
}
case 2: // 2-取消审核
orderState = ErpInventoryProductOrderUnAudit
if inventoryProductOrder.State == ErpInventoryProductOrderUnAudit { // 订单未审核
return errors.New("订单是未审核状态,无需取消审核")
}
// 退库-更新库存信息
err = cancelProductAuditAndUpdateStock(begin, inventoryProductOrder)
if err != nil {
begin.Rollback()
return err
}
default:
logger.Error("order err, req.State is:", logger.Field("req.State", req.State))
return errors.New("参数有误")
}
// 更新产品入库订单表
err = begin.Table("erp_inventory_product_order").Where("id = ?", inventoryProductOrder.ID).
Updates(map[string]interface{}{
"state": orderState,
"auditor_id": sysUser.UserId,
"audit_time": time.Now(),
"auditor_name": sysUser.NickName,
}).Error
if err != nil {
begin.Rollback()
logger.Error("update erp_inventory_product_order err:", logger.Field("err", err))
return err
}
err = begin.Commit().Error
if err != nil {
begin.Rollback()
logger.Errorf("commit err:", err)
return err
}
return nil
}
// cancelProductAuditAndUpdateStock 产品入库反审核后更新库存信息
func cancelProductAuditAndUpdateStock(gdb *gorm.DB, productOrder ErpInventoryProductOrder) error {
// 查询采购入库商品信息
var commodities []ErpInventoryProductCommodity
err := orm.Eloquent.Table("erp_inventory_product_commodity").Where("product_order_id = ?",
productOrder.ID).Find(&commodities).Error
if err != nil {
logger.Error("query erp_inventory_product_commodity err:", logger.Field("err", err))
return err
}
if len(commodities) == 0 {
return errors.New("未查询到商品信息")
}
// 更新库存数量
for i, _ := range commodities {
if commodities[i].IMEIType == 2 { // 串码商品
if commodities[i].IMEI == "" {
return errors.New("串码为空")
}
// 判断该串码商品是否已经销售
var stockCommodityInfo ErpStockCommodity
err = orm.Eloquent.Table("erp_stock_commodity").Where("imei = ?",
commodities[i].IMEI).Find(&stockCommodityInfo).Error
if err != nil {
logger.Error("Inventory RejectStock query commodities err:", logger.Field("err", err))
return err
}
if stockCommodityInfo.State == SoldOut {
return fmt.Errorf("商品[%s]已经销售,不能退货", stockCommodityInfo.ErpCommodityName)
} else if stockCommodityInfo.State == OnSale {
return fmt.Errorf("商品[%s]在销售锁定中,不能退货", stockCommodityInfo.ErpCommodityName)
}
// 更新库存数量
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
productOrder.StoreId, commodities[i].CommodityId).
Updates(map[string]interface{}{"count": gorm.Expr("count - ?", 1)}).Error // 库存数量-1
if err != nil {
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
return err
}
} else {
// 查询入库商品实际库存详情处剩余有效数,不包含已出库的数量
nCount, err := GetCommodityStockByPurchaseId(productOrder.SerialNumber,
commodities[i].CommodityId)
if err != nil {
logger.Error("InventoryErpPurchaseUpdateRejectStock GetCommodityStockByPurchaseId err:",
logger.Field("err", err))
return err
}
// 如果库存数量不够则报错
if nCount < commodities[i].Count {
return fmt.Errorf("商品[%s]采购退货数量超出实际库存数量,请先零售退货",
commodities[i].CommodityName)
}
// 更新库存数量
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
productOrder.StoreId, commodities[i].CommodityId).
Updates(map[string]interface{}{"count": gorm.Expr("count - ?", commodities[i].Count)}).Error // 库存数量-count
if err != nil {
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
return err
}
}
}
// 删除库存商品表对应的记录
err = gdb.Where("original_sn = ? and state = ?", productOrder.SerialNumber, InStock).Delete(&ErpStockCommodity{}).Error
if err != nil {
logger.Error("delete erp_stock_commodity err:", logger.Field("err", err))
return err
}
return nil
}
// productAuditAndUpdateStock 产品入库审核后更新库存信息
func productAuditAndUpdateStock(gdb *gorm.DB, productOrder ErpInventoryProductOrder) error {
// 查询采购入库商品信息
var commodities []ErpInventoryProductCommodity
err := orm.Eloquent.Table("erp_inventory_product_commodity").Where("product_order_id = ?",
productOrder.ID).Find(&commodities).Error
if err != nil {
logger.Error("query erp_inventory_product_commodity err:", logger.Field("err", err))
return err
}
// 遍历采购入库商品信息
var stockList []ErpStockCommodity
for _, v := range commodities {
commodityInfo, err := GetCommodity(v.CommodityId)
if err != nil {
logger.Errorf("GetCommodity err:", err)
return err
}
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock WHERE store_id=%d AND erp_commodity_id=%d",
productOrder.StoreId, v.CommodityId))
if err != nil {
logger.Errorf("exist err:", err)
return err
}
if exist {
err = gdb.Exec(fmt.Sprintf(
"UPDATE erp_stock SET count=count+%d WHERE store_id=%d AND erp_commodity_id=%d",
v.Count, productOrder.StoreId, v.CommodityId)).Error
if err != nil {
logger.Errorf("update stock err:", err)
return err
}
} else {
stock := &ErpStock{
StoreId: productOrder.StoreId,
StoreName: productOrder.StoreName,
ErpCommodityId: v.CommodityId,
ErpCommodityName: v.CommodityName,
ErpCategoryId: commodityInfo.ErpCategoryId,
ErpCategoryName: commodityInfo.ErpCategoryName,
CommoditySerialNumber: commodityInfo.SerialNumber,
IMEIType: v.IMEIType,
RetailPrice: commodityInfo.RetailPrice,
MinRetailPrice: commodityInfo.MinRetailPrice,
Count: v.Count,
DispatchCount: 0,
}
err = gdb.Create(stock).Error
if err != nil {
logger.Errorf("create stock err:", err)
return err
}
}
for i := 0; i < int(v.Count); i++ {
nowTime := time.Now()
stockCommodity := ErpStockCommodity{
StoreId: productOrder.StoreId,
StoreName: productOrder.StoreName,
ErpCommodityId: v.CommodityId,
ErpCommodityName: v.CommodityName,
CommoditySerialNumber: commodityInfo.SerialNumber,
ErpCategoryId: commodityInfo.ErpCategoryId,
ErpCategoryName: commodityInfo.ErpCategoryName,
ErpSupplierId: v.SupplierId,
ErpSupplierName: v.SupplierName,
StaffCostPrice: uint32(v.EmployeePrice - v.Price),
WholesalePrice: uint32(v.Price),
State: InStock,
StorageType: ProductInventory, // 产品入库
FirstStockTime: nowTime,
StockTime: nowTime,
Count: 1,
ErpBarcode: commodityInfo.ErpBarcode, // 240106新增商品条码
IMEIType: v.IMEIType,
IMEI: v.IMEI,
Remark: "",
MemberDiscount: commodityInfo.MemberDiscount,
MinRetailPrice: commodityInfo.MinRetailPrice,
RetailPrice: commodityInfo.RetailPrice,
OriginalSn: productOrder.SerialNumber,
//StockSn: v.SerialNumber,
}
stockList = append(stockList, stockCommodity)
}
}
err = gdb.Debug().Create(&stockList).Error
if err != nil {
logger.Errorf("create stock commodity err:", err)
return err
}
return nil
}
// List 查询采购订单列表
func (m *ProductInventoryListReq) List() (*ProductInventoryListResp, error) {
resp := &ProductInventoryListResp{
PageIndex: m.PageIndex,
PageSize: m.PageSize,
}
page := m.PageIndex - 1
if page < 0 {
page = 0
}
if m.PageSize == 0 {
m.PageSize = 10
}
qs := orm.Eloquent.Table("erp_inventory_product_order")
if m.SerialNumber != "" {
qs = qs.Where("serial_number=?", m.SerialNumber)
} else {
if m.StoreId != 0 {
qs = qs.Where("store_id=?", m.StoreId)
}
if m.HandlerId != 0 {
qs = qs.Where("handler_id=?", m.HandlerId)
}
if m.State != 0 {
qs = qs.Where("state=?", m.State)
}
if m.AuditTimeStart != "" {
parse, err := time.Parse(QueryTimeFormat, m.AuditTimeStart)
if err != nil {
logger.Errorf("ProductInventoryList err:", err)
return nil, err
}
qs = qs.Where("audit_time > ?", parse)
}
if m.AuditTimeEnd != "" {
parse, err := time.Parse(QueryTimeFormat, m.AuditTimeEnd)
if err != nil {
logger.Errorf("ProductInventoryList err:", err)
return nil, err
}
qs = qs.Where("audit_time < ?", parse)
}
}
var count int64
err := qs.Count(&count).Error
if err != nil {
logger.Error("count err:", logger.Field("err", err))
return resp, err
}
resp.Total = int(count)
var orders []ErpInventoryProductOrder
err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&orders).Error
if err != nil && err != RecordNotFound {
logger.Error("product list err:", logger.Field("err", err))
return resp, err
}
// 校验时间如果为01-01-01 08:05则赋值为空
for i, v := range orders {
if v.MakerTime != nil && v.MakerTime.IsZero() {
orders[i].MakerTime = nil
}
if v.AuditTime != nil && v.AuditTime.IsZero() {
orders[i].AuditTime = nil
}
}
resp.List = orders
return resp, nil
}

View File

@ -1009,7 +1009,8 @@ func updatePurchaseCommodityData(gdb *gorm.DB, orderId uint32, req *ErpPurchaseE
for _, dbCommodity := range commodities {
var found bool
for _, reqCommodity := range req.ErpPurchaseCommodities {
if reqCommodity.ID == dbCommodity.ID {
if reqCommodity.ID == dbCommodity.ID { // 应该是比较商品id,前端入参如果有主键id也可以比较
//if reqCommodity.ErpCommodityId == dbCommodity.ErpCommodityId {
found = true
// 找到匹配的商品,加入匹配列表
matchingCommodities = append(matchingCommodities, reqCommodity)
@ -1316,9 +1317,15 @@ func InventoryErpPurchaseUpdateRejectStock(gdb *gorm.DB, list []ErpPurchaseInven
}
var stockCommodity []ErpStockCommodity
// 通过门店id商品id查找状态为1-在库的非串码商品
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? and store_id = ? "+
"and state = ? and imei_type = ?", list[i].ErpCommodityId, purchaseOrder.StoreId, InStock, 1).
//// 通过门店id商品id查找状态为1-在库的非串码商品
//err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? and store_id = ? "+
// "and state = ? and imei_type = ? ", list[i].ErpCommodityId, purchaseOrder.StoreId, InStock, 1).
// Order("id DESC").Find(&stockCommodity).Error
// 通过首次入库订单编号查找状态为1-在库的非串码商品
err = orm.Eloquent.Table("erp_stock_commodity").
Where("erp_commodity_id = ? and state = ? and imei_type = ? and original_sn = ?",
list[i].ErpCommodityId, purchaseOrder.StoreId, InStock, 1, purchaseOrder.RejectedSerialNumber).
Order("id DESC").Find(&stockCommodity).Error
if err != nil {
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))

View File

@ -0,0 +1,14 @@
package router
import (
"github.com/gin-gonic/gin"
"go-admin/app/admin/apis/decision"
"go-admin/app/admin/middleware"
jwt "go-admin/pkg/jwtauth"
)
func registerErpDecisionRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
r := v1.Group("/decision").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
r.POST("report", decision.ErpDecisionReport) // 进销存报表
}

View File

@ -26,15 +26,6 @@ func registerInventoryManageRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJ
r1.POST("list", inventorymanage.ProductInventoryList) // 列表
r1.POST("detail", inventorymanage.ProductInventoryDetail) // 详情
// 库存变动
r2 := v1.Group("/inventory/change").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
r2.POST("add", inventorymanage.InventoryChangeAdd) // 新增
r2.POST("edit", inventorymanage.InventoryChangeEdit) // 编辑
r2.POST("audit", inventorymanage.InventoryChangeAudit) // 审核
r2.POST("delete", inventorymanage.InventoryChangeDelete) // 删除
r2.POST("list", inventorymanage.InventoryChangeList) // 列表
r2.POST("detail", inventorymanage.InventoryChangeDetail) // 详情
// 库存调拨
r3 := v1.Group("/inventory/allot").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
r3.POST("add", inventorymanage.InventoryAllotAdd) // 新增
@ -46,6 +37,15 @@ func registerInventoryManageRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJ
r3.POST("deliver", inventorymanage.InventoryAllotDeliver) // 发货
r3.POST("receive", inventorymanage.InventoryAllotReceive) // 收货
// 库存变动
r2 := v1.Group("/inventory/change").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
r2.POST("add", inventorymanage.InventoryChangeAdd) // 新增
r2.POST("edit", inventorymanage.InventoryChangeEdit) // 编辑
r2.POST("audit", inventorymanage.InventoryChangeAudit) // 审核
r2.POST("delete", inventorymanage.InventoryChangeDelete) // 删除
r2.POST("list", inventorymanage.InventoryChangeList) // 列表
r2.POST("detail", inventorymanage.InventoryChangeDetail) // 详情
// 库存报表
r4 := v1.Group("/inventory/report").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
r4.POST("product", inventorymanage.InventoryReportByProduct) // 产品库存汇总(按门店)

View File

@ -108,4 +108,6 @@ func examplesCheckRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddle
registerErpOrderManageRouter(v1, authMiddleware)
// 采购管理
registerErpPurchaseManageRouter(v1, authMiddleware)
// 决策中心
registerErpDecisionRouter(v1, authMiddleware)
}

View File

@ -41,9 +41,9 @@ settings:
driver: mysql
# 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms
# source: root:myTest@921@tcp(127.0.0.1:3306)/mh_dev?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
# source: mh_dev:d9qy46ONI0ZTF9eH@tcp(112.33.14.191:3306)/mh_dev?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
source: mh_dev:d9qy46ONI0ZTF9eH@tcp(112.33.14.191:3306)/mh_dev?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
# source: mh_pro:c5JBW3X6EEVQluYM@tcp(39.108.188.218:3306)/mh_pro?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
source: mh_test:GPLzZ8rMmbJbKtMh@tcp(112.33.14.191:3306)/mh_test?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
# source: mh_test:GPLzZ8rMmbJbKtMh@tcp(112.33.14.191:3306)/mh_test?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
gen:
# 代码生成读取的数据库名称

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff