2023-11-08 03:51:33 +00:00
package models
import (
"errors"
"fmt"
2024-04-17 09:44:43 +00:00
"github.com/gin-gonic/gin"
2023-11-08 03:51:33 +00:00
"github.com/xuri/excelize/v2"
orm "go-admin/common/global"
"go-admin/logger"
2024-04-17 01:37:02 +00:00
"go-admin/tools"
2023-11-23 12:38:11 +00:00
"go-admin/tools/config"
2023-11-08 03:51:33 +00:00
"golang.org/x/sync/errgroup"
"gorm.io/gorm"
2024-09-18 09:11:39 +00:00
"math"
2023-12-13 12:05:53 +00:00
"math/rand"
2024-05-10 01:54:37 +00:00
"sort"
2023-11-08 03:51:33 +00:00
"strconv"
"strings"
"sync"
"time"
2024-01-06 08:48:35 +00:00
"unicode/utf8"
2023-11-08 03:51:33 +00:00
)
2023-12-27 11:23:03 +00:00
const (
2024-04-17 01:37:02 +00:00
NoIMEICommodity = 1 // 非串码商品类型
SystemInventory = 1 // 系统入库
2024-03-16 08:19:12 +00:00
PurchaseInventory = 2 // 采购入库
2024-04-10 06:17:19 +00:00
ProductInventory = 3 // 产品入库
2024-04-17 01:37:02 +00:00
CheckInventory = 4 // 盘点入库
2023-12-27 11:23:03 +00:00
InStock = 1 // 在库
SoldOut = 2 // 已售
PurchaseReturn = 3 // 采购退货
2024-07-01 01:44:35 +00:00
InAllot = 4 // 调拨中(调出门店)
2024-04-29 10:10:48 +00:00
SystemOut = 5 // 系统出库
CheckOut = 6 // 盘点出库
OnSale = 7 // 销售锁定中
2024-11-08 10:58:41 +00:00
PurchaseCancel = 8 // 采购订单反审核
2023-12-27 11:23:03 +00:00
)
2023-11-23 12:38:11 +00:00
// ErpStock 库存列表
2023-11-08 03:51:33 +00:00
type ErpStock struct {
Model
2023-11-16 10:09:11 +00:00
StoreId uint32 ` json:"store_id" gorm:"index" ` // 门店编号
StoreName string ` json:"store_name" ` // 门店名称
ErpCommodityId uint32 ` json:"erp_commodity_id" gorm:"index" ` // 商品id
ErpCommodityName string ` json:"erp_commodity_name" ` // 商品名称
ErpCategoryId uint32 ` json:"erp_category_id" gorm:"index" ` // 分类id
ErpCategoryName string ` json:"erp_category_name" ` // 分类名称
CommoditySerialNumber string ` json:"commodity_serial_number" gorm:"index" ` // 商品编码/串码
IMEIType uint32 ` json:"imei_type" ` // 1-无串码 2-串码(系统生成) 3-串码(手动添加)
2024-04-17 01:37:02 +00:00
RetailPrice float64 ` json:"retail_price" ` // 指导零售价
MinRetailPrice float64 ` json:"min_retail_price" ` // 最低零售价
2023-11-16 10:09:11 +00:00
Count uint32 ` json:"count" ` // 数量
2024-04-22 10:12:19 +00:00
DispatchCount uint32 ` json:"dispatch_count" ` // 调拨中数量(调拨中调入)
2024-07-16 10:30:46 +00:00
Commodities [ ] ErpStockCommodity ` json:"commodities" gorm:"-" ` //
DecisionStoreId [ ] uint32 ` json:"decision_store_id" gorm:"-" ` // 门店编号列表(查询进销存的时候使用)
2023-11-08 03:51:33 +00:00
}
2023-11-16 10:09:11 +00:00
// ErpStockCommodity 库存详情
2023-11-08 03:51:33 +00:00
type ErpStockCommodity struct {
Model
2023-11-16 10:09:11 +00:00
ErpStockId uint32 ` json:"erp_stock_id" gorm:"index" ` // 库存id
StoreId uint32 ` json:"store_id" gorm:"index" ` // 门店id
StoreName string ` json:"store_name" ` // 门店名称
ErpCommodityId uint32 ` json:"erp_commodity_id" gorm:"index" ` // 商品id
ErpCommodityName string ` json:"erp_commodity_name" ` // 商品名称
CommoditySerialNumber string ` json:"commodity_serial_number" gorm:"index" ` // 商品编号
ErpCategoryId uint32 ` json:"erp_category_id" gorm:"index" ` // 分类id
ErpCategoryName string ` json:"erp_category_name" ` // 分类名称
2024-01-06 08:48:35 +00:00
ErpBarcode string ` json:"erp_barcode" ` // 商品条码
2023-11-16 10:09:11 +00:00
IMEIType uint32 ` json:"imei_type" ` // 是否串码: 1-无串码 2-串码(系统生成) 3-串码(手动添加)
IMEI string ` json:"imei" ` // 商品串码
ErpSupplierId uint32 ` json:"erp_supplier_id" gorm:"index" ` // 供应商id
ErpSupplierName string ` json:"erp_supplier_name" ` // 供应商名称
StockTime time . Time ` json:"stock_time" ` // 最近入库时间
2024-04-17 01:37:02 +00:00
RetailPrice float64 ` json:"retail_price" ` // 指导零售价
MinRetailPrice float64 ` json:"min_retail_price" ` // 最低零售价
StaffCostPrice float64 ` json:"staff_cost_price" ` // 员工成本价加价( 如: 加价50, 不是加价后的价格)
WholesalePrice float64 ` json:"wholesale_price" ` // 指导采购价
2023-12-22 09:26:34 +00:00
MemberDiscount float64 ` json:"member_discount" ` // 会员优惠
2024-04-17 01:37:02 +00:00
State uint32 ` json:"state" ` // 状态:1-在库 2-已售 3-采购退货 4-调拨中 5-销售锁定中 6-产品出库 7-盘点出库
2023-11-16 10:09:11 +00:00
Count uint32 ` json:"count" ` // 数量
2024-04-17 01:37:02 +00:00
StorageType uint32 ` json:"storage_type" ` // 入库方式: 1-系统入库 2-采购入库 3-产品入库 4-盘点入库
2023-11-16 10:09:11 +00:00
FirstStockTime time . Time ` json:"first_stock_time" ` // 首次入库时间
2024-03-27 10:01:38 +00:00
StockSn string ` json:"stock_sn" ` // 库存订单编号(跟采购入库的入库编号关联)
2024-03-18 11:53:42 +00:00
OriginalSn string ` json:"original_sn" gorm:"index" ` // 首次入库订单编号(单据编号)
2023-11-16 10:09:11 +00:00
StockStartTime time . Time ` json:"stock_start_time" gorm:"-" ` // 最近入库开始时间
StockEndTime time . Time ` json:"stock_end_time" gorm:"-" ` // 最近入库结束时间
Age uint32 ` json:"age" gorm:"-" ` // 最近库龄
AllAge uint32 ` json:"all_age" gorm:"-" ` // 总库龄
2023-11-24 09:09:24 +00:00
Remark string ` json:"remark" ` // 备注
2024-09-14 09:31:16 +00:00
CategoryNumber string ` json:"category_number" gorm:"-" ` // 商品分类编号
2024-03-27 10:01:38 +00:00
//ErpOrderCommodityId uint32 `json:"erp_order_commodity_id"` // 零售订单商品表的主键ID( 后端使用, 前端忽略)
2023-11-16 10:09:11 +00:00
//Commodity ErpCommodity `json:"commodity" gorm:"-"`
2023-11-08 03:51:33 +00:00
}
2023-11-16 10:09:11 +00:00
// ErpCommodity 商品表
2023-11-08 03:51:33 +00:00
type ErpCommodity struct {
Model
SerialNumber string ` json:"serial_number" ` // 商品编号
Number uint32 ` json:"number" ` // 商品数量
Name string ` json:"name" ` // 商品名称
ErpCategoryId uint32 ` json:"erp_category_id" gorm:"index" ` // 商品分类id
ErpCategoryName string ` json:"erp_category_name" ` // 商品分类名称
2024-01-06 08:48:35 +00:00
ErpBarcode string ` json:"erp_barcode" ` // 商品条码
2023-11-24 09:09:24 +00:00
IsIMEI uint32 ` json:"is_imei" gorm:"-" ` // 是否串码: 1-串码类 2-非串码
2023-11-09 10:26:19 +00:00
IMEIType uint32 ` json:"imei_type" ` // 1-无串码 2-串码(系统生成) 3-串码(手动添加)
2023-11-08 03:51:33 +00:00
IMEI string ` json:"imei" ` // 串码
ErpSupplierId uint32 ` json:"erp_supplier_id" gorm:"index" ` // 主供应商id
ErpSupplierName string ` json:"erp_supplier_name" ` // 主供应商名称
2024-04-17 01:37:02 +00:00
RetailPrice float64 ` json:"retail_price" ` // 指导零售价
MinRetailPrice float64 ` json:"min_retail_price" ` // 最低零售价
StaffCostPrice float64 ` json:"staff_cost_price" ` // 员工成本价加价( 如: 加价50, 不是加价后的价格)
WholesalePrice float64 ` json:"wholesale_price" ` // 指导采购价
2023-11-08 03:51:33 +00:00
Brokerage1 float64 ` json:"brokerage_1" ` // 销售毛利提成
Brokerage2 float64 ` json:"brokerage_2" ` // 员工毛利提成
MemberDiscount float64 ` json:"member_discount" ` // 会员优惠
Origin string ` json:"origin" ` // 产地
Remark string ` json:"remark" gorm:"type:varchar(512)" ` // 备注
2024-03-27 10:01:38 +00:00
StockCount uint32 ` json:"stock_count" gorm:"-" ` // 库存数量
2024-08-14 01:52:38 +00:00
Img string ` json:"img" ` // 图片
2024-11-13 07:49:57 +00:00
StopPurchase uint32 ` json:"stop_purchase" ` // 0-未勾选, 正常采购; 1-勾选,停止采购
2023-11-08 03:51:33 +00:00
ErpCategory * ErpCategory ` json:"erp_category" gorm:"-" `
}
2023-11-23 12:38:11 +00:00
// ErpCategory 商品分类
2023-11-08 03:51:33 +00:00
type ErpCategory struct {
Model
Name string ` json:"name" ` // 名称
Priority string ` json:"priority" ` // 分类
2024-01-06 08:48:35 +00:00
Number string ` json:"number" `
2023-11-08 03:51:33 +00:00
FullNum uint32 ` json:"full_num" `
State uint32 ` json:"state" ` // 1-未使用 2-使用 3-隐藏
Level uint32 ` json:"level" ` // 分类层级
Pid uint32 ` json:"pid" gorm:"index" `
Sort uint32 ` json:"sort" `
SubCats [ ] ErpCategory ` json:"sub_cats" gorm:"-" ` // 子列表
// erp_category
}
2023-11-23 12:38:11 +00:00
// ErpSupplier 供应商
2023-11-08 03:51:33 +00:00
type ErpSupplier struct {
Model
Number string ` json:"number" gorm:"index" `
Name string ` json:"name" `
Contact string ` json:"contact" `
Tel string ` json:"tel" `
Address string ` json:"address" `
OpeningBank string ` json:"opening_bank" `
BankAccount string ` json:"bank_account" `
PaymentCycle uint32 ` json:"payment_cycle" `
TaxNumber string ` json:"tax_number" `
StoreIds string ` json:"store_ids" `
Landline string ` json:"landline" `
Email string ` json:"email" `
CompanyWebsite string ` json:"company_website" `
// erp_supplier
}
type ErpInventoryStock struct {
Model
2024-04-17 01:37:02 +00:00
StoreId uint32 ` json:"store_id" gorm:"index" `
StoreName string ` json:"store_name" `
ErpCommodityId uint32 ` json:"erp_commodity_id" gorm:"index" `
ErpCommodityName string ` json:"erp_commodity_name" `
ErpCategoryId uint32 ` json:"erp_category_id" gorm:"index" `
ErpCategoryName string ` json:"erp_category_name" `
CommoditySerialNumber string ` json:"commodity_serial_number" gorm:"index" `
IMEIType uint32 ` json:"imei_type" ` // 1-无串码 2-串码(系统生成) 3-串码(手动添加)
RetailPrice float64 ` json:"retail_price" `
MinRetailPrice float64 ` json:"min_retail_price" `
Count uint32 ` json:"count" `
Sn string ` json:"sn" gorm:"index" `
2023-11-08 03:51:33 +00:00
//ErpSupplierId uint32 `json:"erp_supplier_id" gorm:"index"`
//ErpSupplierName string `json:"erp_supplier_name"`
//IMEI string `json:"imei"`
//StockTime time.Time `json:"stock_time"`
//StaffCostPrice uint32 `json:"staff_cost_price"`
//WholesalePrice uint32 `json:"wholesale_price"`
// erp_inventory_stock
}
type ErpInventoryStockCommodity struct {
Model
ErpInventoryStockId uint32 ` json:"erp_inventory_stock_id" gorm:"index" `
ErpCommodityId uint32 ` json:"erp_commodity_id" gorm:"index" `
ErpCommodityName string ` json:"erp_commodity_name" `
CommoditySerialNumber string ` json:"commodity_serial_number" gorm:"index" `
2023-11-09 10:26:19 +00:00
IMEIType uint32 ` json:"imei_type" ` // 1-无串码 2-串码(系统生成) 3-串码(手动添加)
2023-11-08 03:51:33 +00:00
IMEI string ` json:"imei" `
ErpSupplierId uint32 ` json:"erp_supplier_id" gorm:"index" `
ErpSupplierName string ` json:"erp_supplier_name" `
StockTime time . Time ` json:"stock_time" `
2024-04-17 01:37:02 +00:00
RetailPrice float64 ` json:"retail_price" `
MinRetailPrice float64 ` json:"min_retail_price" `
StaffCostPrice float64 ` json:"staff_cost_price" `
WholesalePrice float64 ` json:"wholesale_price" `
2023-11-08 03:51:33 +00:00
Count uint32 ` json:"count" `
StorageType uint32 ` json:"storage_type" `
Sn string ` json:"sn" gorm:"index" `
//StoreId uint32 `json:"store_id" gorm:"index"`
//StoreName string `json:"store_name"`
//ErpCategoryId uint32 `json:"erp_category_id" gorm:"index"`
//ErpCategoryName string `json:"erp_category_name"`
// erp_inventory_stock_commodity
}
2024-01-06 08:48:35 +00:00
// QueryCodeReq 查询商品串码或条码入参
type QueryCodeReq struct {
ScanCode string ` json:"scan_code" binding:"required" ` // 扫码枪扫码数据:串码/条码
PageIndex int ` json:"pageIndex" ` // 页码
PageSize int ` json:"pageSize" ` // 页面条数
2024-06-20 06:32:03 +00:00
State uint32 ` json:"state" ` // 库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库( 前端只看1, 4)
StoreId uint32 ` json:"store_id" ` // 门店id
2024-01-06 08:48:35 +00:00
}
type QueryCodeResp struct {
List [ ] string ` json:"list" ` // 串码/条码
Total int ` json:"count" ` // 数据总条数
PageIndex int ` json:"pageIndex" ` // 页码
PageSize int ` json:"pageSize" ` // 每页展示条数
}
2024-07-01 01:44:35 +00:00
// QueryNameReq 通过名称模糊查询商品库存详情入参
type QueryNameReq struct {
CommodityName string ` json:"commodity_name" binding:"required" ` // 商品名称
PageIndex int ` json:"pageIndex" ` // 页码
PageSize int ` json:"pageSize" ` // 每页展示数据条数
State uint32 ` json:"state" ` // 库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库( 前端只看1, 4)
StoreId uint32 ` json:"store_id" ` // 门店id
}
2023-11-23 12:38:11 +00:00
// IdInit 新增/编辑商品时获取分类和供应商信息
2024-01-06 08:48:35 +00:00
func ( c * ErpCommodity ) IdInit ( ) error {
2023-11-08 03:51:33 +00:00
if c . ErpCategoryId != 0 {
if c . ErpCategory == nil {
category , err := GetErpCategory ( c . ErpCategoryId )
2024-01-06 08:48:35 +00:00
if err != nil || category . ID == 0 {
2023-11-08 03:51:33 +00:00
//logger.Error("get erp category err:", err)
2024-01-06 08:48:35 +00:00
return errors . New ( "商品分类信息不存在" )
2023-11-08 03:51:33 +00:00
}
c . ErpCategory = category
}
c . ErpCategoryName = c . ErpCategory . Name
}
if c . ErpSupplierId != 0 {
supplier , err := GetErpSupplier ( c . ErpSupplierId )
2024-01-06 08:48:35 +00:00
if err != nil || supplier . ID == 0 {
2023-11-08 03:51:33 +00:00
//logger.Error("get erp category err:", err)
2024-01-06 08:48:35 +00:00
return errors . New ( "供应商信息不存在" )
2023-11-08 03:51:33 +00:00
} else {
c . ErpSupplierName = supplier . Name
}
}
2024-01-06 08:48:35 +00:00
return nil
2023-11-08 03:51:33 +00:00
}
2023-11-23 12:38:11 +00:00
// GetErpCategory 根据id查询分类信息
2023-11-08 03:51:33 +00:00
func GetErpCategory ( id uint32 ) ( * ErpCategory , error ) {
category := new ( ErpCategory )
err := orm . Eloquent . Table ( "erp_category" ) . Where ( "id=?" , id ) . Find ( category ) . Error
if err != nil {
//logger.Error("category err:", err)
return category , err
}
return category , nil
}
2023-11-23 12:38:11 +00:00
// GetErpSupplier 根据id查询供应商
2023-11-08 03:51:33 +00:00
func GetErpSupplier ( id uint32 ) ( * ErpSupplier , error ) {
supplier := new ( ErpSupplier )
err := orm . Eloquent . Table ( "erp_supplier" ) . Where ( "id=?" , id ) . Find ( supplier ) . Error
if err != nil {
//logger.Error("category err:", err)
return supplier , err
}
return supplier , err
}
2023-11-23 12:38:11 +00:00
// SetErpCategory 新增/编辑商品时设置分类信息
2023-11-08 03:51:33 +00:00
func ( c * ErpCommodity ) SetErpCategory ( ) error {
if c . ErpCategoryId != 0 {
category , err := GetErpCategory ( c . ErpCategoryId )
if err != nil {
2024-01-06 08:48:35 +00:00
logger . Errorf ( "get erp category err:" , err )
2023-11-08 03:51:33 +00:00
return err
}
c . ErpCategory = category
return nil
}
return errors . New ( "erp category id null" )
}
type ErpCommodityListReq struct {
2023-11-09 10:26:19 +00:00
SerialNumber string ` json:"serial_number" ` // 商品编号
ErpCommodityName string ` json:"erp_commodity_name" ` // 商品名称
ErpCategoryId uint32 ` json:"erp_category_id" ` // 商品分类id
IMEI string ` json:"imei" ` // 串码
2024-05-31 09:51:41 +00:00
ErpBarcode string ` json:"erp_barcode" ` // 商品条码
2023-11-09 10:26:19 +00:00
ErpSupplierId uint32 ` json:"erp_supplier_id" ` // 供应商id
2024-11-20 08:17:53 +00:00
PurchaseType uint32 ` json:"purchase_type" ` // 0-全部, 1-正常采购, 2-停止采购
2023-11-28 09:33:38 +00:00
PageIndex int ` json:"pageIndex" ` // 页码
PageSize int ` json:"pageSize" ` // 每页展示数据条数
2023-11-09 10:26:19 +00:00
IsExport uint32 ` json:"is_export" ` // 1-导出
2023-11-08 03:51:33 +00:00
}
type ErpCommodityListResp struct {
List [ ] ErpCommodity ` json:"list" `
2024-02-02 06:33:45 +00:00
Total int ` json:"total" ` // 数据总条数
2023-11-28 09:33:38 +00:00
PageIndex int ` json:"pageIndex" ` // 页码
PageSize int ` json:"pageSize" ` // 每页展示条数
2024-02-01 10:11:22 +00:00
ExportUrl string ` json:"export_url" ` // 文件路径
2023-11-08 03:51:33 +00:00
}
2024-07-01 01:44:35 +00:00
//func (m *ErpCommodityListReq) List() (*ErpCommodityListResp, error) {
// resp := &ErpCommodityListResp{
// 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.Debug().Table("erp_commodity")
// if m.SerialNumber != "" {
// qs = qs.Where("serial_number=?", m.SerialNumber)
// }
// if m.ErpCommodityName != "" {
// qs = qs.Where("name Like '%" + m.ErpCommodityName + "%'")
// //qs = qs.Where("name LIKE ?", m.Name)
// }
// if m.IMEI != "" {
// qs = qs.Where("imei=?", m.IMEI)
// }
// if m.ErpCategoryId != 0 {
// categoryInfo, err := GetErpCategory(m.ErpCategoryId)
// if err != nil {
// return nil, err
// }
// qs = qs.Where("serial_number like ?", categoryInfo.Number+"%")
// }
// if m.ErpSupplierId != 0 {
// qs = qs.Where("erp_supplier_id=?", m.ErpSupplierId)
// }
// if m.ErpBarcode != "" {
// qs = qs.Where("erp_barcode LIKE ?", "%"+m.ErpBarcode+"%")
// }
//
// var count int64
// err := qs.Count(&count).Error
// if err != nil {
// //logger.Error("count err:", err)
// return resp, err
// }
//
// var commodities []ErpCommodity
// err = qs.Order("id DESC").Find(&commodities).Error
// if err != nil && err != RecordNotFound {
// //logger.Error("dailys err:", err)
// return resp, err
// }
//
// // 按商品编号进行排序
// SortCommoditiesAsc(commodities)
//
// if m.IsExport == 1 {
// listExport, err := ErpCommodityListExport(commodities)
// if err != nil {
// //logger.Error("list export err:", err)
// }
// resp.ExportUrl = listExport
// } else {
// for i, v := range commodities {
// if v.IMEIType == 1 { //无串码
// commodities[i].IsIMEI = 2 // 非串码
// } else {
// commodities[i].IsIMEI = 1 // 串码
// }
//
// // 查询库存数量
// var stockCount int64
// err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? and state = ?",
// v.ID, InStock).Count(&stockCount).Error
// if err != nil {
// return nil, err
// }
// commodities[i].StockCount = uint32(stockCount)
// }
//
// // 计算分页所需的切片索引
// startIndex := page * m.PageSize
// endIndex := (page + 1) * m.PageSize
// if endIndex > len(commodities) {
// endIndex = len(commodities)
// }
// resp.List = commodities[startIndex:endIndex]
//
// //跟之前保持一致
// resp.Total = int(count)
// resp.PageIndex = page + 1
// resp.PageSize = m.PageSize
// }
//
// return resp, nil
//}
2023-11-08 03:51:33 +00:00
func ( m * ErpCommodityListReq ) List ( ) ( * ErpCommodityListResp , error ) {
resp := & ErpCommodityListResp {
2023-11-28 09:33:38 +00:00
PageIndex : m . PageIndex ,
PageSize : m . PageSize ,
2023-11-08 03:51:33 +00:00
}
2023-11-28 09:33:38 +00:00
page := m . PageIndex - 1
2023-11-08 03:51:33 +00:00
if page < 0 {
page = 0
}
if m . PageSize == 0 {
m . PageSize = 10
}
2024-07-01 01:44:35 +00:00
2024-09-26 03:43:52 +00:00
qs := orm . Eloquent . Table ( "erp_commodity" )
2023-11-08 03:51:33 +00:00
if m . SerialNumber != "" {
2024-07-01 01:44:35 +00:00
qs = qs . Where ( "serial_number = ?" , m . SerialNumber )
2023-11-08 03:51:33 +00:00
}
if m . ErpCommodityName != "" {
2024-07-01 01:44:35 +00:00
qs = qs . Where ( "name LIKE ?" , "%" + m . ErpCommodityName + "%" )
2023-11-08 03:51:33 +00:00
}
if m . IMEI != "" {
2024-07-01 01:44:35 +00:00
qs = qs . Where ( "imei = ?" , m . IMEI )
2023-11-08 03:51:33 +00:00
}
if m . ErpCategoryId != 0 {
2024-03-27 10:01:38 +00:00
categoryInfo , err := GetErpCategory ( m . ErpCategoryId )
if err != nil {
return nil , err
}
2024-07-01 01:44:35 +00:00
qs = qs . Where ( "serial_number LIKE ?" , categoryInfo . Number + "%" )
2023-11-08 03:51:33 +00:00
}
if m . ErpSupplierId != 0 {
2024-07-01 01:44:35 +00:00
qs = qs . Where ( "erp_supplier_id = ?" , m . ErpSupplierId )
2023-11-08 03:51:33 +00:00
}
2024-05-31 09:51:41 +00:00
if m . ErpBarcode != "" {
2024-06-20 06:32:03 +00:00
qs = qs . Where ( "erp_barcode LIKE ?" , "%" + m . ErpBarcode + "%" )
2024-05-31 09:51:41 +00:00
}
2024-11-20 08:17:53 +00:00
if m . PurchaseType != 0 {
switch m . PurchaseType {
case 1 : // 正常采购
qs = qs . Where ( "stop_purchase = ?" , 0 )
case 2 : // 停止采购
qs = qs . Where ( "stop_purchase = ?" , 1 )
}
}
2023-11-08 03:51:33 +00:00
var count int64
err := qs . Count ( & count ) . Error
if err != nil {
return resp , err
}
2024-05-10 01:54:37 +00:00
2023-11-08 03:51:33 +00:00
var commodities [ ] ErpCommodity
2024-05-10 01:54:37 +00:00
err = qs . Order ( "id DESC" ) . Find ( & commodities ) . Error
if err != nil && err != RecordNotFound {
return resp , err
}
2023-11-08 03:51:33 +00:00
2024-05-10 01:54:37 +00:00
// 按商品编号进行排序
2024-06-14 07:15:39 +00:00
SortCommoditiesAsc ( commodities )
2023-11-08 03:51:33 +00:00
2024-05-10 01:54:37 +00:00
if m . IsExport == 1 {
2023-11-08 03:51:33 +00:00
listExport , err := ErpCommodityListExport ( commodities )
if err != nil {
2024-07-01 01:44:35 +00:00
return resp , err
2023-11-08 03:51:33 +00:00
}
resp . ExportUrl = listExport
} else {
2024-07-01 01:44:35 +00:00
commodityIDs := make ( [ ] uint32 , len ( commodities ) )
2024-05-10 01:54:37 +00:00
for i , v := range commodities {
2024-07-01 01:44:35 +00:00
commodityIDs [ i ] = v . ID
if v . IMEIType == 1 {
commodities [ i ] . IsIMEI = 2
2024-05-10 01:54:37 +00:00
} else {
2024-07-01 01:44:35 +00:00
commodities [ i ] . IsIMEI = 1
2024-05-10 01:54:37 +00:00
}
2024-07-01 01:44:35 +00:00
}
2024-05-10 01:54:37 +00:00
2024-07-01 01:44:35 +00:00
// 批量查询库存数量
var stockCounts [ ] struct {
ErpCommodityID uint32 ` gorm:"column:erp_commodity_id" `
StockCount int64 ` gorm:"column:stock_count" `
}
err = orm . Eloquent . Table ( "erp_stock_commodity" ) .
Where ( "erp_commodity_id IN (?) AND state = ?" , commodityIDs , InStock ) .
Select ( "erp_commodity_id, COUNT(*) as stock_count" ) .
Group ( "erp_commodity_id" ) .
Scan ( & stockCounts ) . Error
if err != nil {
return nil , err
}
// 将库存数量填充回commodities
stockCountMap := make ( map [ uint32 ] int64 )
for _ , sc := range stockCounts {
stockCountMap [ sc . ErpCommodityID ] = sc . StockCount
}
for i , v := range commodities {
commodities [ i ] . StockCount = uint32 ( stockCountMap [ v . ID ] )
2023-11-08 03:51:33 +00:00
}
2024-05-10 01:54:37 +00:00
// 计算分页所需的切片索引
startIndex := page * m . PageSize
2024-09-26 09:07:01 +00:00
if ( len ( commodities ) / m . PageSize + 1 ) * m . PageSize < startIndex {
2024-09-20 03:09:50 +00:00
startIndex = 0
page = 0
}
2024-05-10 01:54:37 +00:00
endIndex := ( page + 1 ) * m . PageSize
if endIndex > len ( commodities ) {
endIndex = len ( commodities )
}
resp . List = commodities [ startIndex : endIndex ]
resp . Total = int ( count )
resp . PageIndex = page + 1
resp . PageSize = m . PageSize
2023-11-08 03:51:33 +00:00
}
2024-05-10 01:54:37 +00:00
return resp , nil
}
2024-07-23 02:28:53 +00:00
// SortByErpSupplierId 对商品数组进行排序, 先按供应商ID排序, 如果相同则按商品编号排序( 升序)
func SortByErpSupplierId ( commodities [ ] ErpCommodity , supplierIDDesc bool ) {
// 定义排序函数
less := func ( i , j int ) bool {
// 按照供应商ID排序
if commodities [ i ] . ErpSupplierId != commodities [ j ] . ErpSupplierId {
if supplierIDDesc { // 降序 DESC
return commodities [ i ] . ErpSupplierId > commodities [ j ] . ErpSupplierId
}
return commodities [ i ] . ErpSupplierId < commodities [ j ] . ErpSupplierId // 升序 ASC
}
// 解析商品编号,提取分类编号和商品编号的数字部分
catNumI , subCatNumI , threeSubCatNumI , itemNumI := parseSerialNumber ( commodities [ i ] . SerialNumber )
catNumJ , subCatNumJ , threeSubCatNumJ , itemNumJ := parseSerialNumber ( commodities [ j ] . SerialNumber )
// 按照分类编号从小到大排序
if catNumI != catNumJ {
return catNumI < catNumJ
}
// 如果分类编号相同,按照具体分类下的商品编号递增排序
if subCatNumI != subCatNumJ {
return subCatNumI < subCatNumJ
}
if threeSubCatNumI != threeSubCatNumJ {
return threeSubCatNumI < threeSubCatNumJ
}
// 如果具体分类编号也相同,按照商品编号递增排序
return itemNumI < itemNumJ
}
// 调用排序函数进行排序
sort . SliceStable ( commodities , less )
}
2024-05-10 01:54:37 +00:00
// SortStockCommodities 对库存商品数组进行排序
func SortStockCommodities ( commodities [ ] ErpStock ) {
// 定义排序函数
less := func ( i , j int ) bool {
// 解析商品编号,提取分类编号和商品编号的数字部分
catNumI , subCatNumI , threeSubCatNumI , itemNumI := parseSerialNumber ( commodities [ i ] . CommoditySerialNumber )
catNumJ , subCatNumJ , threeSubCatNumJ , itemNumJ := parseSerialNumber ( commodities [ j ] . CommoditySerialNumber )
// 按照分类编号从小到大排序
if catNumI != catNumJ {
return catNumI < catNumJ
2023-11-24 09:09:24 +00:00
}
2024-03-27 10:01:38 +00:00
2024-05-10 01:54:37 +00:00
// 如果分类编号相同,按照具体分类下的商品编号递增排序
if subCatNumI != subCatNumJ {
return subCatNumI < subCatNumJ
}
if threeSubCatNumI != threeSubCatNumJ {
return threeSubCatNumI < threeSubCatNumJ
2024-03-27 10:01:38 +00:00
}
2024-05-10 01:54:37 +00:00
// 如果具体分类编号也相同,按照商品编号递增排序
return itemNumI < itemNumJ
2023-11-24 09:09:24 +00:00
}
2024-05-10 01:54:37 +00:00
// 调用排序函数进行排序
sort . SliceStable ( commodities , less )
}
2023-11-28 09:33:38 +00:00
2024-06-14 07:15:39 +00:00
// SortCommoditiesAsc 对商品数组进行排序(升序)
func SortCommoditiesAsc ( commodities [ ] ErpCommodity ) {
2024-05-10 01:54:37 +00:00
// 定义排序函数
less := func ( i , j int ) bool {
// 解析商品编号,提取分类编号和商品编号的数字部分
catNumI , subCatNumI , threeSubCatNumI , itemNumI := parseSerialNumber ( commodities [ i ] . SerialNumber )
catNumJ , subCatNumJ , threeSubCatNumJ , itemNumJ := parseSerialNumber ( commodities [ j ] . SerialNumber )
// 按照分类编号从小到大排序
if catNumI != catNumJ {
return catNumI < catNumJ
}
// 如果分类编号相同,按照具体分类下的商品编号递增排序
if subCatNumI != subCatNumJ {
return subCatNumI < subCatNumJ
}
if threeSubCatNumI != threeSubCatNumJ {
return threeSubCatNumI < threeSubCatNumJ
}
// 如果具体分类编号也相同,按照商品编号递增排序
return itemNumI < itemNumJ
}
// 调用排序函数进行排序
sort . SliceStable ( commodities , less )
}
2024-06-14 07:15:39 +00:00
// SortCommoditiesDesc 对商品数组进行排序(降序)
func SortCommoditiesDesc ( commodities [ ] ErpCommodity ) {
// 定义排序函数
less := func ( i , j int ) bool {
// 解析商品编号,提取分类编号和商品编号的数字部分
catNumI , subCatNumI , threeSubCatNumI , itemNumI := parseSerialNumber ( commodities [ i ] . SerialNumber )
catNumJ , subCatNumJ , threeSubCatNumJ , itemNumJ := parseSerialNumber ( commodities [ j ] . SerialNumber )
// 按照分类编号从大到小排序
if catNumI != catNumJ {
return catNumI > catNumJ
}
// 如果分类编号相同,按照具体分类下的商品编号递增排序
if subCatNumI != subCatNumJ {
return subCatNumI > subCatNumJ
}
if threeSubCatNumI != threeSubCatNumJ {
return threeSubCatNumI > threeSubCatNumJ
}
// 如果具体分类编号也相同,按照商品编号递增排序
return itemNumI > itemNumJ
}
// 调用排序函数进行排序
sort . SliceStable ( commodities , less )
}
2024-05-31 09:51:41 +00:00
// SortReportByAllotDataCommodities 对商品数组进行排序
func SortReportByAllotDataCommodities ( commodities [ ] ReportByAllotData ) {
// 定义排序函数
less := func ( i , j int ) bool {
// 解析商品编号,提取分类编号和商品编号的数字部分
catNumI , subCatNumI , threeSubCatNumI , itemNumI := parseSerialNumber ( commodities [ i ] . CommoditySerialNumber )
catNumJ , subCatNumJ , threeSubCatNumJ , itemNumJ := parseSerialNumber ( commodities [ j ] . CommoditySerialNumber )
// 按照分类编号从小到大排序
if catNumI != catNumJ {
return catNumI < catNumJ
}
// 如果分类编号相同,按照具体分类下的商品编号递增排序
if subCatNumI != subCatNumJ {
return subCatNumI < subCatNumJ
}
if threeSubCatNumI != threeSubCatNumJ {
return threeSubCatNumI < threeSubCatNumJ
}
// 如果具体分类编号也相同,按照商品编号递增排序
return itemNumI < itemNumJ
}
// 调用排序函数进行排序
sort . SliceStable ( commodities , less )
}
2024-06-20 06:32:03 +00:00
// SortReportByDecisionCommodities 对商品数组进行排序
func SortReportByDecisionCommodities ( commodities [ ] DecisionReportData ) {
// 定义排序函数
less := func ( i , j int ) bool {
// 解析商品编号,提取分类编号和商品编号的数字部分
catNumI , subCatNumI , threeSubCatNumI , itemNumI := parseSerialNumber ( commodities [ i ] . CommoditySerialNumber )
catNumJ , subCatNumJ , threeSubCatNumJ , itemNumJ := parseSerialNumber ( commodities [ j ] . CommoditySerialNumber )
// 按照分类编号从小到大排序
if catNumI != catNumJ {
return catNumI < catNumJ
}
// 如果分类编号相同,按照具体分类下的商品编号递增排序
if subCatNumI != subCatNumJ {
return subCatNumI < subCatNumJ
}
if threeSubCatNumI != threeSubCatNumJ {
return threeSubCatNumI < threeSubCatNumJ
}
// 如果具体分类编号也相同,按照商品编号递增排序
return itemNumI < itemNumJ
}
// 调用排序函数进行排序
sort . SliceStable ( commodities , less )
}
2024-05-31 09:51:41 +00:00
// SortReportByOtherDataCommodities 对商品数组进行排序
func SortReportByOtherDataCommodities ( commodities [ ] ReportByOtherData ) {
// 定义排序函数
less := func ( i , j int ) bool {
// 解析商品编号,提取分类编号和商品编号的数字部分
catNumI , subCatNumI , threeSubCatNumI , itemNumI := parseSerialNumber ( commodities [ i ] . CommoditySerialNumber )
catNumJ , subCatNumJ , threeSubCatNumJ , itemNumJ := parseSerialNumber ( commodities [ j ] . CommoditySerialNumber )
// 按照分类编号从小到大排序
if catNumI != catNumJ {
return catNumI < catNumJ
}
// 如果分类编号相同,按照具体分类下的商品编号递增排序
if subCatNumI != subCatNumJ {
return subCatNumI < subCatNumJ
}
if threeSubCatNumI != threeSubCatNumJ {
return threeSubCatNumI < threeSubCatNumJ
}
// 如果具体分类编号也相同,按照商品编号递增排序
return itemNumI < itemNumJ
}
// 调用排序函数进行排序
sort . SliceStable ( commodities , less )
}
2024-05-10 01:54:37 +00:00
// parseSerialNumber 解析商品编号,提取分类编号、具体分类编号和商品编号的数字部分
func parseSerialNumber ( serialNumber string ) ( catNum , subCatNum , threeSubCatNum , itemNum int ) {
if len ( serialNumber ) < 3 {
return 0 , 0 , 0 , 0 // 如果商品编号长度不足3位, 则返回默认值
}
a := serialNumber [ : 3 ]
fmt . Println ( a )
catNum , _ = strconv . Atoi ( serialNumber [ : 3 ] )
switch len ( serialNumber ) {
case 7 : // 一级分类
subCatNum , _ = strconv . Atoi ( serialNumber [ 3 : 7 ] )
case 10 : // 二级分类
b := serialNumber [ 3 : 6 ]
fmt . Println ( b )
subCatNum , _ = strconv . Atoi ( serialNumber [ 3 : 6 ] )
threeSubCatNum = 0
c := serialNumber [ 6 : ]
fmt . Println ( c )
itemNum , _ = strconv . Atoi ( serialNumber [ 6 : ] )
case 13 : // 三级分类
subCatNum , _ = strconv . Atoi ( serialNumber [ 3 : 6 ] )
d := serialNumber [ 6 : 9 ]
fmt . Println ( d )
threeSubCatNum , _ = strconv . Atoi ( serialNumber [ 6 : 9 ] )
e := serialNumber [ 9 : ]
fmt . Println ( e )
itemNum , _ = strconv . Atoi ( serialNumber [ 9 : ] )
}
return catNum , subCatNum , threeSubCatNum , itemNum
2023-11-08 03:51:33 +00:00
}
type ErpCategoryListReq struct {
ErpCategoryId uint32 ` json:"erp_category_id" `
Pid uint32 ` json:"pid" `
Level uint32 ` json:"level" ` // 分类层级
State uint32 ` json:"state" ` // 1-未使用 2-使用 3-隐藏
PageNum int ` json:"page_num" `
PageSize int ` json:"page_size" `
IsExport uint32 ` json:"is_export" ` // 1-导出
}
type ErpCategoryListResp struct {
List [ ] ErpCategory ` json:"list" `
Total int ` json:"total" `
PageNum int ` json:"page_num" `
PageSize int ` json:"page_size" `
ExportUrl string ` json:"export_url" `
}
func ( m * ErpCategoryListReq ) List ( ) ( * ErpCategoryListResp , error ) {
resp := & ErpCategoryListResp {
PageNum : m . PageNum ,
PageSize : m . PageSize ,
}
//page := m.PageNum - 1
//if page < 0 {
// page = 0
//}
//if m.PageSize == 0 {
// m.PageSize = 10
//}
//qs := orm.Eloquent.Table("erp_category")
//if m.Level != 0 {
// qs = qs.Where("level=?", m.Level)
//}
////if m.ErpCategoryId != 0 {
//// qs = qs.IDEq(m.ErpCategoryId)
////}
//if m.Pid != 0 {
// qs = qs.Where("pid", m.Pid)
//}
//var count int64
2024-05-31 09:51:41 +00:00
//err := qs.Total(&count).Error
2023-11-08 03:51:33 +00:00
//if err != nil {
// logger.Error("count err:", err)
// return resp, err
//}
//resp.Total = int(count)/m.PageSize + 1
//var categories []ErpCategory
//err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&categories).Error
//if err != nil && err != RecordNotFound {
// logger.Error("erp commodity list err:", err)
// return resp, err
//}
var categories [ ] ErpCategory
qs := orm . Eloquent . Table ( "erp_category" ) . Where ( "level=?" , 1 )
if m . Pid != 0 {
qs = qs . Where ( "id=?" , m . Pid )
}
if m . State != 0 {
qs . Where ( "state=?" , m . State )
}
err := qs . Order ( "sort DESC" ) . Find ( & categories ) . Error
if err != nil {
//logger.Error("erp commodity list err:", err)
return resp , err
}
pids := make ( [ ] uint32 , 0 )
for i , _ := range categories {
pids = append ( pids , categories [ i ] . ID )
}
var subCat [ ] ErpCategory
subQs := orm . Eloquent . Table ( "erp_category" ) . Where ( "pid in (?)" , pids )
if m . State != 0 {
subQs . Where ( "state=?" , m . State )
}
err = subQs . Order ( "sort DESC" ) . Find ( & subCat ) . Error
if err != nil {
logger . Errorf ( "pCat err:%#v" , err )
return resp , err
}
pCatMap := make ( map [ uint32 ] [ ] ErpCategory , 0 )
for i , _ := range subCat {
pCatMap [ subCat [ i ] . Pid ] = append ( pCatMap [ subCat [ i ] . Pid ] , subCat [ i ] )
}
for i , _ := range categories {
v , ok := pCatMap [ categories [ i ] . ID ]
if ok {
categories [ i ] . SubCats = v
}
}
if m . IsExport == 1 {
listExport , err := ErpCategoryListExport ( categories )
if err != nil {
//logger.Error("list export err:", err)
}
resp . ExportUrl = listExport
}
resp . List = categories
return resp , nil
}
type CommodityNumberCount struct {
NumberMap map [ uint32 ] uint32 ` json:"number_map" `
}
func ( m * CommodityNumberCount ) GetErpCommodityNumberByCategoryId ( categoryId uint32 ) ( uint32 , error ) {
v , ok := m . NumberMap [ categoryId ]
if ok {
m . NumberMap [ categoryId ] = v + 1
return v + 1 , nil
}
var commodity ErpCommodity
err := orm . Eloquent . Raw ( fmt . Sprintf (
"SELECT number FROM erp_commodity WHERE erp_category_id=%d ORDER BY id DESC LIMIT 0,1;" , categoryId ) ) . Scan ( & commodity ) . Error
if err != nil {
//logger.Error("all categories map err:", err)
return 0 , err
}
m . NumberMap [ categoryId ] = commodity . Number + 1
return commodity . Number + 1 , nil
}
var EsStockLock sync . Mutex
type StockImporter struct {
CensusMap map [ uint32 ] map [ uint32 ] uint32
CommodityMap map [ uint32 ] * ErpCommodity
StoreMap map [ uint32 ] string
Inventories [ ] * ErpInventoryStock
}
type ErpStockFileExcel struct {
StockTimeString string ` json:"stock_time_string" `
IsIMEI string ` json:"is_imei" `
RetailPriceString string ` json:"retail_price_string" `
MinRetailPriceString string ` json:"min_retail_price_string" `
2023-11-23 12:38:11 +00:00
StaffCostPriceString string ` json:"staff_cost_price_string" ` // 员工成本价加价
WholesalePriceString string ` json:"wholesale_price_string" ` // 指导采购价
CountString string ` json:"count_string" ` // 数量
2023-11-08 03:51:33 +00:00
//StoreName string `json:"store_name"`
//ErpCommodityName string `json:"erp_commodity_name"`
//ErpCategoryName string `json:"erp_category_name"`
//SerialNumber string `json:"serial_number"`
//IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
//IMEI string `json:"imei"`
//ErpSupplierName string `json:"erp_supplier_name"`
ErpStockCommodity
}
func ( e * ErpStockFileExcel ) Processing ( ) {
e . Count = IntStringToUin32 ( e . CountString )
if e . IsIMEI == "是" {
e . IMEIType = 2
e . Count = 1
} else if e . IsIMEI == "否" {
e . IMEIType = 1
}
//parseTime, err := time.Parse(DateTimeFormat, e.StockTimeString)
//fmt.Println("StockTimeString:", e.StockTimeString)
//parseTime, err := time.Parse("01-02-06", e.StockTimeString)
format := "2006/01/02"
parseTime , err := time . Parse ( format , e . StockTimeString )
if err != nil {
//logger.Error("parse err:", err)
parseTime = time . Now ( )
}
e . StockTime = parseTime
2024-04-17 01:37:02 +00:00
e . RetailPrice = PercentFloatStringToFloat64 ( e . RetailPriceString )
e . MinRetailPrice = PercentFloatStringToFloat64 ( e . MinRetailPriceString )
e . StaffCostPrice = PercentFloatStringToFloat64 ( e . StaffCostPriceString )
e . WholesalePrice = PercentFloatStringToFloat64 ( e . WholesalePriceString )
2023-11-08 03:51:33 +00:00
}
2023-11-24 09:09:24 +00:00
// ImportStockData 库存导入
// 更新库存表和商品表
// 库存表:插入对应的库存数据
// 库存商品表:插入对应库存商品的数据;供应商只需判断是否在供应商列表即可 todo 库存商品表未插入库存id
func ( m * StockImporter ) ImportStockData ( colsMap [ ] map [ string ] interface { } ) error {
2023-11-23 12:38:11 +00:00
list , err := transStockData ( colsMap )
if err != nil {
return err
}
var erpStockCommodity [ ] ErpStockCommodity
2023-11-08 03:51:33 +00:00
storeNameMap := make ( map [ string ] uint32 , 0 )
erpCommodityMap := make ( map [ string ] * ErpCommodity , 0 )
erpSupplierNameMap := make ( map [ string ] uint32 , 0 )
storeNames := make ( [ ] string , 0 , len ( list ) )
erpCommodityNames := make ( [ ] string , 0 , len ( list ) )
erpSupplierNames := make ( [ ] string , 0 , len ( list ) )
for i , _ := range list {
_ , ok1 := storeNameMap [ list [ i ] . StoreName ]
if ! ok1 {
storeNames = append ( storeNames , list [ i ] . StoreName )
}
2023-11-23 12:38:11 +00:00
_ , ok2 := erpCommodityMap [ list [ i ] . Name ]
2023-11-08 03:51:33 +00:00
if ! ok2 {
2023-12-13 12:05:53 +00:00
if list [ i ] . Name == "" {
//如果商品名称为空,则需要补全
commodityName , err := getCommodityNameBySerialNum ( list [ i ] . SerialNum )
if err != nil {
logger . Errorf ( "getCommodityNameBySerialNum err:" , logger . Field ( "err" , err ) )
return err
}
list [ i ] . Name = commodityName
}
2023-11-23 12:38:11 +00:00
erpCommodityNames = append ( erpCommodityNames , list [ i ] . Name )
2023-12-13 12:05:53 +00:00
2023-11-08 03:51:33 +00:00
}
2023-11-23 12:38:11 +00:00
_ , ok3 := erpSupplierNameMap [ list [ i ] . SupplierName ]
2023-11-08 03:51:33 +00:00
if ! ok3 {
2023-11-23 12:38:11 +00:00
erpSupplierNames = append ( erpSupplierNames , list [ i ] . SupplierName )
2023-11-08 03:51:33 +00:00
}
storeNameMap [ list [ i ] . StoreName ] = uint32 ( 0 )
2023-11-23 12:38:11 +00:00
erpCommodityMap [ list [ i ] . Name ] = nil
erpSupplierNameMap [ list [ i ] . SupplierName ] = uint32 ( 0 )
2023-11-08 03:51:33 +00:00
}
var stores [ ] Store
2023-11-23 12:38:11 +00:00
err = orm . Eloquent . Table ( "store" ) . Where ( "name IN (?)" , storeNames ) . Find ( & stores ) . Error
2023-11-08 03:51:33 +00:00
if err != nil {
//logger.Error("stores err:", err)
return err
}
var erpCommodities [ ] ErpCommodity
err = orm . Eloquent . Table ( "erp_commodity" ) . Where ( "name IN (?)" , erpCommodityNames ) . Find ( & erpCommodities ) . Error
if err != nil {
//logger.Error("stores err:", err)
return err
}
var erpSuppliers [ ] ErpSupplier
err = orm . Eloquent . Table ( "erp_supplier" ) . Debug ( ) . Where ( "name IN (?)" , erpSupplierNames ) . Find ( & erpSuppliers ) . Error
2023-11-23 12:38:11 +00:00
if err != nil && ! errors . Is ( err , RecordNotFound ) {
2023-11-08 03:51:33 +00:00
//logger.Error("stores err:", err)
return err
}
for i , _ := range stores {
storeNameMap [ stores [ i ] . Name ] = stores [ i ] . ID
m . StoreMap [ stores [ i ] . ID ] = stores [ i ] . Name
}
for i , _ := range erpCommodities {
erpCommodityMap [ erpCommodities [ i ] . Name ] = & erpCommodities [ i ]
m . CommodityMap [ erpCommodities [ i ] . ID ] = & erpCommodities [ i ]
}
for i , _ := range erpSuppliers {
erpSupplierNameMap [ erpSuppliers [ i ] . Name ] = erpSuppliers [ i ] . ID
}
nowTime := time . Now ( )
for i , _ := range list {
v1 , ok1 := storeNameMap [ list [ i ] . StoreName ]
if ! ok1 {
2024-09-02 09:22:55 +00:00
logger . Errorf ( "erp store name err:%s" , list [ i ] . StoreName )
fmt . Printf ( "erp store name err:%s" , list [ i ] . StoreName )
return errors . New ( fmt . Sprintf ( "导入门店名称[%s]跟系统不符,请检查" , list [ i ] . StoreName ) )
2023-11-08 03:51:33 +00:00
}
2023-11-23 12:38:11 +00:00
v2 , ok2 := erpCommodityMap [ list [ i ] . Name ]
if ! ok2 || v2 == nil {
2024-09-02 09:22:55 +00:00
logger . Errorf ( "erp commodity name err:%s" , list [ i ] . Name )
fmt . Printf ( "erp commodity name err:%s" , list [ i ] . Name )
return errors . New ( fmt . Sprintf ( "导入商品名称[%s]跟系统不符,请检查" , list [ i ] . Name ) )
2023-11-08 03:51:33 +00:00
}
2023-11-23 12:38:11 +00:00
v3 , ok3 := erpSupplierNameMap [ list [ i ] . SupplierName ]
2023-11-08 03:51:33 +00:00
if ! ok3 {
2024-09-02 09:22:55 +00:00
logger . Errorf ( "erp supplier name err:%s" , list [ i ] . SupplierName )
fmt . Printf ( "erp supplier name err:%s" , list [ i ] . SupplierName )
return errors . New ( fmt . Sprintf ( "导入供应商名称[%s]跟系统不符,请检查" , list [ i ] . SupplierName ) )
2023-11-08 03:51:33 +00:00
}
2023-11-23 12:38:11 +00:00
// 注意:表格导入是员工成本价,数据库存储是员工成本价加价=员工成本价-指导采购价
2024-04-17 01:37:02 +00:00
nStaffCostPrice , err := strconv . ParseFloat ( list [ i ] . StaffCostPrice , 64 )
2023-11-23 12:38:11 +00:00
if err != nil {
return fmt . Errorf ( "员工成本价转换有误:[%v]" , err )
}
2024-04-17 01:37:02 +00:00
nWholesalePrice , err := strconv . ParseFloat ( list [ i ] . WholesalePrice , 64 ) // 指导采购价
2023-11-23 12:38:11 +00:00
if err != nil {
return fmt . Errorf ( "指导采购价转换有误:[%v]" , err )
}
if nStaffCostPrice < nWholesalePrice {
2024-04-22 01:51:41 +00:00
return fmt . Errorf ( "导入价格有误,员工成本价低于采购价" )
2023-11-23 12:38:11 +00:00
}
nCount , err := strconv . ParseUint ( list [ i ] . Count , 10 , 32 )
if err != nil {
return fmt . Errorf ( "数量转换有误:[%v]" , err )
}
2023-11-24 09:09:24 +00:00
for j := 0 ; j < int ( nCount ) ; j ++ { // 商品库存表都是单笔数据,如果非串码商品有多个,需要插入多条数据
stockCommodity := ErpStockCommodity {
StoreId : v1 ,
StoreName : list [ i ] . StoreName ,
ErpCommodityId : v2 . ID ,
ErpCommodityName : v2 . Name ,
2023-12-11 08:21:21 +00:00
CommoditySerialNumber : v2 . SerialNumber ,
2023-11-24 09:09:24 +00:00
ErpCategoryId : v2 . ErpCategoryId ,
ErpCategoryName : v2 . ErpCategoryName ,
ErpSupplierId : v3 ,
ErpSupplierName : list [ i ] . SupplierName ,
2024-04-17 01:37:02 +00:00
StaffCostPrice : tools . RoundToTwoDecimalPlaces ( nStaffCostPrice - nWholesalePrice ) ,
WholesalePrice : tools . RoundToTwoDecimalPlaces ( nWholesalePrice ) ,
State : InStock ,
StorageType : SystemInventory ,
2023-11-24 09:09:24 +00:00
FirstStockTime : nowTime ,
StockTime : nowTime ,
Count : 1 ,
2024-01-06 08:48:35 +00:00
ErpBarcode : v2 . ErpBarcode , // 240106新增商品条码
2023-11-24 09:09:24 +00:00
IMEIType : v2 . IMEIType ,
2023-12-13 12:05:53 +00:00
IMEI : "" ,
2023-11-24 09:09:24 +00:00
Remark : "" ,
2023-12-22 09:26:34 +00:00
MemberDiscount : v2 . MemberDiscount ,
2023-12-27 11:23:03 +00:00
MinRetailPrice : v2 . MinRetailPrice ,
RetailPrice : v2 . RetailPrice ,
} // todo 首次入库订单编号、订单编号还未赋值
2023-12-11 08:21:21 +00:00
if list [ i ] . StockTime != "" { //导入时间不为空
2023-12-13 12:05:53 +00:00
local , _ := time . LoadLocation ( "Local" )
parsedTime , _ := time . ParseInLocation ( "2006/1/2" , list [ i ] . StockTime , local )
//parsedTime, _ := time.Parse("2006/1/2", list[i].StockTime)
2023-12-11 08:21:21 +00:00
stockCommodity . FirstStockTime = parsedTime
2023-12-13 12:05:53 +00:00
stockCommodity . StockTime = parsedTime
2023-12-11 08:21:21 +00:00
}
2023-12-19 10:21:44 +00:00
//if list[i].SysGenerate != "" && v2.IMEIType == 3 { //导入串码不为空, 则默认为3手动添加
// stockCommodity.IMEIType = 3
// stockCommodity.IMEI = list[i].SysGenerate
//} else if v2.IMEIType == 2 { // 如果该商品串码类型是: 2-串码(系统生成),则系统自动生成
// stockCommodity.IMEIType = 2
// serialCode, err := generateSerialCode(v2.ErpCategoryId)
// if err != nil {
// return err
// }
// stockCommodity.IMEI = serialCode
//}
if list [ i ] . SysGenerate != "" && v2 . IMEIType != 1 { // 商品为串码商品,且导入串码不为空
stockCommodity . IMEIType = v2 . IMEIType
2023-11-24 09:09:24 +00:00
stockCommodity . IMEI = list [ i ] . SysGenerate
}
2023-12-13 12:05:53 +00:00
2023-11-24 09:09:24 +00:00
erpStockCommodity = append ( erpStockCommodity , stockCommodity )
2023-11-08 03:51:33 +00:00
2023-11-24 09:09:24 +00:00
_ , ok4 := m . CensusMap [ stockCommodity . StoreId ]
if ok4 {
m . CensusMap [ stockCommodity . StoreId ] [ stockCommodity . ErpCommodityId ] += stockCommodity . Count
} else {
m . CensusMap [ stockCommodity . StoreId ] = map [ uint32 ] uint32 { stockCommodity . ErpCommodityId : stockCommodity . Count }
}
2023-11-23 12:38:11 +00:00
}
}
if err = m . processErpStocks ( erpStockCommodity ) ; err != nil {
return err
}
return nil
}
2023-12-13 12:05:53 +00:00
// 获取商品名称
func getCommodityNameBySerialNum ( serialNumber string ) ( string , error ) {
var commodity ErpCommodity
err := orm . Eloquent . Table ( "erp_commodity" ) . Where ( "serial_number=?" , serialNumber ) . Find ( & commodity ) . Error
if err != nil {
return "" , err
}
return commodity . Name , nil
}
2024-09-22 03:15:44 +00:00
//// GenerateSerialCode 生成商品串码
//func GenerateSerialCode(categoryID uint32) (string, error) {
// max := 1
// for {
// if max > 5 {
// logger.Error("generate SerialCode err")
// return "", errors.New("generate SerialCode err")
// }
//
// // 生成年月日6位数
// dateStr := time.Now().Format("060102")
//
// // 生成四位随机数
// rand.Seed(time.Now().UnixNano())
// randomNumber := rand.Intn(10000)
// randomStr := fmt.Sprintf("%04d", randomNumber)
//
// // 获取商品分类编号前3位
// categoryStr, err := getCategoryCode(categoryID)
// if err != nil {
// logger.Errorf("getCategoryCode err:", logger.Field("err", err))
// return "", err
// }
//
// // 拼接串码
// serialCode := categoryStr + dateStr + randomStr
//
// // 检查生成的串码是否已存在 todo 是否需要判断状态,采购退货的可以重复?
// exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock_commodity WHERE FIND_IN_SET('%s', imei) > 0 ", serialCode))
// if err != nil {
// logger.Error("exist sn err")
// }
// if !exist {
// return serialCode, nil
// }
// }
//
//}
2024-02-20 09:59:43 +00:00
// GenerateSerialCode 生成商品串码
2024-09-22 03:15:44 +00:00
func GenerateSerialCode ( categoryID uint32 , generatedIMEIs map [ string ] struct { } ) ( string , error ) {
2024-02-20 09:59:43 +00:00
max := 1
for {
if max > 5 {
logger . Error ( "generate SerialCode err" )
return "" , errors . New ( "generate SerialCode err" )
}
// 生成年月日6位数
dateStr := time . Now ( ) . Format ( "060102" )
2023-12-13 12:05:53 +00:00
2024-02-20 09:59:43 +00:00
// 生成四位随机数
rand . Seed ( time . Now ( ) . UnixNano ( ) )
randomNumber := rand . Intn ( 10000 )
randomStr := fmt . Sprintf ( "%04d" , randomNumber )
// 获取商品分类编号前3位
categoryStr , err := getCategoryCode ( categoryID )
if err != nil {
logger . Errorf ( "getCategoryCode err:" , logger . Field ( "err" , err ) )
return "" , err
}
// 拼接串码
serialCode := categoryStr + dateStr + randomStr
2024-09-22 03:15:44 +00:00
// 检查生成的串码是否已存在
2024-07-12 07:54:31 +00:00
exist , err := QueryRecordExist ( fmt . Sprintf ( "SELECT * FROM erp_stock_commodity WHERE FIND_IN_SET('%s', imei) > 0 " , serialCode ) )
2024-02-20 09:59:43 +00:00
if err != nil {
logger . Error ( "exist sn err" )
}
2024-09-22 03:15:44 +00:00
// 如果已存在数据库中或在传入的 generatedIMEIs 集合中,则继续生成
2024-02-20 09:59:43 +00:00
if ! exist {
2024-09-22 03:15:44 +00:00
// 检查是否已在 generatedIMEIs 集合中
if _ , found := generatedIMEIs [ serialCode ] ; ! found {
// 将新生成的串码加入集合,以便后续校验
return serialCode , nil
}
2024-02-20 09:59:43 +00:00
}
2023-12-13 12:05:53 +00:00
2024-09-22 03:15:44 +00:00
max ++
}
2023-12-13 12:05:53 +00:00
}
// getCategoryCode 根据商品分类ID查询分类编号前3位
func getCategoryCode ( categoryID uint32 ) ( string , error ) {
// 这里模拟查询数据库,实际中你需要连接数据库进行查询
// 假设这里的数据是从数据库中查询得到的
categoryInfo , err := GetCategoryById ( categoryID )
if err != nil {
logger . Errorf ( "GetCategoryById err:" , logger . Field ( "err" , err ) )
return "" , err
}
// 取前3位字符串
return categoryInfo . Number [ : 3 ] , nil
}
2023-11-23 12:38:11 +00:00
func ( m * StockImporter ) processErpStocks ( erpStocks [ ] ErpStockCommodity ) error {
begin := orm . Eloquent . Begin ( )
total := len ( erpStocks )
size := 200
page := ( total + size - 1 ) / size
errGroup := errgroup . Group { }
for i := 0 ; i < page ; i ++ {
start := i * size
end := ( i + 1 ) * size
if end > total {
end = total
2023-11-08 03:51:33 +00:00
}
2023-11-23 12:38:11 +00:00
stockList := erpStocks [ start : end ]
errGroup . Go ( func ( ) error {
2023-12-11 08:21:21 +00:00
return createStockList ( begin , stockList ) //插入库存商品详情
2023-11-23 12:38:11 +00:00
} )
}
2024-09-18 09:11:39 +00:00
err := errGroup . Wait ( )
2023-11-23 12:38:11 +00:00
if err != nil {
begin . Rollback ( )
return err
}
2024-09-18 09:11:39 +00:00
err = m . ErpStockCountUpdate ( begin ) //更新or插入库存表
2023-11-23 12:38:11 +00:00
if err != nil {
begin . Rollback ( )
return err
}
err = begin . Commit ( ) . Error
if err != nil {
begin . Rollback ( )
return err
}
return nil
}
func createStockList ( begin * gorm . DB , stockList [ ] ErpStockCommodity ) error {
2023-12-13 12:05:53 +00:00
err := begin . Debug ( ) . Create ( & stockList ) . Error
2023-11-23 12:38:11 +00:00
if err != nil {
begin . Rollback ( )
return err
2023-11-08 03:51:33 +00:00
}
return nil
}
2024-09-18 09:11:39 +00:00
// 合并导入数据的辅助函数
func mergeCensusMap ( censusMap map [ uint32 ] map [ uint32 ] uint32 ) map [ uint32 ] map [ uint32 ] uint32 {
mergedMap := make ( map [ uint32 ] map [ uint32 ] uint32 )
for storeId , commodities := range censusMap {
if mergedMap [ storeId ] == nil {
mergedMap [ storeId ] = make ( map [ uint32 ] uint32 )
}
for commodityId , count := range commodities {
mergedMap [ storeId ] [ commodityId ] += count
}
}
return mergedMap
}
2023-11-08 03:51:33 +00:00
func ( m * StockImporter ) ErpStockCountUpdate ( gdb * gorm . DB ) error {
2024-09-18 09:11:39 +00:00
// 合并导入数据,避免同一商品多次重复处理
mergedCensusMap := mergeCensusMap ( m . CensusMap )
//for k1, v1 := range m.CensusMap {
for k1 , v1 := range mergedCensusMap {
2023-11-08 03:51:33 +00:00
for k2 , v2 := range v1 {
exist , err := QueryRecordExist ( fmt . Sprintf ( "SELECT * FROM erp_stock WHERE store_id=%d AND erp_commodity_id=%d" , k1 , k2 ) )
if err != nil {
//logger.Error("exist err:", err)
return err
}
v , ok := m . CommodityMap [ k2 ]
fmt . Println ( "CommodityMap" , m . CommodityMap )
fmt . Println ( "ok" , ok )
fmt . Println ( "v" , v )
if exist {
err = gdb . Exec ( fmt . Sprintf (
"UPDATE erp_stock SET count=count+%d WHERE store_id=%d AND erp_commodity_id=%d;" , v2 , k1 , k2 ) ) . Error
if err != nil {
//logger.Error("update stock err:", err)
return err
}
} else {
if ok && v != nil {
stock := & ErpStock {
StoreId : k1 ,
StoreName : m . StoreMap [ k1 ] ,
ErpCommodityId : v . ID ,
ErpCommodityName : v . Name ,
ErpCategoryId : v . ErpCategoryId ,
ErpCategoryName : v . ErpCategoryName ,
CommoditySerialNumber : v . SerialNumber ,
IMEIType : v . IMEIType ,
RetailPrice : v . RetailPrice ,
MinRetailPrice : v . MinRetailPrice ,
Count : v2 ,
DispatchCount : 0 ,
}
err = gdb . Create ( stock ) . Error
if err != nil {
//logger.Error("create stock err:", err)
return err
}
}
}
if ok && v != nil {
inventoryStock := & ErpInventoryStock {
StoreId : k1 ,
StoreName : m . StoreMap [ k1 ] ,
ErpCommodityId : v . ID ,
ErpCommodityName : v . Name ,
ErpCategoryId : v . ErpCategoryId ,
ErpCategoryName : v . ErpCategoryName ,
CommoditySerialNumber : v . SerialNumber ,
IMEIType : v . IMEIType ,
RetailPrice : v . RetailPrice ,
MinRetailPrice : v . MinRetailPrice ,
Count : v2 ,
}
fmt . Println ( "inventoryStock" , inventoryStock . Count )
m . Inventories = append ( m . Inventories , inventoryStock )
}
2023-12-11 08:21:21 +00:00
}
}
2023-11-08 03:51:33 +00:00
2023-12-11 08:21:21 +00:00
return nil
}
// 查询库存详情时同步库存id
func updateCommodityStock ( id uint32 ) error {
var stock ErpStock
err := orm . Eloquent . Table ( "erp_stock" ) . Raw ( "SELECT * FROM erp_stock WHERE id = ?" , id ) . Scan ( & stock ) . Error
if err != nil {
return err
}
if stock . ID != 0 {
err = orm . Eloquent . Debug ( ) . Exec ( fmt . Sprintf (
"UPDATE erp_stock_commodity SET erp_stock_id = %d WHERE erp_commodity_name = '%s' AND erp_stock_id = 0;" ,
stock . ID , stock . ErpCommodityName ) ) . Error
if err != nil {
return err
2023-11-08 03:51:33 +00:00
}
}
return nil
}
2023-11-23 12:38:11 +00:00
func ( m * StockImporter ) ErpInventoryStockCreate ( gdb * gorm . DB , list [ ] ErpStockCommodity ) error {
2023-11-08 03:51:33 +00:00
defer func ( ) {
if err := recover ( ) ; err != nil {
//logger.Error("err:", err)
return
}
} ( )
inventoryStockIdMap := make ( map [ string ] uint32 , 0 )
for _ , inventory := range m . Inventories {
2023-11-17 10:07:01 +00:00
//err := gdb.Create(inventorymanage).Error
2023-11-08 03:51:33 +00:00
err := orm . Eloquent . Create ( inventory ) . Error
if err != nil {
2023-11-17 10:07:01 +00:00
//logger.Error("create erp inventorymanage stock err:", err)
2023-11-08 03:51:33 +00:00
return err
}
inventoryStockIdMap [ fmt . Sprintf ( "%d_%d" , inventory . StoreId , inventory . ErpCommodityId ) ] = inventory . ID
}
begin := orm . Eloquent . Begin ( )
total := len ( list )
size := 500
page := total / size
if total % size != 0 {
page += 1
}
errGroup := errgroup . Group { }
for i := 0 ; i < page ; i ++ {
if i == page - 1 {
stockList := ErpStockCommodityToInventory ( inventoryStockIdMap , list [ i * size : ] )
err := begin . Create ( & stockList ) . Error
if err != nil {
begin . Rollback ( )
//logger.Error("create commodity err:", err)
return err
}
} else {
errGroup . Go ( func ( ) error {
//stockList := list[i*size : (i+1)*size]
stockList := ErpStockCommodityToInventory ( inventoryStockIdMap , list [ i * size : ( i + 1 ) * size ] )
err := begin . Create ( & stockList ) . Error
if err != nil {
begin . Rollback ( )
//logger.Error("create commodity err:", err)
return err
}
return nil
} )
}
}
err := errGroup . Wait ( )
if err != nil {
//logger.Error("wait err:", err)
return err
}
err = begin . Commit ( ) . Error
if err != nil {
//logger.Error("commit err:", err)
return err
}
return nil
}
2023-11-23 12:38:11 +00:00
func ErpStockCommodityToInventory ( inventoryStockIdMap map [ string ] uint32 , list [ ] ErpStockCommodity ) [ ] * ErpInventoryStockCommodity {
2023-11-08 03:51:33 +00:00
inventoryList := make ( [ ] * ErpInventoryStockCommodity , 0 , len ( list ) )
for i , _ := range list {
v , ok := inventoryStockIdMap [ fmt . Sprintf ( "%d_%d" , list [ i ] . StoreId , list [ i ] . ErpCommodityId ) ]
if ok {
inventoryCommodity := & ErpInventoryStockCommodity {
ErpInventoryStockId : v ,
ErpCommodityId : list [ i ] . ErpCommodityId ,
ErpCommodityName : list [ i ] . ErpCommodityName ,
CommoditySerialNumber : list [ i ] . CommoditySerialNumber ,
IMEIType : list [ i ] . IMEIType ,
IMEI : list [ i ] . IMEI ,
ErpSupplierId : list [ i ] . ErpSupplierId ,
ErpSupplierName : list [ i ] . ErpSupplierName ,
StockTime : list [ i ] . StockTime ,
RetailPrice : list [ i ] . RetailPrice ,
MinRetailPrice : list [ i ] . MinRetailPrice ,
StaffCostPrice : list [ i ] . StaffCostPrice ,
WholesalePrice : list [ i ] . WholesalePrice ,
Count : list [ i ] . Count ,
}
//err := gdb.Create(inventoryCommodity).Error
inventoryList = append ( inventoryList , inventoryCommodity )
//err := orm.Eloquent.Create(inventoryCommodity).Error
//if err != nil {
2023-11-17 10:07:01 +00:00
// logger.Error("create erp inventorymanage stock commodity err:", err)
2023-11-08 03:51:33 +00:00
// return inventoryList
//}
}
}
return inventoryList
}
2023-11-23 12:38:11 +00:00
// ErpCommodityListExport 导出商品列表
2023-11-08 03:51:33 +00:00
func ErpCommodityListExport ( list [ ] ErpCommodity ) ( string , error ) {
file := excelize . NewFile ( )
2024-07-23 10:40:52 +00:00
fSheet := "Sheet1"
2023-11-08 03:51:33 +00:00
2024-09-02 09:22:55 +00:00
url := config . ExportConfig . Url
2024-07-23 10:40:52 +00:00
fileName := time . Now ( ) . Format ( TimeFormat ) + "商品资料" + ".xlsx"
2023-11-08 03:51:33 +00:00
2024-07-23 10:40:52 +00:00
title := [ ] interface { } { "商品编号" , "商品名称" , "商品分类" , "商品条码" , "是否串码" , "系统生成串码" , "主供应商" , "指导零售价" ,
"最低零售价" , "员工成本价加价" , "指导采购价" , "销售毛利提成" , "员工毛利提成" , "会员优惠" , "产地" , "备注" }
for i , _ := range title {
cell , _ := excelize . CoordinatesToCellName ( 1 + i , 1 )
err := file . SetCellValue ( fSheet , cell , title [ i ] )
if err != nil {
logger . Errorf ( "file set value err:" , err )
}
2023-11-08 03:51:33 +00:00
}
2024-07-23 10:40:52 +00:00
2023-11-08 03:51:33 +00:00
var row [ ] interface { }
2024-07-23 10:40:52 +00:00
nExcelStartRow := 0
2023-11-08 03:51:33 +00:00
for rowId := 0 ; rowId < len ( list ) ; rowId ++ {
isIMEI := "否"
2024-07-23 10:40:52 +00:00
systemIMEI := "否"
if list [ rowId ] . IMEIType != 1 { // 非串码
2023-11-08 03:51:33 +00:00
isIMEI = "是"
2024-07-23 10:40:52 +00:00
if list [ rowId ] . IMEIType == 2 { //2-串码(系统生成)
systemIMEI = "是"
}
2023-11-08 03:51:33 +00:00
}
2024-07-23 10:40:52 +00:00
row = [ ] interface { } {
list [ rowId ] . SerialNumber ,
list [ rowId ] . Name ,
list [ rowId ] . ErpCategoryName ,
list [ rowId ] . ErpBarcode ,
isIMEI ,
systemIMEI ,
list [ rowId ] . ErpSupplierName ,
list [ rowId ] . RetailPrice ,
list [ rowId ] . MinRetailPrice ,
list [ rowId ] . StaffCostPrice ,
list [ rowId ] . WholesalePrice ,
list [ rowId ] . Brokerage1 ,
list [ rowId ] . Brokerage2 ,
list [ rowId ] . MemberDiscount ,
list [ rowId ] . Origin ,
list [ rowId ] . Remark }
for j , _ := range row {
cell , _ := excelize . CoordinatesToCellName ( 1 + j , nExcelStartRow + 2 )
err := file . SetCellValue ( fSheet , cell , row [ j ] )
if err != nil {
logger . Error ( "file set value err:" , logger . Field ( "err" , err ) )
}
2023-11-08 03:51:33 +00:00
}
2024-07-23 10:40:52 +00:00
nExcelStartRow ++
2023-11-08 03:51:33 +00:00
}
2024-07-23 10:40:52 +00:00
// 设置所有单元格的样式: 居中、加边框
style , _ := file . NewStyle ( ` { "alignment" : { "horizontal" : "center" , "vertical" : "center" } ,
"border" : [ { "type" : "left" , "color" : "000000" , "style" : 1 } ,
{ "type" : "top" , "color" : "000000" , "style" : 1 } ,
{ "type" : "right" , "color" : "000000" , "style" : 1 } ,
{ "type" : "bottom" , "color" : "000000" , "style" : 1 } ] } ` )
//设置单元格高度
file . SetRowHeight ( "Sheet1" , 1 , 20 )
// 设置单元格大小
file . SetColWidth ( "Sheet1" , "A" , "A" , 15 )
file . SetColWidth ( "Sheet1" , "B" , "B" , 30 )
file . SetColWidth ( "Sheet1" , "D" , "D" , 18 )
endRow := fmt . Sprintf ( "P" + "%d" , nExcelStartRow + 2 )
// 应用样式到整个表格
_ = file . SetCellStyle ( "Sheet1" , "A1" , endRow , style )
fmt . Println ( "save fileName:" , config . ExportConfig . Path + fileName )
if err := file . SaveAs ( config . ExportConfig . Path + fileName ) ; err != nil {
2023-11-08 03:51:33 +00:00
fmt . Println ( err )
}
2024-07-23 10:40:52 +00:00
2023-11-08 03:51:33 +00:00
return url + fileName , nil
}
2024-07-12 07:54:31 +00:00
// 判断是否有入库采购价、入库员工成本价的权限
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
}
2024-11-19 10:38:17 +00:00
// InventoryDetailListExport 导出库存详情
2024-07-22 02:39:22 +00:00
func InventoryDetailListExport ( list [ ] ErpStockCommodity , c * gin . Context ) ( string , error ) {
2023-11-23 12:38:11 +00:00
file := excelize . NewFile ( )
streamWriter , err := file . NewStreamWriter ( "Sheet1" )
if err != nil {
fmt . Println ( err )
2024-07-12 07:54:31 +00:00
return "" , err
2023-11-23 12:38:11 +00:00
}
2024-09-02 09:22:55 +00:00
url := config . ExportConfig . Url
2024-07-22 02:39:22 +00:00
fileName := time . Now ( ) . Format ( TimeFormat ) + "库存详情" + ".xlsx"
2023-11-23 12:38:11 +00:00
fmt . Println ( "url fileName:" , url + fileName )
2024-07-22 02:39:22 +00:00
// 判断是否有入库采购价、入库员工成本价的权限
exportPurchasePrice , _ := checkRoleMenu ( c , PurchasePrice )
exportStaffCostPrice , _ := checkRoleMenu ( c , EmployeeCostPrice )
fmt . Println ( "exportPurchasePrice is:" , exportPurchasePrice )
fmt . Println ( "exportStaffCostPrice is:" , exportStaffCostPrice )
logger . Info ( "exportPurchasePrice is:" , logger . Field ( "exportPurchasePrice" , exportPurchasePrice ) )
logger . Info ( "exportStaffCostPrice is:" , logger . Field ( "exportStaffCostPrice" , exportStaffCostPrice ) )
2024-07-12 07:54:31 +00:00
// 设置标题行
2024-09-02 09:22:55 +00:00
title := [ ] interface { } { "商品编号" , "商品名称" , "商品分类" , "是否串码" , "商品串码" , "所属门店" , "供应商" , "库存数量" ,
"首次入库时间" , "首次入库方式" , "首次入库订单编号" , "最近入库时间" }
2024-07-12 07:54:31 +00:00
if exportPurchasePrice {
title = append ( title , "入库采购价" )
}
if exportStaffCostPrice {
title = append ( title , "入库员工成本价" )
}
title = append ( title , "最近库龄" , "总库龄" , "当前状态" , "备注" )
2023-11-23 12:38:11 +00:00
cell , _ := excelize . CoordinatesToCellName ( 1 , 1 )
if err = streamWriter . SetRow ( cell , title ) ; err != nil {
fmt . Println ( err )
2024-07-12 07:54:31 +00:00
return "" , err
2023-11-23 12:38:11 +00:00
}
2024-07-12 07:54:31 +00:00
2023-11-23 12:38:11 +00:00
for rowId := 0 ; rowId < len ( list ) ; rowId ++ {
isIMEIType := "是"
if list [ rowId ] . IMEIType == 1 {
isIMEIType = "否"
}
storageType := "系统入库"
if list [ rowId ] . StorageType == 2 {
storageType = "采购入库"
}
2024-07-01 01:44:35 +00:00
state := "在库"
2023-11-23 12:38:11 +00:00
switch list [ rowId ] . State {
case 1 :
2024-07-01 01:44:35 +00:00
state = "在库"
2023-11-23 12:38:11 +00:00
case 2 :
state = "已售"
case 3 :
state = "采购退货"
case 4 :
2024-07-01 01:44:35 +00:00
state = "调出中"
case 5 :
state = "系统出库"
case 6 :
state = "盘点出库"
2023-11-23 12:38:11 +00:00
}
2024-07-12 07:54:31 +00:00
row := [ ] interface { } {
2023-11-23 12:38:11 +00:00
list [ rowId ] . CommoditySerialNumber ,
list [ rowId ] . ErpCommodityName ,
list [ rowId ] . ErpCategoryName ,
isIMEIType ,
list [ rowId ] . IMEI ,
list [ rowId ] . StoreName ,
list [ rowId ] . ErpSupplierName ,
2024-09-02 09:22:55 +00:00
1 ,
2023-11-23 12:38:11 +00:00
list [ rowId ] . FirstStockTime ,
storageType ,
2024-03-27 10:01:38 +00:00
list [ rowId ] . OriginalSn ,
2023-11-23 12:38:11 +00:00
list [ rowId ] . StockTime ,
2024-07-12 07:54:31 +00:00
}
// 控制是否导出入库采购价和入库员工成本价
if exportPurchasePrice {
row = append ( row , list [ rowId ] . WholesalePrice )
}
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 )
2024-07-19 02:06:02 +00:00
cell , _ = excelize . CoordinatesToCellName ( 1 , rowId + 2 )
if err = streamWriter . SetRow ( cell , row ) ; err != nil {
2023-11-23 12:38:11 +00:00
fmt . Println ( err )
2024-07-12 07:54:31 +00:00
return "" , err
2023-11-23 12:38:11 +00:00
}
}
2024-07-12 07:54:31 +00:00
2024-07-19 02:06:02 +00:00
if err = streamWriter . Flush ( ) ; err != nil {
2023-11-23 12:38:11 +00:00
fmt . Println ( err )
2024-07-12 07:54:31 +00:00
return "" , err
2023-11-23 12:38:11 +00:00
}
fmt . Println ( "save fileName:" , config . ExportConfig . Path + fileName )
2024-07-19 02:06:02 +00:00
if err = file . SaveAs ( config . ExportConfig . Path + fileName ) ; err != nil {
2023-11-23 12:38:11 +00:00
fmt . Println ( err )
2024-07-12 07:54:31 +00:00
return "" , err
2023-11-23 12:38:11 +00:00
}
return url + fileName , nil
}
// ErpCategoryListExport 导出商品分类
2023-11-08 03:51:33 +00:00
func ErpCategoryListExport ( list [ ] ErpCategory ) ( string , error ) {
file := excelize . NewFile ( )
streamWriter , err := file . NewStreamWriter ( "Sheet1" )
if err != nil {
fmt . Println ( err )
}
2024-09-02 09:22:55 +00:00
url := config . ExportConfig . Url
2023-11-08 03:51:33 +00:00
fileName := time . Now ( ) . Format ( TimeFormat ) + "分类列表数据" + ".xlsx"
//title := []interface{}{"门店", "用户ID", "订单编号", "下单时间", "卡带", "说明", "回收价", "闲麦价", "审核时间", "审核人", "操作", "复核时间", "复核状态"}
title := [ ] interface { } { "一级分类" , "二级分类" }
cell , _ := excelize . CoordinatesToCellName ( 1 , 1 )
if err = streamWriter . SetRow ( cell , title ) ; err != nil {
fmt . Println ( err )
}
rowIdx := 2
var row [ ] interface { }
for rowId := 0 ; rowId < len ( list ) ; rowId ++ {
cats := list [ rowId ] . SubCats
for i := 0 ; i < len ( cats ) ; i ++ {
rowName := list [ rowId ] . Name
if i != 0 {
rowName = ""
}
row = [ ] interface { } { rowName , cats [ i ] . Name }
cell , _ := excelize . CoordinatesToCellName ( 1 , rowIdx )
if err := streamWriter . SetRow ( cell , row ) ; err != nil {
fmt . Println ( err )
}
rowIdx ++
}
}
if err := streamWriter . Flush ( ) ; err != nil {
fmt . Println ( err )
}
if err := file . SaveAs ( "/www/server/images/export/" + fileName ) ; err != nil {
//if err := file.SaveAs("./" + fileName); err != nil {
fmt . Println ( err )
}
return url + fileName , nil
}
type ErpStockListReq struct {
2023-11-16 10:09:11 +00:00
SerialNumber string ` json:"serial_number" ` // 商品编号
CommodityName string ` json:"commodity_name" ` // 商品名称
ErpCategoryId uint32 ` json:"erp_category_id" ` // 商品分类
2024-07-12 07:54:31 +00:00
IsIMEI uint32 ` json:"is_imei" ` // 是否串码: 0-查全部 1-查串码类 2-查非串码
2023-11-16 10:09:11 +00:00
StockType uint32 ` json:"stock_type" ` // 库存情况:1-全部 2-有库存 3-无库存
StoreId uint32 ` json:"store_id" ` // 门店编号
2023-11-28 09:33:38 +00:00
PageIndex int ` json:"pageIndex" ` // 页码
PageSize int ` json:"pageSize" ` // 页面条数
2024-11-19 10:38:17 +00:00
IsExport uint32 ` json:"is_export" ` // 1-导出
2023-11-08 03:51:33 +00:00
}
2023-11-23 12:38:11 +00:00
2023-11-08 03:51:33 +00:00
type ErpStockListResp struct {
List [ ] ErpStock ` json:"list" `
2024-02-02 06:33:45 +00:00
Total int ` json:"total" ` // 数据总条数
2023-11-28 09:33:38 +00:00
PageIndex int ` json:"pageIndex" ` // 页码
PageSize int ` json:"pageSize" ` // 每页展示条数
2023-11-08 03:51:33 +00:00
ExportUrl string ` json:"export_url" `
}
func ( m * ErpStockListReq ) List ( ) ( * ErpStockListResp , error ) {
resp := & ErpStockListResp {
2023-11-28 09:33:38 +00:00
PageIndex : m . PageIndex ,
PageSize : m . PageSize ,
2023-11-08 03:51:33 +00:00
}
2023-11-28 09:33:38 +00:00
page := m . PageIndex - 1
2023-11-08 03:51:33 +00:00
if page < 0 {
page = 0
}
if m . PageSize == 0 {
m . PageSize = 10
}
2023-12-11 08:21:21 +00:00
qs := orm . Eloquent . Table ( "erp_stock" ) .
Joins ( "JOIN erp_category c ON erp_stock.erp_category_id = c.id" )
2023-11-08 03:51:33 +00:00
if m . SerialNumber != "" {
qs = qs . Where ( "commodity_serial_number=?" , m . SerialNumber )
}
if m . CommodityName != "" {
2023-11-17 10:07:01 +00:00
qs = qs . Where ( "erp_commodity_name LIKE ?" , "%" + m . CommodityName + "%" )
2023-11-08 03:51:33 +00:00
}
if m . ErpCategoryId != 0 {
qs = qs . Where ( "erp_category_id=?" , m . ErpCategoryId )
}
2023-11-16 10:09:11 +00:00
if m . StoreId != 0 {
qs = qs . Where ( "store_id=?" , m . StoreId )
2023-11-08 03:51:33 +00:00
}
2023-11-16 10:09:11 +00:00
switch m . StockType {
case 2 :
qs = qs . Where ( "count > 0" )
case 3 :
qs = qs . Where ( "count = 0" )
}
2023-12-11 08:21:21 +00:00
// SQL Order By Clause
qs = qs . Order ( "CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) ELSE " +
"CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END" ) .
Order ( "CAST(c.pid AS SIGNED)" ) .
Order ( "CAST(SUBSTRING(erp_stock.commodity_serial_number, -4) AS SIGNED)" )
2023-11-08 03:51:33 +00:00
var count int64
2023-11-16 10:09:11 +00:00
if err := qs . Count ( & count ) . Error ; err != nil {
2023-11-08 03:51:33 +00:00
//logger.Error("count err:", err)
return resp , err
}
2023-11-16 10:09:11 +00:00
var commodities [ ] ErpStock
2023-12-11 08:21:21 +00:00
err := qs . Offset ( page * m . PageSize ) . Limit ( m . PageSize ) . Find ( & commodities ) . Error
2023-11-16 10:09:11 +00:00
if err != nil && ! errors . Is ( err , RecordNotFound ) {
//logger.Error("erp commodity list err:", err)
return resp , err
2023-11-08 03:51:33 +00:00
}
2023-11-16 10:09:11 +00:00
resp . List = commodities
2023-11-08 03:51:33 +00:00
2023-11-28 09:33:38 +00:00
//跟之前保持一致
resp . Total = int ( count )
resp . PageIndex = page + 1
resp . PageSize = m . PageSize
2023-11-08 03:51:33 +00:00
return resp , nil
}
2023-12-11 08:21:21 +00:00
// StockList
// 1、如果筛选条件有: 库存情况筛选; 则以库存表为准, 查库存表即可
// ( 1) 没门店, 则查所有库存情况并排序
// ( 2) 有门店, 则查门店对应的库存情况并排序
// 2、如果筛选条件没有库存情况,
// ( 1) 先查询商品资料, 并排序; 支持筛选条件: 商品编号、商品分类、商品名称
// ( 2) 然后查询每个商品资料的库存情况, 没传门店id, 则查所有库存; 否则查当前门店的库存情况
2024-04-17 09:44:43 +00:00
func ( m * ErpStockListReq ) StockList ( c * gin . Context ) ( * ErpStockListResp , error ) {
2023-12-11 08:21:21 +00:00
switch m . StockType {
case 2 : // 有库存
2024-04-17 09:44:43 +00:00
return m . stockNoEmptyList ( c )
2023-12-11 08:21:21 +00:00
case 3 : // 无库存,连表查询商品明细和库存表
2024-04-17 09:44:43 +00:00
return m . stockIsEmptyList ( c )
2023-12-11 08:21:21 +00:00
default : // 0和1, 以及其他值, 表示无库存情况筛选
2024-04-17 09:44:43 +00:00
return m . allCommodityList ( c )
2023-12-11 08:21:21 +00:00
}
}
// stockIsEmptyList 库存列表-无库存查询
// 无库存,要连表查询(商品明细、库存表)
2024-04-17 09:44:43 +00:00
func ( m * ErpStockListReq ) stockIsEmptyList ( c * gin . Context ) ( * ErpStockListResp , error ) {
2023-12-11 08:21:21 +00:00
resp := & ErpStockListResp {
PageIndex : m . PageIndex ,
PageSize : m . PageSize ,
}
page := m . PageIndex - 1
if page < 0 {
page = 0
}
if m . PageSize == 0 {
m . PageSize = 10
}
//以下代码组合了2个连表查询
//( 1) 查询无库存的商品资料
/ * * *
SELECT erp_commodity . * ,
COALESCE ( erp_stock . count , 0 ) AS count
FROM erp_commodity
LEFT JOIN (
SELECT erp_commodity_id , SUM ( count ) AS count
FROM erp_stock
GROUP BY erp_commodity_id
) erp_stock ON erp_commodity . id = erp_stock . erp_commodity_id
WHERE erp_stock . count IS NULL OR erp_stock . count = 0 ;
* * * /
//( 2) 按商品编号排序
/ * * *
SELECT e . *
FROM erp_stock e
JOIN erp_category c ON e . erp_category_id = c . id
ORDER BY
CASE WHEN c . pid = 0 THEN CAST ( c . number AS SIGNED ) ELSE CAST ( SUBSTRING ( c . number , 1 , 3 ) AS SIGNED ) END ,
CAST ( c . pid AS SIGNED ) ,
CAST ( SUBSTRING ( e . commodity_serial_number , - 4 ) AS SIGNED ) ;
* * * /
2024-09-26 03:43:52 +00:00
qs := orm . Eloquent . Table ( "erp_commodity" )
es := orm . Eloquent . Table ( "erp_commodity" )
2024-04-17 09:44:43 +00:00
// 非管理员才判断所属门店
var storeList [ ] uint32
if ! ( tools . GetRoleName ( c ) == "admin" || tools . GetRoleName ( c ) == "系统管理员" ) {
sysUser , err := GetSysUserByCtx ( c )
if err != nil {
return nil , err
}
// 返回sysUser未过期的门店id列表
storeList = GetValidStoreIDs ( sysUser . StoreData )
if m . StoreId != 0 {
if ! Contains ( storeList , m . StoreId ) {
return nil , errors . New ( "您没有该门店权限" )
}
} else {
if len ( storeList ) == 0 {
return nil , errors . New ( "用户未绑定门店" )
}
}
}
2023-12-11 08:21:21 +00:00
if m . StoreId != 0 { // 传门店id
2024-04-29 10:10:48 +00:00
qs = qs . Select ( "erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count," +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count" ) .
2024-04-01 03:00:22 +00:00
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id AND erp_stock.store_id = ?" , m . StoreId ) .
//Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id").
Joins ( "LEFT JOIN erp_category c ON erp_commodity.erp_category_id = c.id" ) .
2024-05-23 07:30:20 +00:00
Group ( "erp_commodity.id" ) .
2024-04-01 03:00:22 +00:00
//Where("erp_stock.count = 0 AND erp_stock.store_id = ?", m.StoreId).
Order ( "CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) " +
"ELSE CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END, " +
"CAST(c.pid AS SIGNED), CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" )
2024-04-29 10:10:48 +00:00
es = es . Select ( "erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count, " +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count" ) .
2024-04-01 03:00:22 +00:00
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id AND erp_stock.store_id = ?" , m . StoreId ) .
//Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id").
Joins ( "LEFT JOIN erp_category c ON erp_commodity.erp_category_id = c.id" ) .
2024-05-23 07:30:20 +00:00
Group ( "erp_commodity.id" ) .
2024-04-01 03:00:22 +00:00
//Where("erp_stock.count = 0 AND erp_stock.store_id = ?", m.StoreId).
2023-12-11 08:21:21 +00:00
Order ( "CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) " +
"ELSE CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END, " +
"CAST(c.pid AS SIGNED), CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" )
2024-05-27 03:08:39 +00:00
} else {
qs = qs . Select ( "erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count," +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count" ) .
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id" ) .
//Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id").
Joins ( "LEFT JOIN erp_category c ON erp_commodity.erp_category_id = c.id" ) .
Group ( "erp_commodity.id" ) .
//Where("erp_stock.count = 0 AND erp_stock.store_id = ?", m.StoreId).
Order ( "CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) " +
"ELSE CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END, " +
"CAST(c.pid AS SIGNED), CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" )
es = es . Select ( "erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count, " +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count" ) .
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id" ) .
//Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id").
Joins ( "LEFT JOIN erp_category c ON erp_commodity.erp_category_id = c.id" ) .
Group ( "erp_commodity.id" ) .
//Where("erp_stock.count = 0 AND erp_stock.store_id = ?", m.StoreId).
Order ( "CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) " +
"ELSE CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END, " +
"CAST(c.pid AS SIGNED), CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" )
2023-12-11 08:21:21 +00:00
}
2024-05-27 03:08:39 +00:00
//} else { // 没传门店id, 则子查询先求库存表中erp_commodity_id相同的count之和
// if len(storeList) == 0 {
// qs = qs.Select("erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count, " +
// "COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count").
// Joins("LEFT JOIN (SELECT erp_commodity_id, SUM(count) AS count, SUM(dispatch_count) AS dispatch_count FROM erp_stock GROUP BY erp_commodity_id) " +
// "erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id").
// Joins("JOIN erp_category c ON erp_commodity.erp_category_id = c.id").
// Where("erp_stock.count IS NULL OR erp_stock.count = 0").
// Order("CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) " +
// "ELSE CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END, " +
// "CAST(c.pid AS SIGNED), CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)")
// es = es.Select("erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count, " +
// "COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count").
// Joins("LEFT JOIN (SELECT erp_commodity_id, SUM(count) AS count, SUM(dispatch_count) AS dispatch_count FROM erp_stock GROUP BY erp_commodity_id) " +
// "erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id").
// Joins("JOIN erp_category c ON erp_commodity.erp_category_id = c.id").
// Where("erp_stock.count IS NULL OR erp_stock.count = 0").
// Order("CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) " +
// "ELSE CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END, " +
// "CAST(c.pid AS SIGNED), CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)")
// } else {
// qs = qs.Select("erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count, "+
// "COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count").
// Joins("LEFT JOIN (SELECT erp_commodity_id, SUM(count) AS count, SUM(dispatch_count) AS dispatch_count FROM erp_stock WHERE store_id IN (?) GROUP BY erp_commodity_id) "+
// "erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id", storeList).
// Joins("JOIN erp_category c ON erp_commodity.erp_category_id = c.id").
// Where("erp_stock.count IS NULL OR erp_stock.count = 0").
// Order("CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) " +
// "ELSE CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END, " +
// "CAST(c.pid AS SIGNED), CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)")
// es = es.Select("erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count, "+
// "COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count").
// Joins("LEFT JOIN (SELECT erp_commodity_id, SUM(count) AS count, SUM(dispatch_count) AS dispatch_count FROM erp_stock WHERE store_id IN (?) GROUP BY erp_commodity_id) "+
// "erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id", storeList).
// Joins("JOIN erp_category c ON erp_commodity.erp_category_id = c.id").
// Where("erp_stock.count IS NULL OR erp_stock.count = 0").
// Order("CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) " +
// "ELSE CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END, " +
// "CAST(c.pid AS SIGNED), CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)")
// }
//}
2023-12-11 08:21:21 +00:00
if m . SerialNumber != "" {
qs = qs . Where ( "erp_commodity.serial_number=?" , m . SerialNumber )
2024-04-01 03:00:22 +00:00
es = es . Where ( "erp_commodity.serial_number=?" , m . SerialNumber )
2023-12-11 08:21:21 +00:00
}
if m . CommodityName != "" {
qs = qs . Where ( "erp_commodity.name Like '%" + m . CommodityName + "%'" )
2024-04-01 03:00:22 +00:00
es = es . Where ( "erp_commodity.name Like '%" + m . CommodityName + "%'" )
2023-12-11 08:21:21 +00:00
//qs = qs.Where("name LIKE ?", m.Name)
}
if m . ErpCategoryId != 0 {
qs = qs . Where ( "erp_commodity.erp_category_id=?" , m . ErpCategoryId )
2024-04-01 03:00:22 +00:00
es = es . Where ( "erp_commodity.erp_category_id=?" , m . ErpCategoryId )
2023-12-11 08:21:21 +00:00
}
var count int64
2024-04-01 03:00:22 +00:00
err := es . Count ( & count ) . Error
2023-12-11 08:21:21 +00:00
if err != nil {
logger . Error ( "查询无库存列表数量失败" , logger . Field ( "err" , err ) )
return nil , err
}
2024-04-01 03:00:22 +00:00
var commodities [ ] struct {
ErpCommodity
2024-04-29 10:10:48 +00:00
TotalCount int
TotalDispatchCount int
2024-04-01 03:00:22 +00:00
}
//err = qs.Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error
err = qs . Find ( & commodities ) . Error
if err != nil && err != RecordNotFound {
logger . Error ( "查询无库存列表失败" , logger . Field ( "err" , err ) )
return nil , err
}
2023-12-11 08:21:21 +00:00
//遍历商品资料,转换为库存列表数据
var stockList [ ] ErpStock
for _ , commodity := range commodities {
2024-04-01 03:00:22 +00:00
if commodity . TotalCount == 0 {
2024-11-13 07:49:57 +00:00
if commodity . StopPurchase == 1 { // 停止采购且没有库存
continue
}
2024-04-01 03:00:22 +00:00
var stock ErpStock
stock . ErpCommodityId = commodity . ID
stock . ErpCommodityName = commodity . Name
stock . ErpCategoryId = commodity . ErpCategoryId
stock . ErpCategoryName = commodity . ErpCategoryName
stock . CommoditySerialNumber = commodity . SerialNumber
stock . IMEIType = commodity . IMEIType
stock . RetailPrice = commodity . RetailPrice
stock . MinRetailPrice = commodity . MinRetailPrice
stock . Count = 0
stock . DispatchCount = 0
stockList = append ( stockList , stock )
}
}
2023-12-11 08:21:21 +00:00
2024-05-10 01:54:37 +00:00
SortStockCommodities ( stockList )
2024-11-19 10:38:17 +00:00
if m . IsExport == 1 {
filePath , err := InventoryListExport ( stockList , m . StockType )
if err != nil {
return nil , err
}
resp = & ErpStockListResp { }
resp . ExportUrl = filePath
} else {
// Paginate results
startIndex := page * m . PageSize
endIndex := startIndex + m . PageSize
if endIndex > len ( stockList ) {
endIndex = len ( stockList )
}
2023-12-11 08:21:21 +00:00
2024-11-19 10:38:17 +00:00
// Slice the users based on pagination
pagedList := stockList [ startIndex : endIndex ]
2024-04-01 03:00:22 +00:00
2024-11-19 10:38:17 +00:00
//跟之前保持一致
resp . Total = len ( stockList )
resp . PageIndex = page + 1
resp . PageSize = m . PageSize
resp . List = pagedList
}
2023-12-11 08:21:21 +00:00
return resp , nil
}
2024-04-17 09:44:43 +00:00
func ( m * ErpStockListReq ) stockNoEmptyList ( c * gin . Context ) ( * ErpStockListResp , error ) {
2023-12-11 08:21:21 +00:00
resp := & ErpStockListResp {
PageIndex : m . PageIndex ,
PageSize : m . PageSize ,
}
page := m . PageIndex - 1
if page < 0 {
page = 0
}
if m . PageSize == 0 {
m . PageSize = 10
}
/ * * *
//组合查询
SELECT
ec . * ,
COALESCE ( SUM ( es . count ) , 0 ) AS total_count
FROM
erp_commodity ec
LEFT JOIN
erp_stock es ON ec . id = es . erp_commodity_id
GROUP BY
ec . id
ORDER BY
CASE
WHEN ec . erp_category_id IN ( SELECT id FROM erp_category WHERE pid = 0 ) THEN CAST ( ( SELECT number FROM erp_category WHERE id = ec . erp_category_id ) AS SIGNED )
ELSE CAST ( SUBSTRING ( ( SELECT number FROM erp_category WHERE id = ( SELECT pid FROM erp_category WHERE id = ec . erp_category_id ) ) , 1 , 3 ) AS SIGNED )
END ,
CAST ( ( SELECT pid FROM erp_category WHERE id = ec . erp_category_id ) AS SIGNED ) ,
CAST ( SUBSTRING ( ec . serial_number , - 4 ) AS SIGNED ) ;
* * * /
2024-09-26 03:43:52 +00:00
qs := orm . Eloquent . Table ( "erp_commodity" )
es := orm . Eloquent . Table ( "erp_commodity" )
2024-04-17 09:44:43 +00:00
// 非管理员才判断所属门店
if ! ( tools . GetRoleName ( c ) == "admin" || tools . GetRoleName ( c ) == "系统管理员" ) {
sysUser , err := GetSysUserByCtx ( c )
if err != nil {
return nil , err
}
// 返回sysUser未过期的门店id列表
storeList := GetValidStoreIDs ( sysUser . StoreData )
if m . StoreId != 0 {
if ! Contains ( storeList , m . StoreId ) {
return nil , errors . New ( "您没有该门店权限" )
}
} else {
if len ( storeList ) > 0 {
2024-05-27 11:01:04 +00:00
if len ( storeList ) == 1 {
2024-07-12 07:54:31 +00:00
qs = qs . Where ( "erp_stock.store_id = ?" , storeList [ 0 ] )
es = es . Where ( "erp_stock.store_id = ?" , storeList [ 0 ] )
2024-05-27 11:01:04 +00:00
} else {
2024-07-12 07:54:31 +00:00
qs = qs . Where ( "erp_stock.store_id IN (?)" , storeList )
es = es . Where ( "erp_stock.store_id IN (?)" , storeList )
2024-05-27 11:01:04 +00:00
}
2024-04-17 09:44:43 +00:00
} else {
return nil , errors . New ( "用户未绑定门店" )
}
}
}
2023-12-11 08:21:21 +00:00
if m . StoreId == 0 { // 没指定门店,连表查询并计算总数量
2024-04-29 10:10:48 +00:00
qs = qs . Select ( "erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, " +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count, erp_stock.id AS erp_stock_id" ) .
2023-12-11 08:21:21 +00:00
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id AND erp_stock.count != 0" ) .
Group ( "erp_commodity.id" ) .
Order ( "CASE WHEN erp_commodity.erp_category_id IN (SELECT id FROM erp_category WHERE pid = 0) " +
"THEN CAST((SELECT number FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED) " +
"ELSE CAST(SUBSTRING((SELECT number FROM erp_category WHERE id = (SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id)), 1, 3) AS SIGNED) " +
"END, CAST((SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED), " +
"CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" )
2024-04-29 10:10:48 +00:00
es = es . Select ( "erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, " +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count, erp_stock.id AS erp_stock_id" ) .
2024-04-01 03:00:22 +00:00
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id AND erp_stock.count != 0" ) .
Group ( "erp_commodity.id" ) .
Order ( "CASE WHEN erp_commodity.erp_category_id IN (SELECT id FROM erp_category WHERE pid = 0) " +
"THEN CAST((SELECT number FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED) " +
"ELSE CAST(SUBSTRING((SELECT number FROM erp_category WHERE id = (SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id)), 1, 3) AS SIGNED) " +
"END, CAST((SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED), " +
"CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" )
2023-12-11 08:21:21 +00:00
} else { // 指定了门店, 连表查询指定store_id的count
2024-04-29 10:10:48 +00:00
qs = qs . Select ( "erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, " +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count, erp_stock.id AS erp_stock_id" ) .
2023-12-11 08:21:21 +00:00
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id " +
"AND erp_stock.count != 0 AND erp_stock.store_id = ?" , m . StoreId ) .
Group ( "erp_commodity.id" ) .
Order ( "CASE WHEN erp_category.pid = 0 THEN CAST(erp_category.number AS SIGNED) " +
"ELSE CAST(SUBSTRING(erp_category.number, 1, 3) AS SIGNED) END, " +
"CAST(erp_category.pid AS SIGNED), " +
"CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" ) .
Joins ( "JOIN erp_category ON erp_commodity.erp_category_id = erp_category.id" )
2024-04-29 10:10:48 +00:00
es = es . Select ( "erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, " +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count, erp_stock.id AS erp_stock_id" ) .
2024-04-01 03:00:22 +00:00
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id " +
"AND erp_stock.count != 0 AND erp_stock.store_id = ?" , m . StoreId ) .
Group ( "erp_commodity.id" ) .
Order ( "CASE WHEN erp_category.pid = 0 THEN CAST(erp_category.number AS SIGNED) " +
"ELSE CAST(SUBSTRING(erp_category.number, 1, 3) AS SIGNED) END, " +
"CAST(erp_category.pid AS SIGNED), " +
"CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" ) .
Joins ( "JOIN erp_category ON erp_commodity.erp_category_id = erp_category.id" )
2023-12-11 08:21:21 +00:00
}
if m . SerialNumber != "" {
qs = qs . Where ( "erp_commodity.serial_number=?" , m . SerialNumber )
2024-04-01 03:00:22 +00:00
es = es . Where ( "erp_commodity.serial_number=?" , m . SerialNumber )
2023-12-11 08:21:21 +00:00
}
if m . CommodityName != "" {
qs = qs . Where ( "erp_commodity.name Like '%" + m . CommodityName + "%'" )
2024-04-01 03:00:22 +00:00
es = es . Where ( "erp_commodity.name Like '%" + m . CommodityName + "%'" )
2023-12-11 08:21:21 +00:00
}
if m . ErpCategoryId != 0 {
qs = qs . Where ( "erp_commodity.erp_category_id=?" , m . ErpCategoryId )
2024-04-01 03:00:22 +00:00
es = es . Where ( "erp_commodity.erp_category_id=?" , m . ErpCategoryId )
2023-12-11 08:21:21 +00:00
}
2024-07-12 07:54:31 +00:00
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 )
}
}
2023-12-11 08:21:21 +00:00
var commodities [ ] struct {
ErpCommodity
2024-04-29 10:10:48 +00:00
TotalCount int
ErpStockId int
TotalDispatchCount int
2023-12-11 08:21:21 +00:00
}
var count int64
2024-04-01 03:00:22 +00:00
err := es . Count ( & count ) . Error
2023-12-11 08:21:21 +00:00
if err != nil {
logger . Error ( "commodityList count err" , logger . Field ( "err" , err ) )
return resp , err
}
2024-04-01 03:00:22 +00:00
//err = qs.Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error
err = qs . Find ( & commodities ) . Error
if err != nil && err != RecordNotFound {
logger . Error ( "commodityList err" , logger . Field ( "err" , err ) )
return resp , err
}
2023-12-11 08:21:21 +00:00
//遍历商品资料,转换为库存列表数据
var stockList [ ] ErpStock
for _ , commodity := range commodities {
if commodity . TotalCount != 0 {
var stock ErpStock
stock . ID = uint32 ( commodity . ErpStockId )
stock . ErpCommodityId = commodity . ID
stock . ErpCommodityName = commodity . Name
stock . ErpCategoryId = commodity . ErpCategoryId
stock . ErpCategoryName = commodity . ErpCategoryName
stock . CommoditySerialNumber = commodity . SerialNumber
2024-03-27 10:01:38 +00:00
stock . IMEIType = commodity . IMEIType
2023-12-11 08:21:21 +00:00
stock . RetailPrice = commodity . RetailPrice
stock . MinRetailPrice = commodity . MinRetailPrice
stock . Count = uint32 ( commodity . TotalCount )
2024-04-29 10:10:48 +00:00
stock . DispatchCount = uint32 ( commodity . TotalDispatchCount )
2023-12-11 08:21:21 +00:00
stockList = append ( stockList , stock )
}
2024-04-01 03:00:22 +00:00
}
2023-12-11 08:21:21 +00:00
2024-05-10 01:54:37 +00:00
SortStockCommodities ( stockList )
2024-11-19 10:38:17 +00:00
if m . IsExport == 1 {
filePath , err := InventoryListExport ( stockList , m . StockType )
if err != nil {
return nil , err
}
resp = & ErpStockListResp { }
resp . ExportUrl = filePath
} else {
// Paginate results
startIndex := page * m . PageSize
endIndex := startIndex + m . PageSize
if endIndex > len ( stockList ) {
endIndex = len ( stockList )
}
2023-12-11 08:21:21 +00:00
2024-11-19 10:38:17 +00:00
// Slice the users based on pagination
pagedList := stockList [ startIndex : endIndex ]
2024-04-01 03:00:22 +00:00
2024-11-19 10:38:17 +00:00
//跟之前保持一致
resp . Total = len ( stockList )
resp . PageIndex = page + 1
resp . PageSize = m . PageSize
resp . List = pagedList
}
2023-12-11 08:21:21 +00:00
return resp , nil
}
// 筛选条件无:库存情况筛选
// ( 1) 先查询商品资料, 并排序; 支持筛选条件: 商品编号、商品分类、商品名称
// ( 2) 然后查询每个商品资料的库存情况, 没传门店id, 则查所有库存; 否则查当前门店的库存情况
2024-04-17 09:44:43 +00:00
func ( m * ErpStockListReq ) allCommodityList ( c * gin . Context ) ( * ErpStockListResp , error ) {
2023-12-11 08:21:21 +00:00
resp := & ErpStockListResp {
PageIndex : m . PageIndex ,
PageSize : m . PageSize ,
}
page := m . PageIndex - 1
if page < 0 {
page = 0
}
if m . PageSize == 0 {
m . PageSize = 10
}
/ * * *
//组合查询
SELECT
ec . * ,
COALESCE ( SUM ( es . count ) , 0 ) AS total_count
FROM
erp_commodity ec
LEFT JOIN
erp_stock es ON ec . id = es . erp_commodity_id
GROUP BY
ec . id
ORDER BY
CASE
WHEN ec . erp_category_id IN ( SELECT id FROM erp_category WHERE pid = 0 ) THEN CAST ( ( SELECT number FROM erp_category WHERE id = ec . erp_category_id ) AS SIGNED )
ELSE CAST ( SUBSTRING ( ( SELECT number FROM erp_category WHERE id = ( SELECT pid FROM erp_category WHERE id = ec . erp_category_id ) ) , 1 , 3 ) AS SIGNED )
END ,
CAST ( ( SELECT pid FROM erp_category WHERE id = ec . erp_category_id ) AS SIGNED ) ,
CAST ( SUBSTRING ( ec . serial_number , - 4 ) AS SIGNED ) ;
* * * /
2024-09-26 03:43:52 +00:00
qs := orm . Eloquent . Table ( "erp_commodity" )
es := orm . Eloquent . Table ( "erp_commodity" )
2023-12-11 08:21:21 +00:00
if m . SerialNumber != "" {
qs = qs . Where ( "erp_commodity.serial_number=?" , m . SerialNumber )
2024-04-01 03:00:22 +00:00
es = es . Where ( "erp_commodity.serial_number=?" , m . SerialNumber )
2023-12-11 08:21:21 +00:00
}
if m . CommodityName != "" {
qs = qs . Where ( "erp_commodity.name Like '%" + m . CommodityName + "%'" )
2024-04-01 03:00:22 +00:00
es = es . Where ( "erp_commodity.name Like '%" + m . CommodityName + "%'" )
2023-12-11 08:21:21 +00:00
}
if m . ErpCategoryId != 0 {
qs = qs . Where ( "erp_commodity.erp_category_id=?" , m . ErpCategoryId )
2024-04-01 03:00:22 +00:00
es = es . Where ( "erp_commodity.erp_category_id=?" , m . ErpCategoryId )
2023-12-11 08:21:21 +00:00
}
2024-04-17 09:44:43 +00:00
// 非管理员才判断所属门店
if ! ( tools . GetRoleName ( c ) == "admin" || tools . GetRoleName ( c ) == "系统管理员" ) {
sysUser , err := GetSysUserByCtx ( c )
if err != nil {
return nil , err
}
// 返回sysUser未过期的门店id列表
storeList := GetValidStoreIDs ( sysUser . StoreData )
if m . StoreId != 0 {
if ! Contains ( storeList , m . StoreId ) {
return nil , errors . New ( "您没有该门店权限" )
}
} else {
if len ( storeList ) > 0 {
2024-05-27 11:01:04 +00:00
if len ( storeList ) == 1 {
qs = qs . Where ( "store_id = ?" , storeList [ 0 ] )
es = es . Where ( "store_id = ?" , storeList [ 0 ] )
} else {
qs = qs . Where ( "store_id IN (?)" , storeList )
es = es . Where ( "store_id IN (?)" , storeList )
}
2024-04-17 09:44:43 +00:00
} else {
return nil , errors . New ( "用户未绑定门店" )
}
}
}
2023-12-11 08:21:21 +00:00
if m . StoreId == 0 { // 没指定门店,连表查询并计算总数量
2024-04-29 10:10:48 +00:00
qs = qs . Select ( "erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, " +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count, erp_stock.id AS erp_stock_id" ) .
2023-12-11 08:21:21 +00:00
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id" ) .
Group ( "erp_commodity.id" ) .
Order ( "CASE WHEN erp_commodity.erp_category_id IN (SELECT id FROM erp_category WHERE pid = 0) " +
"THEN CAST((SELECT number FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED) " +
"ELSE CAST(SUBSTRING((SELECT number FROM erp_category WHERE id = (SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id)), 1, 3) AS SIGNED) " +
"END, CAST((SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED), " +
"CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" )
2024-04-29 10:10:48 +00:00
es = es . Select ( "erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, " +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count, erp_stock.id AS erp_stock_id" ) .
2024-04-01 03:00:22 +00:00
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id" ) .
Group ( "erp_commodity.id" ) .
Order ( "CASE WHEN erp_commodity.erp_category_id IN (SELECT id FROM erp_category WHERE pid = 0) " +
"THEN CAST((SELECT number FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED) " +
"ELSE CAST(SUBSTRING((SELECT number FROM erp_category WHERE id = (SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id)), 1, 3) AS SIGNED) " +
"END, CAST((SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED), " +
"CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" )
2023-12-11 08:21:21 +00:00
} else { // 指定了门店, 连表查询指定store_id的count
2024-04-29 10:10:48 +00:00
qs = qs . Select ( "erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, " +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count, erp_stock.id AS erp_stock_id" ) .
2023-12-11 08:21:21 +00:00
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id " +
"AND erp_stock.store_id = ?" , m . StoreId ) .
Group ( "erp_commodity.id" ) .
Order ( "CASE WHEN erp_category.pid = 0 THEN CAST(erp_category.number AS SIGNED) " +
"ELSE CAST(SUBSTRING(erp_category.number, 1, 3) AS SIGNED) END, " +
"CAST(erp_category.pid AS SIGNED), " +
"CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" ) .
Joins ( "JOIN erp_category ON erp_commodity.erp_category_id = erp_category.id" )
2024-04-29 10:10:48 +00:00
es = es . Select ( "erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, " +
"COALESCE(SUM(erp_stock.dispatch_count), 0) AS total_dispatch_count, erp_stock.id AS erp_stock_id" ) .
2024-04-01 03:00:22 +00:00
Joins ( "LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id " +
"AND erp_stock.store_id = ?" , m . StoreId ) .
Group ( "erp_commodity.id" ) .
Order ( "CASE WHEN erp_category.pid = 0 THEN CAST(erp_category.number AS SIGNED) " +
"ELSE CAST(SUBSTRING(erp_category.number, 1, 3) AS SIGNED) END, " +
"CAST(erp_category.pid AS SIGNED), " +
"CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)" ) .
Joins ( "JOIN erp_category ON erp_commodity.erp_category_id = erp_category.id" )
2023-12-11 08:21:21 +00:00
}
var commodities [ ] struct {
ErpCommodity
2024-04-29 10:10:48 +00:00
TotalCount int
ErpStockId int
TotalDispatchCount int
2023-12-11 08:21:21 +00:00
}
var count int64
2024-05-27 03:08:39 +00:00
err := orm . Eloquent . Debug ( ) . Table ( "(?) AS subquery" , es ) . Count ( & count ) . Error
2024-05-31 09:51:41 +00:00
//err := es.Total(&count).Error
2023-12-11 08:21:21 +00:00
if err != nil {
logger . Error ( "commodityList count err" , logger . Field ( "err" , err ) )
return resp , err
}
2024-11-19 10:38:17 +00:00
if m . IsExport == 1 {
err = qs . Find ( & commodities ) . Error
} else {
err = qs . Offset ( page * m . PageSize ) . Limit ( m . PageSize ) . Find ( & commodities ) . Error
}
2024-04-01 03:00:22 +00:00
if err != nil && err != RecordNotFound {
logger . Error ( "commodityList err" , logger . Field ( "err" , err ) )
return resp , err
}
2023-12-11 08:21:21 +00:00
//遍历商品资料,转换为库存列表数据
var stockList [ ] ErpStock
for _ , commodity := range commodities {
2024-11-13 07:49:57 +00:00
if commodity . StopPurchase == 1 && commodity . TotalCount == 0 { // 停止采购且没有库存
continue
}
2023-12-11 08:21:21 +00:00
var stock ErpStock
stock . ID = uint32 ( commodity . ErpStockId )
stock . ErpCommodityId = commodity . ID
stock . ErpCommodityName = commodity . Name
stock . ErpCategoryId = commodity . ErpCategoryId
stock . ErpCategoryName = commodity . ErpCategoryName
stock . CommoditySerialNumber = commodity . SerialNumber
2024-03-27 10:01:38 +00:00
stock . IMEIType = commodity . IMEIType
2023-12-11 08:21:21 +00:00
stock . RetailPrice = commodity . RetailPrice
stock . MinRetailPrice = commodity . MinRetailPrice
stock . Count = uint32 ( commodity . TotalCount )
2024-04-29 10:10:48 +00:00
stock . DispatchCount = uint32 ( commodity . TotalDispatchCount )
2023-12-11 08:21:21 +00:00
stockList = append ( stockList , stock )
}
2024-05-10 01:54:37 +00:00
SortStockCommodities ( stockList )
2024-11-19 10:38:17 +00:00
if m . IsExport == 1 {
filePath , err := InventoryListExport ( stockList , m . StockType )
if err != nil {
return nil , err
}
resp = & ErpStockListResp { }
resp . ExportUrl = filePath
} else {
//跟之前保持一致
resp . Total = int ( count )
resp . PageIndex = page + 1
resp . PageSize = m . PageSize
resp . List = stockList
}
2023-12-11 08:21:21 +00:00
return resp , nil
}
2024-11-19 10:38:17 +00:00
// InventoryListExport 导出库存列表
func InventoryListExport ( list [ ] ErpStock , nType uint32 ) ( string , error ) {
file := excelize . NewFile ( )
fSheet := "Sheet1"
var fileName string
switch nType {
case 2 : // 有库存
fileName = time . Now ( ) . Format ( TimeFormat ) + "库存列表(有库存)" + ".xlsx"
case 3 : // 无库存
fileName = time . Now ( ) . Format ( TimeFormat ) + "库存列表(无库存)" + ".xlsx"
default : // 全部
fileName = time . Now ( ) . Format ( TimeFormat ) + "库存列表(全部)" + ".xlsx"
}
url := config . ExportConfig . Url
fmt . Println ( "url fileName:" , url + fileName )
// 设置标题行
title1 := [ ] interface { } { "基础资料" , "" , "" , "" , "" , "" , "库存情况" , "" }
title2 := [ ] interface { } { "商品编号" , "商品名称" , "商品分类" , "是否串码" , "指导零售价" , "最低零售价" , "有效库存数量" , "调出中数量" }
for i , _ := range title1 {
cell , _ := excelize . CoordinatesToCellName ( 1 + i , 1 )
err := file . SetCellValue ( fSheet , cell , title1 [ i ] )
if err != nil {
logger . Errorf ( "file set value err:" , err )
}
}
for i , _ := range title2 {
cell , _ := excelize . CoordinatesToCellName ( 1 + i , 2 )
err := file . SetCellValue ( fSheet , cell , title2 [ i ] )
if err != nil {
logger . Errorf ( "file set value err:" , err )
}
}
nExcelStartRow := 0
for rowId := 0 ; rowId < len ( list ) ; rowId ++ {
isIMEIType := "是"
if list [ rowId ] . IMEIType == 1 {
isIMEIType = "否"
}
row := [ ] interface { } {
list [ rowId ] . CommoditySerialNumber ,
list [ rowId ] . ErpCommodityName ,
list [ rowId ] . ErpCategoryName ,
isIMEIType ,
list [ rowId ] . RetailPrice ,
list [ rowId ] . MinRetailPrice ,
list [ rowId ] . Count ,
list [ rowId ] . DispatchCount ,
}
for j , _ := range row {
cell , _ := excelize . CoordinatesToCellName ( 1 + j , nExcelStartRow + 3 )
err := file . SetCellValue ( fSheet , cell , row [ j ] )
if err != nil {
logger . Error ( "file set value err:" , logger . Field ( "err" , err ) )
}
}
nExcelStartRow ++
}
// 设置所有单元格的样式: 居中、加边框
style , _ := file . NewStyle ( ` { "alignment" : { "horizontal" : "center" , "vertical" : "center" } ,
"border" : [ { "type" : "left" , "color" : "000000" , "style" : 1 } ,
{ "type" : "top" , "color" : "000000" , "style" : 1 } ,
{ "type" : "right" , "color" : "000000" , "style" : 1 } ,
{ "type" : "bottom" , "color" : "000000" , "style" : 1 } ] } ` )
// 合并单元格
_ = file . MergeCell ( fSheet , "A1" , "F1" )
_ = file . MergeCell ( fSheet , "G1" , "H1" )
//设置单元格高度
file . SetRowHeight ( "Sheet1" , 1 , 20 )
// 设置单元格大小
file . SetColWidth ( "Sheet1" , "A" , "A" , 13 )
file . SetColWidth ( "Sheet1" , "B" , "B" , 40 )
file . SetColWidth ( "Sheet1" , "C" , "C" , 13 )
file . SetColWidth ( "Sheet1" , "E" , "E" , 13 )
file . SetColWidth ( "Sheet1" , "F" , "F" , 13 )
file . SetColWidth ( "Sheet1" , "G" , "G" , 13 )
file . SetColWidth ( "Sheet1" , "H" , "H" , 13 )
endRow := fmt . Sprintf ( "H" + "%d" , nExcelStartRow + 2 )
// 应用样式到整个表格
_ = file . SetCellStyle ( "Sheet1" , "A1" , endRow , style )
fmt . Println ( "save fileName:" , config . ExportConfig . Path + fileName )
if err := file . SaveAs ( config . ExportConfig . Path + fileName ) ; err != nil {
fmt . Println ( err )
}
return url + fileName , nil
}
2023-11-08 03:51:33 +00:00
func ErpStockCommodityListSetAge ( commodities [ ] ErpStockCommodity ) {
nowTime := time . Now ( )
for i , _ := range commodities {
commodities [ i ] . Age = uint32 ( nowTime . Sub ( commodities [ i ] . StockTime ) . Hours ( ) ) / 24
commodities [ i ] . AllAge = uint32 ( nowTime . Sub ( commodities [ i ] . FirstStockTime ) . Hours ( ) ) / 24
}
}
2024-09-22 03:15:44 +00:00
func ErpStockCommodityListSetCategoryNumber ( commodities [ ] ErpStockCommodity ) {
for i , _ := range commodities {
categoryInfo , _ := GetErpCategory ( commodities [ i ] . ErpCategoryId )
if categoryInfo != nil {
commodities [ i ] . CategoryNumber = categoryInfo . Number
}
}
}
2023-11-16 10:09:11 +00:00
// ErpStockCommodityListReq 库存详情接口请求参数
2023-11-08 03:51:33 +00:00
type ErpStockCommodityListReq struct {
2024-07-01 01:44:35 +00:00
ScanCode string ` json:"scan_code" ` // 扫码枪扫码数据:串码/条码
ErpStockId uint32 ` json:"erp_stock_id" ` // 库存id
ErpCommodityId uint32 ` json:"erp_commodity_id" ` // 商品id
SerialNumber string ` json:"serial_number" ` // 商品编号
2024-07-12 01:39:14 +00:00
CommodityName [ ] string ` json:"commodity_name" ` // 商品名称
2024-07-01 01:44:35 +00:00
ErpCategoryId uint32 ` json:"erp_category_id" ` // 商品分类Id
IsIMEI uint32 ` json:"is_imei" ` // 是否串码: 0-查全部 1-查串码类 2-查非串码
IMEI string ` json:"imei" ` // 串码
StoreId uint32 ` json:"store_id" ` // 门店编号
SupplierId uint32 ` json:"supplier_id" ` // 供应商id
State [ ] uint32 ` json:"state" ` // 库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库( 前端只看1, 4)
OriginalSn string ` json:"original_sn" ` // 首次入库订单编号
StorageType uint32 ` json:"storage_type" ` // 首次入库方式: 1-系统入库 2-采购入库
StockTimeStart string ` json:"stock_time_start" ` // 最近入库开始时间
StockTimeEnd string ` json:"stock_time_end" ` // 最近入库结束时间
Age uint32 ` json:"age" ` // 最近库龄
AllAge uint32 ` json:"all_age" ` // 总库龄
PageIndex int ` json:"pageIndex" ` // 页码
PageSize int ` json:"pageSize" ` // 每页展示数据条数
IsExport uint32 ` json:"is_export" ` // 是否导出excel: 1-导出
2024-07-10 07:24:34 +00:00
StockSortFlag uint32 ` json:"stock_sort_flag" ` // 排序方式: 0-按入库时间降序排列( 默认) , 1-按入库时间升序排列
2024-04-22 01:51:41 +00:00
//Sn string `json:"sn"` // 首次入库订单编号
2023-11-08 03:51:33 +00:00
}
2023-11-24 09:09:24 +00:00
2024-11-20 08:17:53 +00:00
// NewErpStockCommodityListReq 库存详情接口请求参数
type NewErpStockCommodityListReq struct {
ScanCode string ` json:"scan_code" ` // 扫码枪扫码数据:串码/条码
ErpStockId uint32 ` json:"erp_stock_id" ` // 库存id
ErpCommodityId uint32 ` json:"erp_commodity_id" ` // 商品id
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-查非串码
IMEI string ` json:"imei" ` // 串码
StoreId [ ] uint32 ` json:"store_id" ` // 门店编号
SupplierId uint32 ` json:"supplier_id" ` // 供应商id
State [ ] uint32 ` json:"state" ` // 库存状态:1-在库 2-已售 3-采购退货 4-调拨中 5-出库( 前端只看1, 4)
OriginalSn string ` json:"original_sn" ` // 首次入库订单编号
StorageType uint32 ` json:"storage_type" ` // 首次入库方式: 1-系统入库 2-采购入库
StockTimeStart string ` json:"stock_time_start" ` // 最近入库开始时间
StockTimeEnd string ` json:"stock_time_end" ` // 最近入库结束时间
Age uint32 ` json:"age" ` // 最近库龄
AllAge uint32 ` json:"all_age" ` // 总库龄
PageIndex int ` json:"pageIndex" ` // 页码
PageSize int ` json:"pageSize" ` // 每页展示数据条数
IsExport uint32 ` json:"is_export" ` // 是否导出excel: 1-导出
StockSortFlag uint32 ` json:"stock_sort_flag" ` // 排序方式: 0-按入库时间降序排列( 默认) , 1-按入库时间升序排列
//Sn string `json:"sn"` // 首次入库订单编号
}
2023-11-24 09:09:24 +00:00
// ErpStockCommodityListResp 库存详情接口响应参数
2023-11-08 03:51:33 +00:00
type ErpStockCommodityListResp struct {
2023-12-19 10:21:44 +00:00
List [ ] ErpStockCommodity ` json:"list" `
2024-02-02 06:33:45 +00:00
Total int ` json:"total" ` // 数据总条数
2023-12-19 10:21:44 +00:00
PageIndex int ` json:"pageIndex" ` // 页码
PageSize int ` json:"pageSize" ` // 每页展示条数
2024-09-18 09:11:39 +00:00
TotalWholesalePrice float64 ` json:"total_wholesale_price" ` // 入库采购价之和
TotalStaffPrice float64 ` json:"total_staff_price" ` // 入库员工成本价之和
2023-12-19 10:21:44 +00:00
ExportUrl string ` json:"export_url" `
2023-11-08 03:51:33 +00:00
}
2023-11-24 09:09:24 +00:00
// GetDetailList 查看库存详情
2024-07-01 01:44:35 +00:00
func ( m * ErpStockCommodityListReq ) GetDetailList ( c * gin . Context , nType uint32 ) ( * ErpStockCommodityListResp , error ) {
2023-11-08 03:51:33 +00:00
resp := & ErpStockCommodityListResp {
2023-11-28 09:33:38 +00:00
PageIndex : m . PageIndex ,
PageSize : m . PageSize ,
2023-11-08 03:51:33 +00:00
}
2023-11-28 09:33:38 +00:00
page := m . PageIndex - 1
2023-11-08 03:51:33 +00:00
if page < 0 {
page = 0
}
if m . PageSize == 0 {
m . PageSize = 10
}
2023-11-16 10:09:11 +00:00
2023-12-11 08:21:21 +00:00
if m . ErpStockId != 0 {
updateCommodityStock ( m . ErpStockId ) // 同步详情表的库存id
}
// 出库数据不查询
2024-01-06 08:48:35 +00:00
qs := orm . Eloquent . Table ( "erp_stock_commodity" )
2023-11-16 10:09:11 +00:00
2024-04-17 09:44:43 +00:00
// 非管理员才判断所属门店
if ! ( tools . GetRoleName ( c ) == "admin" || tools . GetRoleName ( c ) == "系统管理员" ) {
sysUser , err := GetSysUserByCtx ( c )
if err != nil {
return nil , err
}
// 返回sysUser未过期的门店id列表
storeList := GetValidStoreIDs ( sysUser . StoreData )
if m . StoreId != 0 {
if ! Contains ( storeList , m . StoreId ) {
return nil , errors . New ( "您没有该门店权限" )
}
} else {
if len ( storeList ) > 0 {
2024-05-27 11:01:04 +00:00
if len ( storeList ) == 1 {
qs = qs . Where ( "store_id = ?" , storeList [ 0 ] )
} else {
qs = qs . Where ( "store_id IN (?)" , storeList )
}
2024-04-17 09:44:43 +00:00
} else {
return nil , errors . New ( "用户未绑定门店" )
}
}
}
2023-11-16 10:09:11 +00:00
// 构建查询条件
2024-07-01 01:44:35 +00:00
m . buildQueryConditions ( qs , nType )
2023-12-19 10:21:44 +00:00
es := qs
2023-11-16 10:09:11 +00:00
var count int64
if err := qs . Count ( & count ) . Error ; err != nil {
2023-12-05 09:21:11 +00:00
logger . Error ( "count err:" , logger . Field ( "err" , err ) )
2023-11-16 10:09:11 +00:00
return resp , err
}
2023-12-19 10:21:44 +00:00
nTotalCount := & struct {
2024-04-17 01:37:02 +00:00
TotalWholesalePrice float64 ` json:"total_wholesale_price" `
TotalStaffCostPrice float64 ` json:"total_staff_cost_price" `
2023-12-19 10:21:44 +00:00
} { }
err := es . Debug ( ) . Select ( "SUM(wholesale_price) as total_wholesale_price, SUM(staff_cost_price) as total_staff_cost_price" ) .
Scan ( & nTotalCount ) . Error
if err != nil {
logger . Error ( "count err:" , logger . Field ( "err" , err ) )
return resp , err
}
2023-11-16 10:09:11 +00:00
//获取库存商品列表
var commodities [ ] ErpStockCommodity
if m . IsExport == 1 {
2024-07-10 07:24:34 +00:00
err := qs . Find ( & commodities ) . Order ( "stock_time DESC,id DESC" ) . Error
2023-11-16 10:09:11 +00:00
if err != nil && ! errors . Is ( err , RecordNotFound ) {
2024-07-12 07:54:31 +00:00
logger . Error ( "find err:" , logger . Field ( "err" , err ) )
2023-11-16 10:09:11 +00:00
return resp , err
}
2024-03-27 10:01:38 +00:00
ErpStockCommodityListSetAge ( commodities )
2024-07-22 02:39:22 +00:00
listExport , err := InventoryDetailListExport ( commodities , c )
2023-11-23 12:38:11 +00:00
if err != nil {
//logger.Error("list export err:", err)
}
resp . ExportUrl = listExport
2023-11-16 10:09:11 +00:00
} else {
2024-07-10 07:24:34 +00:00
if m . StockSortFlag == 1 {
err = qs . Offset ( page * m . PageSize ) . Limit ( m . PageSize ) . Order ( "stock_time ASC,id ASC" ) . Find ( & commodities ) . Error
} else {
err = qs . Offset ( page * m . PageSize ) . Limit ( m . PageSize ) . Order ( "stock_time DESC,id DESC" ) . Find ( & commodities ) . Error
}
2023-11-16 10:09:11 +00:00
if err != nil && ! errors . Is ( err , RecordNotFound ) {
//logger.Error("erp commodity list err:", err)
return resp , err
}
ErpStockCommodityListSetAge ( commodities )
2024-09-22 03:15:44 +00:00
ErpStockCommodityListSetCategoryNumber ( commodities )
2023-11-16 10:09:11 +00:00
resp . List = commodities
}
2024-05-10 01:54:37 +00:00
if len ( commodities ) == 1 && commodities [ 0 ] . State == InAllot && m . ScanCode != "" {
return nil , errors . New ( "该商品在调拨中" )
}
2023-11-28 09:33:38 +00:00
//跟之前保持一致
resp . Total = int ( count )
resp . PageIndex = page + 1
resp . PageSize = m . PageSize
2024-09-18 09:11:39 +00:00
resp . TotalWholesalePrice = math . Round ( nTotalCount . TotalWholesalePrice * 100 ) / 100
resp . TotalStaffPrice = math . Round ( ( nTotalCount . TotalStaffCostPrice + nTotalCount . TotalWholesalePrice ) * 100 ) / 100
2023-11-28 09:33:38 +00:00
2023-11-16 10:09:11 +00:00
return resp , nil
}
2024-11-20 08:17:53 +00:00
// GetDetailListNew 查看库存详情
func ( m * NewErpStockCommodityListReq ) GetDetailListNew ( c * gin . Context ) ( * ErpStockCommodityListResp , error ) {
resp := & ErpStockCommodityListResp {
PageIndex : m . PageIndex ,
PageSize : m . PageSize ,
}
page := m . PageIndex - 1
if page < 0 {
page = 0
}
if m . PageSize == 0 {
m . PageSize = 10
}
if m . ErpStockId != 0 {
updateCommodityStock ( m . ErpStockId ) // 同步详情表的库存id
}
// 出库数据不查询
qs := orm . Eloquent . Table ( "erp_stock_commodity" )
// 非管理员才判断所属门店
if ! ( tools . GetRoleName ( c ) == "admin" || tools . GetRoleName ( c ) == "系统管理员" ) {
sysUser , err := GetSysUserByCtx ( c )
if err != nil {
return nil , err
}
// 返回sysUser未过期的门店id列表
storeList := GetValidStoreIDs ( sysUser . StoreData )
if len ( m . StoreId ) != 0 {
if len ( CompareLists ( storeList , m . StoreId ) ) == 0 {
return nil , errors . New ( "您没有该门店权限" )
}
} else {
if len ( storeList ) > 0 {
if len ( storeList ) == 1 {
qs = qs . Where ( "store_id = ?" , storeList [ 0 ] )
} else {
qs = qs . Where ( "store_id IN (?)" , storeList )
}
} else {
return nil , errors . New ( "用户未绑定门店" )
}
}
}
// 构建查询条件
m . buildQueryConditionsNew ( qs )
es := qs
var count int64
if err := qs . Count ( & count ) . Error ; err != nil {
logger . Error ( "count err:" , logger . Field ( "err" , err ) )
return resp , err
}
nTotalCount := & struct {
TotalWholesalePrice float64 ` json:"total_wholesale_price" `
TotalStaffCostPrice float64 ` json:"total_staff_cost_price" `
} { }
err := es . Debug ( ) . Select ( "SUM(wholesale_price) as total_wholesale_price, SUM(staff_cost_price) as total_staff_cost_price" ) .
Scan ( & nTotalCount ) . Error
if err != nil {
logger . Error ( "count err:" , logger . Field ( "err" , err ) )
return resp , err
}
//获取库存商品列表
var commodities [ ] ErpStockCommodity
if m . IsExport == 1 {
err := qs . Find ( & commodities ) . Order ( "stock_time DESC,id DESC" ) . Error
if err != nil && ! errors . Is ( err , RecordNotFound ) {
logger . Error ( "find err:" , logger . Field ( "err" , err ) )
return resp , err
}
ErpStockCommodityListSetAge ( commodities )
listExport , err := InventoryDetailListExport ( commodities , c )
if err != nil {
//logger.Error("list export err:", err)
}
resp . ExportUrl = listExport
} else {
if m . StockSortFlag == 1 {
err = qs . Offset ( page * m . PageSize ) . Limit ( m . PageSize ) . Order ( "stock_time ASC,id ASC" ) . Find ( & commodities ) . Error
} else {
err = qs . Offset ( page * m . PageSize ) . Limit ( m . PageSize ) . Order ( "stock_time DESC,id DESC" ) . Find ( & commodities ) . Error
}
if err != nil && ! errors . Is ( err , RecordNotFound ) {
//logger.Error("erp commodity list err:", err)
return resp , err
}
ErpStockCommodityListSetAge ( commodities )
ErpStockCommodityListSetCategoryNumber ( commodities )
resp . List = commodities
}
if len ( commodities ) == 1 && commodities [ 0 ] . State == InAllot && m . ScanCode != "" {
return nil , errors . New ( "该商品在调拨中" )
}
//跟之前保持一致
resp . Total = int ( count )
resp . PageIndex = page + 1
resp . PageSize = m . PageSize
resp . TotalWholesalePrice = math . Round ( nTotalCount . TotalWholesalePrice * 100 ) / 100
resp . TotalStaffPrice = math . Round ( ( nTotalCount . TotalStaffCostPrice + nTotalCount . TotalWholesalePrice ) * 100 ) / 100
return resp , nil
}
// buildQueryConditions 根据请求参数构建查询条件
func ( m * NewErpStockCommodityListReq ) buildQueryConditionsNew ( qs * gorm . DB ) {
if m . ScanCode != "" {
qs = qs . Where ( "erp_barcode = ? or imei = ?" , m . ScanCode , m . ScanCode )
qs = qs . Where ( "state in (?)" , [ ] uint32 { InStock , InAllot } )
} else {
qs = qs . Where ( "state in (?)" , [ ] uint32 { InStock , InAllot } )
if m . ErpStockId != 0 { //库存id
qs = qs . Where ( "erp_stock_id=?" , m . ErpStockId )
}
if m . ErpCommodityId != 0 { //商品id
qs = qs . Where ( "erp_commodity_id=?" , m . ErpCommodityId )
}
if m . IsIMEI != 0 { // 是否串码
if m . IsIMEI == 1 { // 查串码数据
qs = qs . Where ( "imei_type != ?" , NoIMEICommodity )
} else if m . IsIMEI == 2 { // 查非串码数据
qs = qs . Where ( "imei_type = ?" , NoIMEICommodity )
}
}
if m . SerialNumber != "" { //商品编号
qs = qs . Where ( "commodity_serial_number=?" , m . SerialNumber )
}
if len ( m . CommodityName ) != 0 { //商品名称
qs = qs . Where ( "erp_commodity_name IN (?)" , m . CommodityName )
}
if m . ErpCategoryId != 0 { //商品分类id
categoryList , _ := GetSubcategoryIds ( m . ErpCategoryId )
if categoryList == nil {
categoryList = append ( categoryList , m . ErpCategoryId )
}
qs = qs . Where ( "erp_category_id in ?" , categoryList )
}
if m . IMEI != "" { //商品串码
qs = qs . Where ( "imei=?" , m . IMEI )
}
if len ( m . StoreId ) != 0 { //门店编号
qs = qs . Where ( "store_id in ?" , m . StoreId )
}
if m . SupplierId != 0 { //供应商id
qs = qs . Where ( "erp_supplier_id=?" , m . SupplierId )
}
defaultStates := [ ] int { 1 , 4 }
if len ( m . State ) != 0 {
if len ( m . State ) == 1 {
qs = qs . Where ( "state = ?" , m . State [ 0 ] )
} else {
qs = qs . Where ( "state IN (?)" , m . State )
}
} else {
qs = qs . Where ( "state IN (?)" , defaultStates )
}
if m . OriginalSn != "" { //首次入库订单编号
qs = qs . Where ( "original_sn=?" , m . OriginalSn )
}
if m . StorageType != 0 { //首次入库方式
qs = qs . Where ( "storage_type=?" , m . StorageType )
}
if m . StockTimeStart != "" { //最近入库开始时间
startTime , err := time . Parse ( QueryTimeFormat , m . StockTimeStart )
if err == nil {
qs = qs . Where ( "stock_time>?" , startTime )
} else {
//logger.Error("stock time start parse err:", err)
}
}
if m . StockTimeEnd != "" { //最近入库结束时间
endTime , err := time . Parse ( QueryTimeFormat , m . StockTimeEnd )
if err == nil {
qs = qs . Where ( "stock_time<?" , endTime )
} else {
//logger.Error("stock time end parse err:", err)
}
}
if m . Age != 0 { //最近库龄
qs = qs . Where ( "stock_time<?" , time . Now ( ) . AddDate ( 0 , 0 , int ( m . Age ) * ( - 1 ) ) )
}
if m . AllAge != 0 { //总库龄
qs = qs . Where ( "first_stock_time<?" , time . Now ( ) . AddDate ( 0 , 0 , int ( m . AllAge ) * ( - 1 ) ) )
}
}
}
2024-07-01 01:44:35 +00:00
// RemoveDuplicates 去除重复数据,只保留 FirstStockTime 最久的记录
func RemoveDuplicates ( resp * ErpStockCommodityListResp ) ( * ErpStockCommodityListResp , error ) {
uniqueItems := make ( map [ string ] ErpStockCommodity )
for _ , item := range resp . List {
if existing , found := uniqueItems [ item . ErpCommodityName ] ; found {
if item . FirstStockTime . Before ( existing . FirstStockTime ) {
uniqueItems [ item . ErpCommodityName ] = item
}
} else {
uniqueItems [ item . ErpCommodityName ] = item
}
}
// 转换回列表
var newList [ ] ErpStockCommodity
for _ , item := range uniqueItems {
//if len(uniqueItems) == 1 && item.IMEIType != 1{
// return nil, errors.New("串码商品请扫串码")
//}
if item . IMEIType != 1 {
continue
}
newList = append ( newList , item )
}
// 更新响应结构体
resp . List = newList
resp . Total = len ( newList )
resp . TotalWholesalePrice = 0
resp . TotalStaffPrice = 0
return resp , nil
}
2024-05-23 07:30:20 +00:00
func CheckScanCodeResp ( scanCode string , storeId uint32 , req * ErpStockCommodityListResp ) error {
2024-01-06 08:48:35 +00:00
if req . Total == 1 { // 串码商品, 只有1个; 条码商品, 刚好也只有1个
if req . List [ 0 ] . IMEI == scanCode { // 串码商品, 只有1个
2024-05-23 07:30:20 +00:00
if req . List [ 0 ] . StoreId != storeId && storeId != 0 {
return errors . New ( req . List [ 0 ] . ErpCommodityName + "商品非所选门店库存,请检查" )
}
2024-01-06 08:48:35 +00:00
return nil
}
if req . List [ 0 ] . ErpBarcode == scanCode && req . List [ 0 ] . IMEI != "" {
return errors . New ( "串码类商品,请直接输入串码" )
}
} else { // 条码商品,数量多
var barCodeList [ ] ErpStockCommodity
var imeiLst [ ] ErpStockCommodity
for _ , item := range req . List {
if item . ErpBarcode == scanCode { // 扫码跟商品条码匹配
flag := false
for _ , barCode := range barCodeList {
if barCode . ErpBarcode == item . ErpBarcode {
flag = true
break
}
}
if ! flag { // 遍历后不存在则添加
barCodeList = append ( barCodeList , item )
}
}
if item . IMEI == scanCode { // 扫码跟商品串码匹配
flag := false
for _ , barCode := range imeiLst {
if barCode . IMEI == item . IMEI {
flag = true
break
}
}
if ! flag { // 遍历后不存在则添加
imeiLst = append ( imeiLst , item )
}
}
}
2024-07-01 01:44:35 +00:00
// 查询的数据是条码,但是条码对应的商品是串码商品
if len ( barCodeList ) == 1 && len ( imeiLst ) == 0 {
if barCodeList [ 0 ] . ErpBarcode == scanCode && barCodeList [ 0 ] . IMEI != "" {
return errors . New ( "串码类商品,请直接输入串码" )
}
}
2024-01-06 08:48:35 +00:00
req . List = nil
if len ( barCodeList ) > 0 {
req . List = append ( req . List , barCodeList [ 0 ] )
}
if len ( imeiLst ) > 0 {
req . List = append ( req . List , imeiLst [ 0 ] )
}
req . Total = len ( req . List )
req . TotalStaffPrice = 0
req . TotalWholesalePrice = 0
}
return nil
}
2024-03-16 08:19:12 +00:00
// contains 函数用于检查一个整数切片中是否包含某个值
func contains ( s [ ] int , e int ) bool {
for _ , a := range s {
if a == e {
return true
}
}
return false
}
2023-11-16 10:09:11 +00:00
// buildQueryConditions 根据请求参数构建查询条件
2024-07-01 01:44:35 +00:00
func ( m * ErpStockCommodityListReq ) buildQueryConditions ( qs * gorm . DB , nType uint32 ) {
2024-01-06 08:48:35 +00:00
if m . ScanCode != "" {
qs = qs . Where ( "erp_barcode = ? or imei = ?" , m . ScanCode , m . ScanCode )
2024-05-10 01:54:37 +00:00
qs = qs . Where ( "state in (?)" , [ ] uint32 { InStock , InAllot } )
2024-01-06 08:48:35 +00:00
} else {
2024-04-29 10:10:48 +00:00
qs = qs . Where ( "state in (?)" , [ ] uint32 { InStock , InAllot } )
2024-01-06 08:48:35 +00:00
if m . ErpStockId != 0 { //库存id
qs = qs . Where ( "erp_stock_id=?" , m . ErpStockId )
}
2023-11-16 10:09:11 +00:00
2024-01-06 08:48:35 +00:00
if m . ErpCommodityId != 0 { //商品id
qs = qs . Where ( "erp_commodity_id=?" , m . ErpCommodityId )
}
2023-11-16 10:09:11 +00:00
2024-01-06 08:48:35 +00:00
if m . IsIMEI != 0 { // 是否串码
if m . IsIMEI == 1 { // 查串码数据
qs = qs . Where ( "imei_type != ?" , NoIMEICommodity )
} else if m . IsIMEI == 2 { // 查非串码数据
qs = qs . Where ( "imei_type = ?" , NoIMEICommodity )
}
2023-12-27 11:23:03 +00:00
}
2024-01-06 08:48:35 +00:00
if m . SerialNumber != "" { //商品编号
qs = qs . Where ( "commodity_serial_number=?" , m . SerialNumber )
}
2023-11-16 10:09:11 +00:00
2024-07-12 01:39:14 +00:00
if len ( m . CommodityName ) != 0 { //商品名称
2024-07-01 01:44:35 +00:00
if nType == 1 {
2024-07-12 01:39:14 +00:00
qs = qs . Where ( "erp_commodity_name IN (?)" , m . CommodityName )
2024-07-01 01:44:35 +00:00
} else {
2024-07-12 01:39:14 +00:00
qs = qs . Where ( "erp_commodity_name like ?" , "%" + m . CommodityName [ 0 ] + "%" )
2024-07-01 01:44:35 +00:00
}
2024-01-06 08:48:35 +00:00
}
2023-11-16 10:09:11 +00:00
2024-01-06 08:48:35 +00:00
if m . ErpCategoryId != 0 { //商品分类id
2024-11-06 10:38:41 +00:00
categoryList , _ := GetSubcategoryIds ( m . ErpCategoryId )
if categoryList == nil {
categoryList = append ( categoryList , m . ErpCategoryId )
}
qs = qs . Where ( "erp_category_id in ?" , categoryList )
2024-01-06 08:48:35 +00:00
}
2023-11-16 10:09:11 +00:00
2024-01-06 08:48:35 +00:00
if m . IMEI != "" { //商品串码
qs = qs . Where ( "imei=?" , m . IMEI )
}
2023-11-16 10:09:11 +00:00
2024-01-06 08:48:35 +00:00
if m . StoreId != 0 { //门店编号
qs = qs . Where ( "store_id=?" , m . StoreId )
}
2023-11-16 10:09:11 +00:00
2024-01-06 08:48:35 +00:00
if m . SupplierId != 0 { //供应商id
qs = qs . Where ( "erp_supplier_id=?" , m . SupplierId )
}
2023-11-24 09:09:24 +00:00
2024-03-16 08:19:12 +00:00
defaultStates := [ ] int { 1 , 4 }
2024-07-01 01:44:35 +00:00
if len ( m . State ) != 0 {
if len ( m . State ) == 1 {
qs = qs . Where ( "state = ?" , m . State [ 0 ] )
} else {
qs = qs . Where ( "state IN (?)" , m . State )
}
2024-03-16 08:19:12 +00:00
} else {
qs = qs . Where ( "state IN (?)" , defaultStates )
2024-01-06 08:48:35 +00:00
}
2023-11-16 10:09:11 +00:00
2024-04-22 01:51:41 +00:00
if m . OriginalSn != "" { //首次入库订单编号
qs = qs . Where ( "original_sn=?" , m . OriginalSn )
2024-01-06 08:48:35 +00:00
}
2023-11-16 10:09:11 +00:00
2024-01-06 08:48:35 +00:00
if m . StorageType != 0 { //首次入库方式
qs = qs . Where ( "storage_type=?" , m . StorageType )
}
2023-11-16 10:09:11 +00:00
2024-01-06 08:48:35 +00:00
if m . StockTimeStart != "" { //最近入库开始时间
startTime , err := time . Parse ( QueryTimeFormat , m . StockTimeStart )
if err == nil {
qs = qs . Where ( "stock_time>?" , startTime )
} else {
//logger.Error("stock time start parse err:", err)
}
2023-11-08 03:51:33 +00:00
}
2023-11-16 10:09:11 +00:00
2024-01-06 08:48:35 +00:00
if m . StockTimeEnd != "" { //最近入库结束时间
endTime , err := time . Parse ( QueryTimeFormat , m . StockTimeEnd )
if err == nil {
qs = qs . Where ( "stock_time<?" , endTime )
} else {
//logger.Error("stock time end parse err:", err)
}
2023-11-08 03:51:33 +00:00
}
2023-11-16 10:09:11 +00:00
2024-01-06 08:48:35 +00:00
if m . Age != 0 { //最近库龄
qs = qs . Where ( "stock_time<?" , time . Now ( ) . AddDate ( 0 , 0 , int ( m . Age ) * ( - 1 ) ) )
}
2023-11-08 03:51:33 +00:00
2024-01-06 08:48:35 +00:00
if m . AllAge != 0 { //总库龄
qs = qs . Where ( "first_stock_time<?" , time . Now ( ) . AddDate ( 0 , 0 , int ( m . AllAge ) * ( - 1 ) ) )
}
2023-11-08 03:51:33 +00:00
}
}
2023-11-17 10:07:01 +00:00
2023-11-24 09:09:24 +00:00
// SetStockCommodityState 更新库存状态
2024-06-05 02:50:15 +00:00
func SetStockCommodityState ( c * gin . Context , id uint32 ) error { //更新库存状态为5, 并同步扣减库存数量
2023-12-11 08:21:21 +00:00
begin := orm . Eloquent . Begin ( )
// 查询库存详情
var commodityInfo ErpStockCommodity
err := orm . Eloquent . Table ( "erp_stock_commodity" ) .
Raw ( "SELECT * FROM erp_stock_commodity WHERE id = ?" , id ) .
Scan ( & commodityInfo ) . Error
if err != nil {
logger . Error ( "查询库存商品信息失败" , logger . Field ( "err" , err ) )
return err
2023-11-17 10:07:01 +00:00
}
2023-12-11 08:21:21 +00:00
2024-06-05 02:50:15 +00:00
// 校验是否有入参门店权限
err = AuthUserStore ( c , commodityInfo . StoreId )
if err != nil {
return err
}
2023-12-11 08:21:21 +00:00
// 查询库存数据
var record ErpStock
err = orm . Eloquent . Table ( "erp_stock" ) .
Where ( "erp_commodity_name = ? and store_id = ?" ,
commodityInfo . ErpCommodityName , commodityInfo . StoreId ) . First ( & record ) . Error
if err != nil {
logger . Error ( "查询库存数量失败" , logger . Field ( "err" , err ) )
return err
}
2024-04-29 10:10:48 +00:00
// 更新商品库存详情表状态为:系统出库
2023-12-11 08:21:21 +00:00
if err := begin . Model ( & ErpStockCommodity { } ) . Where ( "id=?" , id ) . Updates ( map [ string ] interface { } {
2024-08-15 03:50:53 +00:00
"state" : SystemOut ,
"updated_at" : time . Now ( ) ,
} ) . Error ; err != nil {
2023-11-17 10:07:01 +00:00
return fmt . Errorf ( "[update err]: %v" , err )
}
2023-12-11 08:21:21 +00:00
if record . Count > 0 {
// 扣减商品库存数量
err = begin . Model ( & record ) . Update ( "count" , record . Count - 1 ) . Error
if err != nil {
logger . Error ( "扣减库存数量失败" , logger . Field ( "err" , err ) )
return err
}
}
err = begin . Commit ( ) . Error
if err != nil {
begin . Rollback ( )
logger . Error ( "出库事务失败" , logger . Field ( "err" , err ) )
return err
}
2023-11-17 10:07:01 +00:00
return nil
}
type BatchPrintInfo struct {
ErpCommodityName string ` json:"erp_commodity_name" binding:"required" ` // 商品名称
RetailPrice uint32 ` json:"retail_price" binding:"required" ` // 指导零售价
IMEI string ` json:"imei" binding:"required" ` // 商品串码
}
type BatchPrintInfoReq struct {
PrintListInfo [ ] * BatchPrintInfo ` json:"print_list_info" binding:"required" `
}
2023-11-24 09:09:24 +00:00
// BatchPrint 批量打印标签
2023-11-17 10:07:01 +00:00
func BatchPrint ( req * BatchPrintInfoReq ) error {
return nil
}
func StringToFloat ( req string ) ( float64 , error ) {
if req == "" {
return 0 , nil
}
return strconv . ParseFloat ( req , 64 )
}
2023-11-23 12:38:11 +00:00
2024-04-17 01:37:02 +00:00
func PercentFloatStringToFloat64 ( s string ) float64 {
u := float64 ( 0 )
2023-11-24 09:09:24 +00:00
if s != "" {
s = strings . ReplaceAll ( s , "%" , "" )
}
f , err := strconv . ParseFloat ( s , 64 )
if err != nil {
//logger.Error("parse float err:", err)
return u
}
2024-04-17 01:37:02 +00:00
u = f * 100
return tools . RoundToTwoDecimalPlaces ( u )
2023-11-24 09:09:24 +00:00
}
func IntStringToUin32 ( s string ) uint32 {
u := uint32 ( 0 )
if s != "" {
s = strings . ReplaceAll ( s , "%" , "" )
}
i , err := strconv . Atoi ( s )
if err != nil {
//logger.Error("parse float err:", err)
return u
}
u = uint32 ( i )
return u
2023-11-23 12:38:11 +00:00
}
func NewStockImporter ( ) * StockImporter {
return & StockImporter {
CensusMap : make ( map [ uint32 ] map [ uint32 ] uint32 , 0 ) ,
CommodityMap : make ( map [ uint32 ] * ErpCommodity ) ,
StoreMap : make ( map [ uint32 ] string , 0 ) ,
Inventories : make ( [ ] * ErpInventoryStock , 0 ) ,
}
}
2023-11-24 09:09:24 +00:00
// UpdateStockCommodityRemark 更新库存商品备注信息
func UpdateStockCommodityRemark ( id int , remark string ) error {
if remark == "" {
return nil
}
if err := orm . Eloquent . Model ( & ErpStockCommodity { } ) . Where ( "id=?" , id ) . Updates ( map [ string ] interface { } {
"remark" : remark } ) . Error ; err != nil {
return fmt . Errorf ( "[update err]: %v" , err )
}
return nil
}
2024-01-06 08:48:35 +00:00
func GetCommodity ( id uint32 ) ( * ErpCommodity , error ) {
var erpCommodity ErpCommodity
err := orm . Eloquent . Table ( "erp_commodity" ) . Where ( "id=?" , id ) . Find ( & erpCommodity ) . Error
if err != nil {
logger . Errorf ( "err:" , logger . Field ( "err" , err ) )
return & erpCommodity , err
}
return & erpCommodity , nil
}
// CheckAndConvertBarcode 校验输入的条码数据是否正确
func CheckAndConvertBarcode ( input string ) ( string , error ) {
// 1. 检查总长度不超过100字符
if utf8 . RuneCountInString ( input ) > 100 {
return "" , errors . New ( "error: Total length exceeds 100 characters" )
}
// 2. 转换中文逗号为英文逗号
input = strings . ReplaceAll ( input , ", " , "," )
// 3. 两个逗号之前需要有数据,不能是空格或无数据
parts := strings . Split ( input , "," )
for _ , part := range parts {
trimmedPart := strings . TrimSpace ( part )
if trimmedPart == "" {
return "" , errors . New ( "error: Two commas should have data in between" )
}
}
// 4.判断逗号隔开的数据数据库是否已存在
for _ , part := range parts {
// 检查生成的条码是否已存在
2024-07-12 07:54:31 +00:00
exist , err := QueryRecordExist ( fmt . Sprintf ( "SELECT * FROM erp_commodity WHERE FIND_IN_SET('%s', erp_barcode) > 0" , part ) )
2024-01-06 08:48:35 +00:00
if err != nil {
logger . Error ( "exist sn err" )
}
if exist {
return "" , errors . New ( "[" + part + "]" + "该条码已存在,请检查" )
}
}
// 如果通过所有检查,返回处理后的字符串
return input , nil
}
2024-02-05 06:11:48 +00:00
// CheckBarcodeById 校验输入的条码数据是否正确
func CheckBarcodeById ( input string , commodityId uint32 ) ( string , error ) {
// 1. 检查总长度不超过100字符
if utf8 . RuneCountInString ( input ) > 100 {
return "" , errors . New ( "error: Total length exceeds 100 characters" )
}
// 2. 转换中文逗号为英文逗号
input = strings . ReplaceAll ( input , ", " , "," )
// 3. 两个逗号之前需要有数据,不能是空格或无数据
parts := strings . Split ( input , "," )
for _ , part := range parts {
trimmedPart := strings . TrimSpace ( part )
if trimmedPart == "" {
return "" , errors . New ( "error: Two commas should have data in between" )
}
}
// 4.判断逗号隔开的数据数据库是否已存在
for _ , part := range parts {
// 检查生成的条码是否已存在
2024-07-12 07:54:31 +00:00
exist , err := QueryRecordExist ( fmt . Sprintf ( "SELECT * FROM erp_commodity WHERE FIND_IN_SET('%s', erp_barcode) > 0" , part ) )
2024-02-05 06:11:48 +00:00
if err != nil {
logger . Error ( "exist sn err" )
}
if exist {
var commodityInfo ErpCommodity
err = orm . Eloquent . Table ( "erp_commodity" ) . Where ( "id=?" , commodityId ) . Find ( & commodityInfo ) . Error
if err != nil {
logger . Errorf ( "get erp_commodity err:" , err )
return "" , err
}
if commodityInfo . ErpBarcode == input {
return input , nil
} else {
return "" , errors . New ( "[" + part + "]" + "该条码已存在,请检查" )
}
}
}
// 如果通过所有检查,返回处理后的字符串
return input , nil
}
2024-01-06 08:48:35 +00:00
// GenerateBarcode 系统生成条码
func GenerateBarcode ( categoryCode uint32 ) ( string , error ) {
category := new ( Category )
err := orm . Eloquent . Table ( "erp_category" ) . Where ( "id=?" , categoryCode ) . Find ( category ) . Error
if err != nil {
logger . Errorf ( "get erp category err:" , err )
return "" , err
}
max := 1
for {
if max > 5 {
logger . Error ( "create Barcode err" )
return "" , errors . New ( "create Barcode err" )
}
// 生成当前日期的六位数
dateCode := time . Now ( ) . Format ( "060102" )
// 生成三位随机数
randomNumber := fmt . Sprintf ( "%03d" , rand . Intn ( 1000 ) )
// 组合生成的条码
barcode := fmt . Sprintf ( "%03s%s%s" , category . Number [ : 3 ] , dateCode , randomNumber )
// 检查生成的条码是否已存在
2024-07-12 07:54:31 +00:00
exist , err := QueryRecordExist ( fmt . Sprintf ( "SELECT * FROM erp_commodity WHERE FIND_IN_SET('%s', erp_barcode) > 0" , barcode ) )
2024-01-06 08:48:35 +00:00
if err != nil {
logger . Error ( "exist sn err" )
}
if ! exist {
return barcode , nil
}
}
}
// GetCodeList 查询输入的条码或串码数据
func GetCodeList ( req * QueryCodeReq ) ( * QueryCodeResp , error ) {
resp := & QueryCodeResp {
PageIndex : req . PageIndex ,
PageSize : req . PageSize ,
}
page := req . PageIndex - 1
if page < 0 {
page = 0
}
if req . PageSize == 0 {
req . PageSize = 10
}
var commodities [ ] ErpStockCommodity
orderStr := fmt . Sprintf ( "CASE WHEN imei LIKE '%%%s%%' THEN 1 ELSE 2 END" , req . ScanCode )
2024-07-01 01:44:35 +00:00
qs := orm . Eloquent . Debug ( ) . Table ( "erp_stock_commodity" )
qs = qs . Where ( "imei LIKE ? OR erp_barcode LIKE ?" , "%" + req . ScanCode + "%" , "%" + req . ScanCode + "%" )
2024-01-31 10:00:16 +00:00
2024-06-20 06:32:03 +00:00
if req . State != 0 {
qs = qs . Where ( "state = ?" , req . State )
}
if req . StoreId != 0 {
qs = qs . Where ( "store_id = ?" , req . StoreId )
}
2024-01-06 08:48:35 +00:00
es := qs
err := qs . Order ( orderStr ) . Offset ( page * req . PageSize ) . Limit ( req . PageSize ) . Find ( & commodities ) . Error
if err != nil && err != RecordNotFound {
logger . Error ( "commodityList err" , logger . Field ( "err" , err ) )
return resp , err
}
var count int64
err = es . Count ( & count ) . Error
if err != nil {
logger . Error ( "commodityList count err" , logger . Field ( "err" , err ) )
return resp , err
}
var stockList [ ] string
var strCode string
for _ , commodity := range commodities {
if commodity . IMEI != "" && strings . Contains ( commodity . IMEI , req . ScanCode ) { // 串码非空且包含查找的数据
strCode = commodity . IMEI
2024-05-10 01:54:37 +00:00
//} else if commodity.IMEI != "" && strings.Contains(commodity.ErpBarcode, req.ScanCode) { // 串码不为空,但条码包含扫码数据
} else if commodity . IMEI != "" && commodity . ErpBarcode == req . ScanCode { // 串码不为空,但条码包含扫码数据
2024-01-31 10:00:16 +00:00
return nil , errors . New ( "串码类商品请直接输入串码" )
} else {
2024-01-06 08:48:35 +00:00
strCode = commodity . ErpBarcode
}
stockList = append ( stockList , strCode )
}
//跟之前保持一致
resp . Total = len ( stockList )
resp . PageIndex = page + 1
resp . PageSize = req . PageSize
resp . List = stockList
2024-03-16 08:19:12 +00:00
return removeDuplicates ( resp ) , nil
}
func removeDuplicates ( resp * QueryCodeResp ) * QueryCodeResp {
// 创建一个 map 用来记录已经出现过的字符串
uniqueMap := make ( map [ string ] bool )
// 新建一个切片用来保存不重复的数据
var uniqueList [ ] string
// 遍历原始的 List
for _ , item := range resp . List {
// 如果这个字符串已经在 map 中存在,说明重复,跳过
if _ , ok := uniqueMap [ item ] ; ok {
continue
}
// 否则,将其添加到新的切片中,并在 map 中标记为已经出现过
uniqueList = append ( uniqueList , item )
uniqueMap [ item ] = true
}
// 构建新的 QueryCodeResp 结构体
newResp := & QueryCodeResp {
List : uniqueList ,
Total : len ( uniqueList ) ,
PageIndex : resp . PageIndex ,
PageSize : resp . PageSize ,
}
return newResp
2024-01-06 08:48:35 +00:00
}
2024-02-20 09:59:43 +00:00
func GetErpCommodityMap ( ids [ ] uint32 ) ( map [ uint32 ] ErpCommodity , error ) {
commodityMap := make ( map [ uint32 ] ErpCommodity , 0 )
if len ( ids ) == 0 {
return commodityMap , nil
}
var commodities [ ] ErpCommodity
err := orm . Eloquent . Table ( "erp_commodity" ) . Where ( "id IN (?)" , ids ) . Find ( & commodities ) . Error
if err != nil {
logger . Error ( "commodities err:" , logger . Field ( "err" , err ) )
return commodityMap , err
}
for i , _ := range commodities {
commodityMap [ commodities [ i ] . ID ] = commodities [ i ]
}
return commodityMap , nil
}
2024-04-22 01:51:41 +00:00
type CommodityCreateRequest struct {
Name string ` json:"name" binding:"required" ` // 商品名称
ErpCategoryId uint32 ` json:"erp_category_id" binding:"required" ` // 商品分类id
IsIMEI uint32 ` json:"is_imei" binding:"required" ` // 是否串码: 1-串码类 2-非串码
ErpBarcode string ` json:"erp_barcode" ` // 商品条码
IMEIType uint32 ` json:"imei_type" ` // 系统生成串码: 2-是(系统生成) 3-否(手动添加)
ErpSupplierId uint32 ` json:"erp_supplier_id" binding:"required" ` // 主供应商
RetailPrice float64 ` json:"retail_price" ` // 指导零售价
MinRetailPrice float64 ` json:"min_retail_price" ` // 最低零售价
StaffCostPrice float64 ` json:"staff_cost_price" ` // 员工成本价加价
WholesalePrice float64 ` json:"wholesale_price" ` // 指导采购价
Brokerage1 float64 ` json:"brokerage_1" ` // 销售毛利提成
Brokerage2 float64 ` json:"brokerage_2" ` // 员工毛利提成
MemberDiscount float64 ` json:"member_discount" ` // 会员优惠
Origin string ` json:"origin" ` // 产地
2024-08-14 01:52:38 +00:00
Remark string ` json:"remark" ` // 备注
Img string ` json:"img" ` // 图片
2024-11-13 07:49:57 +00:00
StopPurchase uint32 ` json:"stop_purchase" ` // 0-未勾选, 正常采购; 1-勾选,停止采购
2024-04-22 01:51:41 +00:00
}
type CommodityEditRequest struct {
Id uint32 ` json:"id" binding:"required" ` // 商品id
Name string ` json:"name" binding:"required" ` // 商品名称
ErpCategoryId uint32 ` json:"erp_category_id" binding:"required" ` // 商品分类id
ErpBarcode string ` json:"erp_barcode" ` // 商品条码
IsIMEI uint32 ` json:"is_imei" binding:"required" ` // 是否串码: 1-串码类 2-非串码
IMEIType uint32 ` json:"imei_type" binding:"required" ` // 1-无串码 2-串码(系统生成) 3-串码(手动添加)
ErpSupplierId uint32 ` json:"erp_supplier_id" binding:"required" ` // 主供应商id
RetailPrice float64 ` json:"retail_price" ` // 指导零售价
MinRetailPrice float64 ` json:"min_retail_price" ` // 最低零售价
StaffCostPrice float64 ` json:"staff_cost_price" ` // 员工成本价加价
WholesalePrice float64 ` json:"wholesale_price" ` // 指导采购价
Brokerage1 float64 ` json:"brokerage_1" ` // 销售毛利提成
Brokerage2 float64 ` json:"brokerage_2" ` // 员工毛利提成
MemberDiscount float64 ` json:"member_discount" ` // 会员优惠
Origin string ` json:"origin" ` // 产地
2024-08-14 01:52:38 +00:00
Remark string ` json:"remark" ` // 备注
Img string ` json:"img" ` // 图片
2024-11-13 07:49:57 +00:00
StopPurchase uint32 ` json:"stop_purchase" ` // 0-未勾选, 正常采购; 1-勾选,停止采购
2024-04-22 01:51:41 +00:00
}
type CommodityDetailRequest struct {
ErpCommodityId uint32 ` json:"erp_commodity_id" ` // 商品id
SerialNumber string ` json:"serial_number" ` // 商品编号
}
type CommodityDelRequest struct {
ErpCommodityId uint32 ` json:"erp_commodity_id" binding:"required" ` // 商品id
}