1.库存详情导出excel时判断是否有入库采购价、入库员工成本价权限;

2.库存列表增加入参,支持查询不同串码类型;
3.采购入库时判断串码是否重复有缺陷,已优化;
4.采购相关报表金额四舍五入保留2位小数;
This commit is contained in:
chenlin 2024-07-12 15:54:31 +08:00
parent 17c8472e76
commit 0c6325bd2c
6 changed files with 112 additions and 24 deletions

View File

@ -35,6 +35,9 @@ const (
SystemOut = 5 // 系统出库 SystemOut = 5 // 系统出库
CheckOut = 6 // 盘点出库 CheckOut = 6 // 盘点出库
OnSale = 7 // 销售锁定中 OnSale = 7 // 销售锁定中
PurchasePrice = "erp:stock:stockDetails:list:purchasePrice" // 入库采购价
EmployeeCostPrice = "erp:stock:stockDetails:list:employeeCostPrice" // 入库员工成本价
) )
// ErpStock 库存列表 // ErpStock 库存列表
@ -1142,7 +1145,7 @@ func GenerateSerialCode(categoryID uint32) (string, error) {
serialCode := categoryStr + dateStr + randomStr serialCode := categoryStr + dateStr + randomStr
// 检查生成的串码是否已存在 todo 是否需要判断状态,采购退货的可以重复? // 检查生成的串码是否已存在 todo 是否需要判断状态,采购退货的可以重复?
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock_commodity WHERE FIND_IN_SET(%s, imei) > 0 ", serialCode)) exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock_commodity WHERE FIND_IN_SET('%s', imei) > 0 ", serialCode))
if err != nil { if err != nil {
logger.Error("exist sn err") logger.Error("exist sn err")
} }
@ -1446,25 +1449,62 @@ func ErpCommodityListExport(list []ErpCommodity) (string, error) {
return url + fileName, nil return url + fileName, nil
} }
// 判断是否有入库采购价、入库员工成本价的权限
func checkRoleMenu(c *gin.Context, menuName string) (bool, error) {
if tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员" {
return true, nil
}
var sysMenu Menu
err := orm.Eloquent.Table("sys_menu").Raw("select * from sys_menu where permission = ?",
menuName).Scan(&sysMenu).Error
if err != nil {
logger.Errorf("get sys_menu err:", err)
return false, err
}
roleId := tools.GetRoleId(c)
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM sys_role_menu WHERE `menu_id`='%d' "+
"and `role_id`='%d'", sysMenu.MenuId, roleId))
if err != nil {
logger.Errorf("checkRoleMenu QueryRecordExist err:", err)
return false, err
}
return exist, nil
}
// InventoryDetailListExport 导出库存商品列表 // InventoryDetailListExport 导出库存商品列表
func InventoryDetailListExport(list []ErpStockCommodity) (string, error) { func InventoryDetailListExport(list []ErpStockCommodity, exportPurchasePrice bool, exportStaffCostPrice bool) (string, error) {
file := excelize.NewFile() file := excelize.NewFile()
streamWriter, err := file.NewStreamWriter("Sheet1") streamWriter, err := file.NewStreamWriter("Sheet1")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return "", err
} }
url := ExportUrl url := ExportUrl
fileName := time.Now().Format(TimeFormat) + "商品" + ".xlsx" fileName := time.Now().Format(TimeFormat) + "商品" + ".xlsx"
fmt.Println("url fileName:", url+fileName) fmt.Println("url fileName:", url+fileName)
// 设置标题行
title := []interface{}{"商品编号", "商品名称", "商品分类", "是否串码", "商品串码", "所属门店", "供应商", "首次入库时间", "首次入库方式", title := []interface{}{"商品编号", "商品名称", "商品分类", "是否串码", "商品串码", "所属门店", "供应商", "首次入库时间", "首次入库方式",
"首次入库订单编号", "最近入库时间", "入库采购价", "入库员工成本价", "最近库龄", "总库龄", "当前状态", "备注"} "首次入库订单编号", "最近入库时间"}
if exportPurchasePrice {
title = append(title, "入库采购价")
}
if exportStaffCostPrice {
title = append(title, "入库员工成本价")
}
title = append(title, "最近库龄", "总库龄", "当前状态", "备注")
cell, _ := excelize.CoordinatesToCellName(1, 1) cell, _ := excelize.CoordinatesToCellName(1, 1)
if err = streamWriter.SetRow(cell, title); err != nil { if err = streamWriter.SetRow(cell, title); err != nil {
fmt.Println(err) fmt.Println(err)
return "", err
} }
var row []interface{}
for rowId := 0; rowId < len(list); rowId++ { for rowId := 0; rowId < len(list); rowId++ {
isIMEIType := "是" isIMEIType := "是"
if list[rowId].IMEIType == 1 { if list[rowId].IMEIType == 1 {
@ -1492,7 +1532,7 @@ func InventoryDetailListExport(list []ErpStockCommodity) (string, error) {
state = "盘点出库" state = "盘点出库"
} }
row = []interface{}{ row := []interface{}{
list[rowId].CommoditySerialNumber, list[rowId].CommoditySerialNumber,
list[rowId].ErpCommodityName, list[rowId].ErpCommodityName,
list[rowId].ErpCategoryName, list[rowId].ErpCategoryName,
@ -1504,23 +1544,36 @@ func InventoryDetailListExport(list []ErpStockCommodity) (string, error) {
storageType, storageType,
list[rowId].OriginalSn, list[rowId].OriginalSn,
list[rowId].StockTime, list[rowId].StockTime,
list[rowId].WholesalePrice, }
list[rowId].WholesalePrice + list[rowId].StaffCostPrice,
list[rowId].Age, // 控制是否导出入库采购价和入库员工成本价
list[rowId].AllAge, if exportPurchasePrice {
state, row = append(row, list[rowId].WholesalePrice)
list[rowId].Remark} }
if exportStaffCostPrice {
row = append(row, list[rowId].WholesalePrice+list[rowId].StaffCostPrice)
}
row = append(row, list[rowId].Age)
row = append(row, list[rowId].AllAge)
row = append(row, state)
row = append(row, list[rowId].Remark)
cell, _ := excelize.CoordinatesToCellName(1, rowId+2) cell, _ := excelize.CoordinatesToCellName(1, rowId+2)
if err := streamWriter.SetRow(cell, row); err != nil { if err := streamWriter.SetRow(cell, row); err != nil {
fmt.Println(err) fmt.Println(err)
return "", err
} }
} }
if err := streamWriter.Flush(); err != nil { if err := streamWriter.Flush(); err != nil {
fmt.Println(err) fmt.Println(err)
return "", err
} }
fmt.Println("save fileName:", config.ExportConfig.Path+fileName) fmt.Println("save fileName:", config.ExportConfig.Path+fileName)
if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil { if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil {
fmt.Println(err) fmt.Println(err)
return "", err
} }
return url + fileName, nil return url + fileName, nil
} }
@ -1573,6 +1626,7 @@ type ErpStockListReq struct {
SerialNumber string `json:"serial_number"` // 商品编号 SerialNumber string `json:"serial_number"` // 商品编号
CommodityName string `json:"commodity_name"` // 商品名称 CommodityName string `json:"commodity_name"` // 商品名称
ErpCategoryId uint32 `json:"erp_category_id"` // 商品分类 ErpCategoryId uint32 `json:"erp_category_id"` // 商品分类
IsIMEI uint32 `json:"is_imei"` // 是否串码0-查全部 1-查串码类 2-查非串码
StockType uint32 `json:"stock_type"` // 库存情况:1-全部 2-有库存 3-无库存 StockType uint32 `json:"stock_type"` // 库存情况:1-全部 2-有库存 3-无库存
StoreId uint32 `json:"store_id"` // 门店编号 StoreId uint32 `json:"store_id"` // 门店编号
PageIndex int `json:"pageIndex"` // 页码 PageIndex int `json:"pageIndex"` // 页码
@ -1944,11 +1998,11 @@ func (m *ErpStockListReq) stockNoEmptyList(c *gin.Context) (*ErpStockListResp, e
} else { } else {
if len(storeList) > 0 { if len(storeList) > 0 {
if len(storeList) == 1 { if len(storeList) == 1 {
qs = qs.Where("store_id = ?", storeList[0]) qs = qs.Where("erp_stock.store_id = ?", storeList[0])
es = es.Where("store_id = ?", storeList[0]) es = es.Where("erp_stock.store_id = ?", storeList[0])
} else { } else {
qs = qs.Where("store_id IN (?)", storeList) qs = qs.Where("erp_stock.store_id IN (?)", storeList)
es = es.Where("store_id IN (?)", storeList) es = es.Where("erp_stock.store_id IN (?)", storeList)
} }
} else { } else {
return nil, errors.New("用户未绑定门店") return nil, errors.New("用户未绑定门店")
@ -2011,6 +2065,14 @@ func (m *ErpStockListReq) stockNoEmptyList(c *gin.Context) (*ErpStockListResp, e
es = es.Where("erp_commodity.erp_category_id=?", m.ErpCategoryId) es = es.Where("erp_commodity.erp_category_id=?", m.ErpCategoryId)
} }
if m.IsIMEI != 0 {
if m.IsIMEI == 1 { // 查串码数据
qs = qs.Where("erp_commodity.imei_type != ?", NoIMEICommodity)
} else if m.IsIMEI == 2 { // 查非串码数据
qs = qs.Where("erp_commodity.imei_type = ?", NoIMEICommodity)
}
}
var commodities []struct { var commodities []struct {
ErpCommodity ErpCommodity
TotalCount int TotalCount int
@ -2365,11 +2427,18 @@ func (m *ErpStockCommodityListReq) GetDetailList(c *gin.Context, nType uint32) (
if m.IsExport == 1 { if m.IsExport == 1 {
err := qs.Find(&commodities).Order("stock_time DESC,id DESC").Error err := qs.Find(&commodities).Order("stock_time DESC,id DESC").Error
if err != nil && !errors.Is(err, RecordNotFound) { if err != nil && !errors.Is(err, RecordNotFound) {
//logger.Error("dailys err:", err) logger.Error("find err:", logger.Field("err", err))
return resp, err return resp, err
} }
ErpStockCommodityListSetAge(commodities) ErpStockCommodityListSetAge(commodities)
listExport, err := InventoryDetailListExport(commodities) // 判断是否有入库采购价、入库员工成本价的权限
purchasePriceFlag, _ := checkRoleMenu(c, PurchasePrice)
employeeCostPriceFlag, _ := checkRoleMenu(c, EmployeeCostPrice)
fmt.Println("purchasePriceFlag is:", purchasePriceFlag)
fmt.Println("employeeCostPriceFlag is:", employeeCostPriceFlag)
logger.Info("purchasePriceFlag is:", logger.Field("purchasePriceFlag", purchasePriceFlag))
logger.Info("employeeCostPriceFlag is:", logger.Field("employeeCostPriceFlag", purchasePriceFlag))
listExport, err := InventoryDetailListExport(commodities, purchasePriceFlag, employeeCostPriceFlag)
if err != nil { if err != nil {
//logger.Error("list export err:", err) //logger.Error("list export err:", err)
} }
@ -2776,7 +2845,7 @@ func CheckAndConvertBarcode(input string) (string, error) {
// 4.判断逗号隔开的数据数据库是否已存在 // 4.判断逗号隔开的数据数据库是否已存在
for _, part := range parts { for _, part := range parts {
// 检查生成的条码是否已存在 // 检查生成的条码是否已存在
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_commodity WHERE FIND_IN_SET(%s, erp_barcode) > 0", part)) exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_commodity WHERE FIND_IN_SET('%s', erp_barcode) > 0", part))
if err != nil { if err != nil {
logger.Error("exist sn err") logger.Error("exist sn err")
} }
@ -2811,7 +2880,7 @@ func CheckBarcodeById(input string, commodityId uint32) (string, error) {
// 4.判断逗号隔开的数据数据库是否已存在 // 4.判断逗号隔开的数据数据库是否已存在
for _, part := range parts { for _, part := range parts {
// 检查生成的条码是否已存在 // 检查生成的条码是否已存在
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_commodity WHERE FIND_IN_SET(%s, erp_barcode) > 0", part)) exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_commodity WHERE FIND_IN_SET('%s', erp_barcode) > 0", part))
if err != nil { if err != nil {
logger.Error("exist sn err") logger.Error("exist sn err")
} }
@ -2859,7 +2928,7 @@ func GenerateBarcode(categoryCode uint32) (string, error) {
barcode := fmt.Sprintf("%03s%s%s", category.Number[:3], dateCode, randomNumber) barcode := fmt.Sprintf("%03s%s%s", category.Number[:3], dateCode, randomNumber)
// 检查生成的条码是否已存在 // 检查生成的条码是否已存在
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_commodity WHERE FIND_IN_SET(%s, erp_barcode) > 0", barcode)) exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_commodity WHERE FIND_IN_SET('%s', erp_barcode) > 0", barcode))
if err != nil { if err != nil {
logger.Error("exist sn err") logger.Error("exist sn err")
} }

View File

@ -3913,6 +3913,7 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq, c *gin.Context) (*Erp
} }
if req.CashierId != 0 { // 支付方式 if req.CashierId != 0 { // 支付方式
qs = qs.Where("JSON_CONTAINS(cashier_list, ?)", fmt.Sprintf(`{"cashier_id":%d}`, req.CashierId)) qs = qs.Where("JSON_CONTAINS(cashier_list, ?)", fmt.Sprintf(`{"cashier_id":%d}`, req.CashierId))
qs = qs.Where("retail_type=?", RetailTypeSale)
//totalPerQs = totalPerQs.Where("erp_order_pay_way.cashier_id = ?", req.CashierId) //totalPerQs = totalPerQs.Where("erp_order_pay_way.cashier_id = ?", req.CashierId)
} }
if req.StartTime != "" { // 审核开始时间 if req.StartTime != "" { // 审核开始时间

View File

@ -1508,7 +1508,7 @@ func checkPurchaseInventory(req *ErpPurchaseInventoryReq, imeiCheckFlag bool) er
// 如果该商品是串码商品,判断其串码是否会重复 // 如果该商品是串码商品,判断其串码是否会重复
if inventory.IMEI != "" { if inventory.IMEI != "" {
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock_commodity WHERE FIND_IN_SET(%s, imei) > 0", inventory.IMEI)) exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock_commodity WHERE FIND_IN_SET('%s', imei) > 0", inventory.IMEI))
if err != nil { if err != nil {
logger.Error("exist sn err") logger.Error("exist sn err")
} }
@ -3865,6 +3865,7 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq, c *gin.Context
resp.List = reportByOrderDataList resp.List = reportByOrderDataList
} }
nTotalAmount = math.Round(nTotalAmount*100) / 100
resp.Amount = nTotalAmount resp.Amount = nTotalAmount
resp.Count = nTotalCount resp.Count = nTotalCount
//resp.Total = int(count) //resp.Total = int(count)
@ -5764,6 +5765,12 @@ func GetReportDetail(req *ErpPurchaseReportDetailReq, c *gin.Context) (*ErpPurch
resp.Total = int(count) resp.Total = int(count)
resp.Price, resp.EmployeePrice, resp.RejectPrice, resp.DifferencePrice = calculatePrices(reportList) resp.Price, resp.EmployeePrice, resp.RejectPrice, resp.DifferencePrice = calculatePrices(reportList)
// 四舍五入保留2位小数
resp.Price = math.Round(resp.Price*100) / 100
resp.EmployeePrice = math.Round(resp.EmployeePrice*100) / 100
resp.RejectPrice = math.Round(resp.RejectPrice*100) / 100
resp.DifferencePrice = math.Round(resp.DifferencePrice*100) / 100
if req.IsExport == 1 { if req.IsExport == 1 {
resp.List = reportList resp.List = reportList
filePath, err := reportDetailExport(resp) filePath, err := reportDetailExport(resp)

View File

@ -9441,7 +9441,7 @@ const docTemplate = `{
"type": "object", "type": "object",
"properties": { "properties": {
"bank_trx_no": { "bank_trx_no": {
"description": "银流水号", "description": "银流水号",
"type": "string" "type": "string"
}, },
"bill_sn": { "bill_sn": {
@ -11249,6 +11249,10 @@ const docTemplate = `{
"description": "商品分类", "description": "商品分类",
"type": "integer" "type": "integer"
}, },
"is_imei": {
"description": "是否串码0-查全部 1-查串码类 2-查非串码",
"type": "integer"
},
"pageIndex": { "pageIndex": {
"description": "页码", "description": "页码",
"type": "integer" "type": "integer"

View File

@ -9430,7 +9430,7 @@
"type": "object", "type": "object",
"properties": { "properties": {
"bank_trx_no": { "bank_trx_no": {
"description": "银流水号", "description": "银流水号",
"type": "string" "type": "string"
}, },
"bill_sn": { "bill_sn": {
@ -11238,6 +11238,10 @@
"description": "商品分类", "description": "商品分类",
"type": "integer" "type": "integer"
}, },
"is_imei": {
"description": "是否串码0-查全部 1-查串码类 2-查非串码",
"type": "integer"
},
"pageIndex": { "pageIndex": {
"description": "页码", "description": "页码",
"type": "integer" "type": "integer"

View File

@ -2413,7 +2413,7 @@ definitions:
models.ErpOrderRetailDetailReq: models.ErpOrderRetailDetailReq:
properties: properties:
bank_trx_no: bank_trx_no:
description: 流水号 description: 流水号
type: string type: string
bill_sn: bill_sn:
description: 单据编号 description: 单据编号
@ -3730,6 +3730,9 @@ definitions:
erp_category_id: erp_category_id:
description: 商品分类 description: 商品分类
type: integer type: integer
is_imei:
description: 是否串码0-查全部 1-查串码类 2-查非串码
type: integer
pageIndex: pageIndex:
description: 页码 description: 页码
type: integer type: integer