Dockerfile
This commit is contained in:
44
cmd/clear_cache/main.go
Normal file
44
cmd/clear_cache/main.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
goredis "github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
rdb := goredis.NewClient(&goredis.Options{
|
||||
Addr: "192.168.3.200:6379",
|
||||
DB: 0,
|
||||
})
|
||||
defer rdb.Close()
|
||||
|
||||
patterns := []string{
|
||||
"*private_stock*",
|
||||
"*inventory_count*",
|
||||
"*private_sku*",
|
||||
"*warehouse*",
|
||||
"*zone*",
|
||||
"*location*",
|
||||
}
|
||||
|
||||
total := 0
|
||||
for _, pattern := range patterns {
|
||||
keys, err := rdb.Keys(ctx, pattern).Result()
|
||||
if err != nil {
|
||||
fmt.Printf("查询模式[%s]失败: %v\n", pattern, err)
|
||||
continue
|
||||
}
|
||||
for _, key := range keys {
|
||||
rdb.Del(ctx, key)
|
||||
total++
|
||||
}
|
||||
if len(keys) > 0 {
|
||||
fmt.Printf("✅ 模式[%s] 清除了 %d 个key\n", pattern, len(keys))
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n共清除 %d 个Redis缓存key\n", total)
|
||||
}
|
||||
164
cmd/seed_data/main.go
Normal file
164
cmd/seed_data/main.go
Normal file
@@ -0,0 +1,164 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"go.mongodb.org/mongo-driver/v2/mongo"
|
||||
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
client, err := mongo.Connect(options.Client().ApplyURI("mongodb://192.168.3.200:27017/?directConnection=true"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer client.Disconnect(ctx)
|
||||
|
||||
db := client.Database("assets")
|
||||
now := time.Now()
|
||||
|
||||
// 0. 清理之前的测试数据(按warehouseCode匹配)
|
||||
fmt.Println("=== 清理旧测试数据 ===")
|
||||
db.Collection("warehouse").DeleteMany(ctx, bson.M{"warehouseCode": "WH-TEST-001"})
|
||||
db.Collection("zone").DeleteMany(ctx, bson.M{"zoneCode": "ZN-TEST-001"})
|
||||
db.Collection("location").DeleteMany(ctx, bson.M{"locationCode": "LC-TEST-001"})
|
||||
db.Collection("private_sku").DeleteMany(ctx, bson.M{"skuName": "测试商品-矿泉水550ml"})
|
||||
db.Collection("private_stock").DeleteMany(ctx, bson.M{"warehouseCode": "WH-TEST-001"})
|
||||
db.Collection("inventory_count").DeleteMany(ctx, bson.M{"title": bson.M{"$regex": "测试"}})
|
||||
db.Collection("inventory_count_detail").DeleteMany(ctx, bson.M{})
|
||||
fmt.Println("✅ 旧测试数据已清理")
|
||||
|
||||
// 基础字段(MongoBaseDO)
|
||||
base := func() bson.M {
|
||||
return bson.M{
|
||||
"creator": "admin",
|
||||
"createdAt": now,
|
||||
"updater": "admin",
|
||||
"updatedAt": now,
|
||||
"tenantId": float64(1),
|
||||
"isDeleted": false,
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 创建仓库(匹配现有数据格式)
|
||||
warehouseId := bson.NewObjectID()
|
||||
whDoc := base()
|
||||
whDoc["_id"] = warehouseId
|
||||
whDoc["warehouseCode"] = "WH-TEST-001"
|
||||
whDoc["warehouseName"] = "测试仓库"
|
||||
whDoc["address"] = "测试地址"
|
||||
whDoc["contactPerson"] = "测试联系人"
|
||||
whDoc["contactPhone"] = "13800138000"
|
||||
whDoc["status"] = "enable"
|
||||
whDoc["remark"] = "自动生成的测试数据"
|
||||
|
||||
_, err = db.Collection("warehouse").InsertOne(ctx, whDoc)
|
||||
if err != nil {
|
||||
fmt.Printf("创建仓库失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("✅ 仓库已创建: %s\n", warehouseId.Hex())
|
||||
|
||||
// 2. 创建库区(Zone.WarehouseId是string类型,zoneType是string枚举)
|
||||
zoneId := bson.NewObjectID()
|
||||
znDoc := base()
|
||||
znDoc["_id"] = zoneId
|
||||
znDoc["warehouseId"] = warehouseId.Hex()
|
||||
znDoc["zoneCode"] = "ZN-TEST-001"
|
||||
znDoc["zoneName"] = "测试库区A"
|
||||
znDoc["zoneType"] = "normal"
|
||||
znDoc["status"] = "enable"
|
||||
znDoc["remark"] = "自动生成的测试数据"
|
||||
|
||||
_, err = db.Collection("zone").InsertOne(ctx, znDoc)
|
||||
if err != nil {
|
||||
fmt.Printf("创建库区失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("✅ 库区已创建: %s\n", zoneId.Hex())
|
||||
|
||||
// 3. 创建库位(匹配现有数据:maxCapacity/currentCapacity为顶层字段)
|
||||
locationId := bson.NewObjectID()
|
||||
lcDoc := base()
|
||||
lcDoc["_id"] = locationId
|
||||
lcDoc["warehouseId"] = warehouseId
|
||||
lcDoc["zoneId"] = zoneId
|
||||
lcDoc["locationCode"] = "LC-TEST-001"
|
||||
lcDoc["locationName"] = "测试库位A-1"
|
||||
lcDoc["locationType"] = "shelf"
|
||||
lcDoc["status"] = "idle"
|
||||
lcDoc["maxCapacity"] = 100
|
||||
lcDoc["currentCapacity"] = 0
|
||||
lcDoc["remark"] = "自动生成的测试数据"
|
||||
|
||||
_, err = db.Collection("location").InsertOne(ctx, lcDoc)
|
||||
if err != nil {
|
||||
fmt.Printf("创建库位失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("✅ 库位已创建: %s\n", locationId.Hex())
|
||||
|
||||
// 4. 创建私域SKU(匹配现有数据格式)
|
||||
skuId := bson.NewObjectID()
|
||||
skuDoc := base()
|
||||
skuDoc["_id"] = skuId
|
||||
skuDoc["skuName"] = "测试商品-矿泉水550ml"
|
||||
skuDoc["price"] = 200
|
||||
skuDoc["stock"] = 150
|
||||
skuDoc["sort"] = 1
|
||||
skuDoc["capacityUnitType"] = 1
|
||||
skuDoc["capacity"] = bson.M{"value": 550, "unit": "ml"}
|
||||
skuDoc["privateCategoryPath"] = "/饮品/矿泉水"
|
||||
|
||||
_, err = db.Collection("private_sku").InsertOne(ctx, skuDoc)
|
||||
if err != nil {
|
||||
fmt.Printf("创建SKU失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("✅ 私域SKU已创建: %s\n", skuId.Hex())
|
||||
|
||||
// 5. 创建私域库存(2条批次,枚举用string类型)
|
||||
for i := 1; i <= 2; i++ {
|
||||
stockId := bson.NewObjectID()
|
||||
stDoc := base()
|
||||
stDoc["_id"] = stockId
|
||||
stDoc["stockType"] = 2
|
||||
stDoc["warehouseId"] = warehouseId
|
||||
stDoc["warehouseCode"] = "WH-TEST-001"
|
||||
stDoc["warehouseName"] = "测试仓库"
|
||||
stDoc["zoneId"] = zoneId
|
||||
stDoc["zoneCode"] = "ZN-TEST-001"
|
||||
stDoc["zoneName"] = "测试库区A"
|
||||
stDoc["zoneType"] = "normal"
|
||||
stDoc["locationId"] = locationId
|
||||
stDoc["locationCode"] = "LC-TEST-001"
|
||||
stDoc["locationName"] = "测试库位A-1"
|
||||
stDoc["locationType"] = "shelf"
|
||||
stDoc["privateSkuId"] = skuId
|
||||
stDoc["batchNo"] = fmt.Sprintf("BATCH-TEST-%03d", i)
|
||||
stDoc["batchQty"] = 50 * i
|
||||
stDoc["availableQty"] = 50 * i
|
||||
stDoc["batchStatus"] = 1
|
||||
stDoc["supportsRecycle"] = false
|
||||
stDoc["privateCategoryPath"] = "/饮品/矿泉水"
|
||||
stDoc["stockStatus"] = 1
|
||||
|
||||
_, err = db.Collection("private_stock").InsertOne(ctx, stDoc)
|
||||
if err != nil {
|
||||
fmt.Printf("创建库存批次%d失败: %v\n", i, err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("✅ 私域库存批次%d已创建: %s (数量:%d)\n", i, stockId.Hex(), 50*i)
|
||||
}
|
||||
|
||||
fmt.Println("\n========== 测试数据创建完成 ==========")
|
||||
fmt.Printf("仓库ID: %s\n", warehouseId.Hex())
|
||||
fmt.Printf("库区ID: %s\n", zoneId.Hex())
|
||||
fmt.Printf("库位ID: %s\n", locationId.Hex())
|
||||
fmt.Printf("SKU ID: %s\n", skuId.Hex())
|
||||
fmt.Println("\n可使用仓库ID创建盘点任务进行测试")
|
||||
}
|
||||
17
consts/asset/asset_sku_status.go
Normal file
17
consts/asset/asset_sku_status.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package consts
|
||||
|
||||
// AssetSkuStatus SKU状态枚举
|
||||
type AssetSkuStatus int
|
||||
|
||||
const (
|
||||
AssetSkuStatusActive AssetSkuStatus = 1 // 启用
|
||||
AssetSkuStatusInactive AssetSkuStatus = 0 // 停用
|
||||
)
|
||||
|
||||
// GetAllSkuStatuses 获取所有SKU状态
|
||||
func GetAllSkuStatuses() []AssetSkuStatus {
|
||||
return []AssetSkuStatus{
|
||||
AssetSkuStatusActive,
|
||||
AssetSkuStatusInactive,
|
||||
}
|
||||
}
|
||||
17
consts/asset/asset_status.go
Normal file
17
consts/asset/asset_status.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package consts
|
||||
|
||||
// AssetStatus 资产状态枚举
|
||||
type AssetStatus int
|
||||
|
||||
const (
|
||||
AssetStatusActive AssetStatus = 1 // 启用
|
||||
AssetStatusInactive AssetStatus = 0 // 停用
|
||||
)
|
||||
|
||||
// GetAllAssetStatuses 获取所有资产状态
|
||||
func GetAllAssetStatuses() []AssetStatus {
|
||||
return []AssetStatus{
|
||||
AssetStatusActive,
|
||||
AssetStatusInactive,
|
||||
}
|
||||
}
|
||||
73
consts/asset/asset_type.go
Normal file
73
consts/asset/asset_type.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package consts
|
||||
|
||||
// AssetType 资产类型枚举
|
||||
type AssetType string
|
||||
|
||||
const (
|
||||
AssetTypePhysical AssetType = "physical" // 实物资产
|
||||
AssetTypeVirtual AssetType = "virtual" // 虚拟资产
|
||||
AssetTypeService AssetType = "service" // 服务资产
|
||||
)
|
||||
|
||||
// GetAllAssetTypeKey 获取所有资产类型
|
||||
func GetAllAssetTypeKey() []AssetType {
|
||||
return []AssetType{
|
||||
AssetTypePhysical,
|
||||
AssetTypeVirtual,
|
||||
AssetTypeService,
|
||||
}
|
||||
}
|
||||
|
||||
type AssetTypeKeyValue struct {
|
||||
Key AssetType // 对应原有常量值(physical/virtual/service)
|
||||
Value string // 对应描述信息(实物资产/虚拟资产/服务资产)
|
||||
}
|
||||
|
||||
// 定义枚举实例(Key-Value 绑定),相当于改造后的常量
|
||||
var (
|
||||
AssetTypePhysicalKeyValue = AssetTypeKeyValue{Key: AssetTypePhysical, Value: "实物资产"}
|
||||
AssetTypeVirtualKeyValue = AssetTypeKeyValue{Key: AssetTypeVirtual, Value: "虚拟资产"}
|
||||
AssetTypeServiceKeyValue = AssetTypeKeyValue{Key: AssetTypeService, Value: "服务资产"}
|
||||
)
|
||||
|
||||
func GetAllAssetTypeKeyValue() []AssetTypeKeyValue {
|
||||
return []AssetTypeKeyValue{
|
||||
AssetTypePhysicalKeyValue,
|
||||
AssetTypeVirtualKeyValue,
|
||||
AssetTypeServiceKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
// -------------- 核心:构建Map映射 + 查询方法 --------------
|
||||
// 预初始化资产类型映射表(包初始化时执行,仅初始化一次)
|
||||
var assetTypeValueMap = map[AssetType]string{
|
||||
AssetTypePhysical: AssetTypePhysicalKeyValue.Value,
|
||||
AssetTypeVirtual: AssetTypeVirtualKeyValue.Value,
|
||||
AssetTypeService: AssetTypeServiceKeyValue.Value,
|
||||
}
|
||||
|
||||
// GetAssetTypeValueByKey 根据 AssetType 键获取对应的描述值
|
||||
// 返回值:第一个返回值是描述信息,第二个返回值是是否存在该键
|
||||
func GetAssetTypeValueByKey(key AssetType) (value string) {
|
||||
value, exists := assetTypeValueMap[key]
|
||||
if !exists {
|
||||
value = "未知资产类型"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// VirtualAssetType 虚拟资产类型二级分类枚举
|
||||
type VirtualAssetType string
|
||||
|
||||
const (
|
||||
VirtualAssetTypeRecharge VirtualAssetType = "recharge" // 虚拟资产-充值
|
||||
VirtualTypeSubscribe VirtualAssetType = "subscribe" // 服务资产-订阅
|
||||
)
|
||||
|
||||
// ServiceAssetType 服务资产类型二级分类枚举
|
||||
type ServiceAssetType string
|
||||
|
||||
const (
|
||||
ServiceAssetTypeArrival ServiceAssetType = "arrival" // 虚拟资产-到店
|
||||
ServiceTypeVisit ServiceAssetType = "visit" // 服务资产-上门
|
||||
)
|
||||
47
consts/asset/attribute_type.go
Normal file
47
consts/asset/attribute_type.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package consts
|
||||
|
||||
// AttributeType 属性类型枚举
|
||||
type AttributeType string
|
||||
|
||||
const (
|
||||
AttributeTypeText AttributeType = "text" // 文本
|
||||
//AttributeTypeNumber AttributeType = "number" // 数字
|
||||
//AttributeTypeDate AttributeType = "date" // 日期
|
||||
AttributeTypeSelect AttributeType = "select" // 单选
|
||||
AttributeTypeMultiSelect AttributeType = "multi_select" // 多选
|
||||
)
|
||||
|
||||
// GetAllAttributeTypes 获取所有属性类型
|
||||
func GetAllAttributeTypes() []AttributeType {
|
||||
return []AttributeType{
|
||||
AttributeTypeText,
|
||||
//AttributeTypeNumber,
|
||||
//AttributeTypeDate,
|
||||
AttributeTypeSelect,
|
||||
AttributeTypeMultiSelect,
|
||||
}
|
||||
}
|
||||
|
||||
type AttrTypeKeyValue struct {
|
||||
Key AttributeType // 对应原有常量值
|
||||
Value string // 对应描述信息
|
||||
}
|
||||
|
||||
// 定义枚举实例(Key-Value 绑定),相当于改造后的常量
|
||||
var (
|
||||
AttrTypeTextKeyValue = AttrTypeKeyValue{Key: AttributeTypeText, Value: "文本"}
|
||||
//AttrTypeNumberKeyValue = AttrTypeKeyValue{Key: AttributeTypeNumber, Value: "数字"}
|
||||
//AttrTypeDateKeyValue = AttrTypeKeyValue{Key: AttributeTypeDate, Value: "日期"}
|
||||
AttrTypeSelectKeyValue = AttrTypeKeyValue{Key: AttributeTypeSelect, Value: "单选"}
|
||||
AttrTypeMultiSelectKeyValue = AttrTypeKeyValue{Key: AttributeTypeMultiSelect, Value: "多选"}
|
||||
)
|
||||
|
||||
func GetAllAttrTypeKeyValue() []AttrTypeKeyValue {
|
||||
return []AttrTypeKeyValue{
|
||||
AttrTypeTextKeyValue,
|
||||
//AttrTypeNumberKeyValue,
|
||||
//AttrTypeDateKeyValue,
|
||||
AttrTypeSelectKeyValue,
|
||||
AttrTypeMultiSelectKeyValue,
|
||||
}
|
||||
}
|
||||
14
consts/category/category_status.go
Normal file
14
consts/category/category_status.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package consts
|
||||
|
||||
// CategoryStatus 分类状态枚举
|
||||
|
||||
type CategoryStatusType *int
|
||||
|
||||
type CategoryStatus struct {
|
||||
Status CategoryStatusType
|
||||
}
|
||||
|
||||
//var CategoryStatusVal = CategoryStatus{
|
||||
// CategoryStatusActive: gconv.PtrInt(1),
|
||||
// CategoryStatusInactive: gconv.PtrInt(0),
|
||||
//}
|
||||
52
consts/procurement/approval_status.go
Normal file
52
consts/procurement/approval_status.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package consts
|
||||
|
||||
// ApprovalStatus 审批状态枚举
|
||||
type ApprovalStatus int
|
||||
|
||||
const (
|
||||
ApprovalStatusPending ApprovalStatus = 1 // 待审批
|
||||
ApprovalStatusApproved ApprovalStatus = 2 // 已批准
|
||||
ApprovalStatusRejected ApprovalStatus = 3 // 已拒绝
|
||||
ApprovalStatusCanceled ApprovalStatus = 4 // 已撤销
|
||||
)
|
||||
|
||||
// GetAllApprovalStatuses 获取所有审批状态
|
||||
func GetAllApprovalStatuses() []ApprovalStatus {
|
||||
return []ApprovalStatus{
|
||||
ApprovalStatusPending,
|
||||
ApprovalStatusApproved,
|
||||
ApprovalStatusRejected,
|
||||
ApprovalStatusCanceled,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取审批状态字符串表示
|
||||
func (a ApprovalStatus) String() string {
|
||||
switch a {
|
||||
case ApprovalStatusPending:
|
||||
return "待审批"
|
||||
case ApprovalStatusApproved:
|
||||
return "已批准"
|
||||
case ApprovalStatusRejected:
|
||||
return "已拒绝"
|
||||
case ApprovalStatusCanceled:
|
||||
return "已撤销"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
type ApprovalStatusKeyValue struct {
|
||||
Key int `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// GetAllApprovalStatusKeyValue 获取所有审批状态的键值对
|
||||
func GetAllApprovalStatusKeyValue() []ApprovalStatusKeyValue {
|
||||
return []ApprovalStatusKeyValue{
|
||||
{Key: 1, Value: "待审批"},
|
||||
{Key: 2, Value: "已批准"},
|
||||
{Key: 3, Value: "已拒绝"},
|
||||
{Key: 4, Value: "已撤销"},
|
||||
}
|
||||
}
|
||||
52
consts/procurement/bid_mode.go
Normal file
52
consts/procurement/bid_mode.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package consts
|
||||
|
||||
// BidMode 竞价模式枚举
|
||||
type BidMode string
|
||||
|
||||
const (
|
||||
BidModePrice BidMode = "price" // 优先价格
|
||||
BidModeQuality BidMode = "quality" // 优先质量
|
||||
BidModeTime BidMode = "time" // 优先时效
|
||||
BidModeMixed BidMode = "mixed" // 综合评价
|
||||
)
|
||||
|
||||
// GetAllBidModes 获取所有竞价模式
|
||||
func GetAllBidModes() []BidMode {
|
||||
return []BidMode{
|
||||
BidModePrice,
|
||||
BidModeQuality,
|
||||
BidModeTime,
|
||||
BidModeMixed,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取竞价模式字符串表示
|
||||
func (b BidMode) String() string {
|
||||
switch b {
|
||||
case BidModePrice:
|
||||
return "优先价格"
|
||||
case BidModeQuality:
|
||||
return "优先质量"
|
||||
case BidModeTime:
|
||||
return "优先时效"
|
||||
case BidModeMixed:
|
||||
return "综合评价"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// IsValidBidMode 验证竞价模式是否有效
|
||||
func (b BidMode) IsValid() bool {
|
||||
switch b {
|
||||
case BidModePrice, BidModeQuality, BidModeTime, BidModeMixed:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// GetBidModeText 获取竞价模式文本
|
||||
func GetBidModeText(bidMode BidMode) string {
|
||||
return bidMode.String()
|
||||
}
|
||||
49
consts/procurement/bid_status.go
Normal file
49
consts/procurement/bid_status.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package consts
|
||||
|
||||
// BidStatus 投标状态枚举
|
||||
type BidStatus string
|
||||
|
||||
const (
|
||||
BidStatusDraft BidStatus = "draft" // 草稿
|
||||
BidStatusSubmitted BidStatus = "submitted" // 已提交
|
||||
BidStatusViewed BidStatus = "viewed" // 已查看
|
||||
BidStatusWinning BidStatus = "winning" // 中标
|
||||
BidStatusLost BidStatus = "lost" // 未中标
|
||||
BidStatusWithdrawn BidStatus = "withdrawn" // 已撤回
|
||||
BidStatusExpired BidStatus = "expired" // 已过期
|
||||
)
|
||||
|
||||
// GetAllBidStatuses 获取所有投标状态
|
||||
func GetAllBidStatuses() []BidStatus {
|
||||
return []BidStatus{
|
||||
BidStatusDraft,
|
||||
BidStatusSubmitted,
|
||||
BidStatusViewed,
|
||||
BidStatusWinning,
|
||||
BidStatusLost,
|
||||
BidStatusWithdrawn,
|
||||
BidStatusExpired,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取投标状态字符串表示
|
||||
func (b BidStatus) String() string {
|
||||
switch b {
|
||||
case BidStatusDraft:
|
||||
return "草稿"
|
||||
case BidStatusSubmitted:
|
||||
return "已提交"
|
||||
case BidStatusViewed:
|
||||
return "已查看"
|
||||
case BidStatusWinning:
|
||||
return "中标"
|
||||
case BidStatusLost:
|
||||
return "未中标"
|
||||
case BidStatusWithdrawn:
|
||||
return "已撤回"
|
||||
case BidStatusExpired:
|
||||
return "已过期"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
21
consts/procurement/billing_method.go
Normal file
21
consts/procurement/billing_method.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package consts
|
||||
|
||||
// BillingMethod 计费方式枚举
|
||||
type BillingMethod string
|
||||
|
||||
const (
|
||||
BillingMethodCount BillingMethod = "count" // 按数量
|
||||
BillingMethodDuration BillingMethod = "duration" // 按时长
|
||||
BillingMethodSku BillingMethod = "sku" // 按SKU
|
||||
BillingMethodDurationAndSku BillingMethod = "duration_and_sku" // 按时长+SKU
|
||||
)
|
||||
|
||||
// GetAllBillingMethods 获取所有计费方式
|
||||
func GetAllBillingMethods() []BillingMethod {
|
||||
return []BillingMethod{
|
||||
BillingMethodCount,
|
||||
BillingMethodDuration,
|
||||
BillingMethodSku,
|
||||
BillingMethodDurationAndSku,
|
||||
}
|
||||
}
|
||||
47
consts/procurement/process_method.go
Normal file
47
consts/procurement/process_method.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package consts
|
||||
|
||||
// ProcessMethod 处理方式枚举
|
||||
type ProcessMethod int
|
||||
|
||||
const (
|
||||
ProcessMethodRefund ProcessMethod = 1 // 退款
|
||||
ProcessMethodReplace ProcessMethod = 2 // 更换
|
||||
ProcessMethodRepair ProcessMethod = 3 // 维修
|
||||
)
|
||||
|
||||
// GetAllProcessMethods 获取所有处理方式
|
||||
func GetAllProcessMethods() []ProcessMethod {
|
||||
return []ProcessMethod{
|
||||
ProcessMethodRefund,
|
||||
ProcessMethodReplace,
|
||||
ProcessMethodRepair,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取处理方式字符串表示
|
||||
func (p ProcessMethod) String() string {
|
||||
switch p {
|
||||
case ProcessMethodRefund:
|
||||
return "退款"
|
||||
case ProcessMethodReplace:
|
||||
return "更换"
|
||||
case ProcessMethodRepair:
|
||||
return "维修"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
type ProcessMethodKeyValue struct {
|
||||
Key int `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// GetAllProcessMethodKeyValue 获取所有处理方式的键值对
|
||||
func GetAllProcessMethodKeyValue() []ProcessMethodKeyValue {
|
||||
return []ProcessMethodKeyValue{
|
||||
{Key: 1, Value: "退款"},
|
||||
{Key: 2, Value: "更换"},
|
||||
{Key: 3, Value: "维修"},
|
||||
}
|
||||
}
|
||||
58
consts/procurement/purchase_order_status.go
Normal file
58
consts/procurement/purchase_order_status.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package consts
|
||||
|
||||
// PurchaseOrderStatus 采购订单状态枚举
|
||||
type PurchaseOrderStatus string
|
||||
|
||||
const (
|
||||
PurchaseOrderStatusDraft PurchaseOrderStatus = "draft" // 草稿
|
||||
PurchaseOrderStatusPublished PurchaseOrderStatus = "published" // 已发布
|
||||
PurchaseOrderStatusProcessing PurchaseOrderStatus = "processing" // 处理中
|
||||
PurchaseOrderStatusAssigned PurchaseOrderStatus = "assigned" // 已指派
|
||||
PurchaseOrderStatusBidding PurchaseOrderStatus = "bidding" // 竞价中
|
||||
PurchaseOrderStatusCompleted PurchaseOrderStatus = "completed" // 已完成
|
||||
PurchaseOrderStatusCancelled PurchaseOrderStatus = "cancelled" // 已取消
|
||||
PurchaseOrderStatusExpired PurchaseOrderStatus = "expired" // 已过期
|
||||
)
|
||||
|
||||
// GetAllPurchaseOrderStatuses 获取所有采购订单状态
|
||||
func GetAllPurchaseOrderStatuses() []PurchaseOrderStatus {
|
||||
return []PurchaseOrderStatus{
|
||||
PurchaseOrderStatusDraft,
|
||||
PurchaseOrderStatusPublished,
|
||||
PurchaseOrderStatusProcessing,
|
||||
PurchaseOrderStatusAssigned,
|
||||
PurchaseOrderStatusBidding,
|
||||
PurchaseOrderStatusCompleted,
|
||||
PurchaseOrderStatusCancelled,
|
||||
PurchaseOrderStatusExpired,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取采购订单状态字符串表示
|
||||
func (p PurchaseOrderStatus) String() string {
|
||||
switch p {
|
||||
case PurchaseOrderStatusDraft:
|
||||
return "草稿"
|
||||
case PurchaseOrderStatusPublished:
|
||||
return "已发布"
|
||||
case PurchaseOrderStatusProcessing:
|
||||
return "处理中"
|
||||
case PurchaseOrderStatusAssigned:
|
||||
return "已指派"
|
||||
case PurchaseOrderStatusBidding:
|
||||
return "竞价中"
|
||||
case PurchaseOrderStatusCompleted:
|
||||
return "已完成"
|
||||
case PurchaseOrderStatusCancelled:
|
||||
return "已取消"
|
||||
case PurchaseOrderStatusExpired:
|
||||
return "已过期"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// GetPurchaseOrderStatusText 获取采购订单状态文本
|
||||
func GetPurchaseOrderStatusText(status PurchaseOrderStatus) string {
|
||||
return status.String()
|
||||
}
|
||||
53
consts/procurement/purchase_order_type.go
Normal file
53
consts/procurement/purchase_order_type.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package consts
|
||||
|
||||
// PurchaseOrderType 采购订单类型枚举
|
||||
type PurchaseOrderType string
|
||||
|
||||
const (
|
||||
PurchaseOrderTypeDirect PurchaseOrderType = "direct" // 直接采购(指定供应商)
|
||||
PurchaseOrderTypeBidding PurchaseOrderType = "bidding" // 竞价采购
|
||||
PurchaseOrderTypeAuction PurchaseOrderType = "auction" // 拍卖采购
|
||||
PurchaseOrderTypeGroup PurchaseOrderType = "group" // 团购采购
|
||||
)
|
||||
|
||||
// GetAllPurchaseOrderTypes 获取所有采购订单类型
|
||||
func GetAllPurchaseOrderTypes() []PurchaseOrderType {
|
||||
return []PurchaseOrderType{
|
||||
PurchaseOrderTypeDirect,
|
||||
PurchaseOrderTypeBidding,
|
||||
PurchaseOrderTypeAuction,
|
||||
PurchaseOrderTypeGroup,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取采购订单类型字符串表示
|
||||
func (p PurchaseOrderType) String() string {
|
||||
switch p {
|
||||
case PurchaseOrderTypeDirect:
|
||||
return "直接采购"
|
||||
case PurchaseOrderTypeBidding:
|
||||
return "竞价采购"
|
||||
case PurchaseOrderTypeAuction:
|
||||
return "拍卖采购"
|
||||
case PurchaseOrderTypeGroup:
|
||||
return "团购采购"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// IsValidOrderType 验证订单类型是否有效
|
||||
func (p PurchaseOrderType) IsValid() bool {
|
||||
switch p {
|
||||
case PurchaseOrderTypeDirect, PurchaseOrderTypeBidding,
|
||||
PurchaseOrderTypeAuction, PurchaseOrderTypeGroup:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// GetPurchaseOrderTypeText 获取采购订单类型文本
|
||||
func GetPurchaseOrderTypeText(orderType PurchaseOrderType) string {
|
||||
return orderType.String()
|
||||
}
|
||||
57
consts/procurement/purchase_status.go
Normal file
57
consts/procurement/purchase_status.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package consts
|
||||
|
||||
// PurchaseStatus 采购单状态枚举
|
||||
type PurchaseStatus string
|
||||
|
||||
const (
|
||||
PurchaseStatusNotArrived PurchaseStatus = "not_arrived" // 未到货
|
||||
PurchaseStatusReceived PurchaseStatus = "received" // 已入库
|
||||
PurchaseStatusPartial PurchaseStatus = "partial" // 部分入库
|
||||
PurchaseStatusCancelled PurchaseStatus = "cancelled" // 已取消
|
||||
)
|
||||
|
||||
// GetAllPurchaseStatuses 获取所有采购单状态
|
||||
func GetAllPurchaseStatuses() []PurchaseStatus {
|
||||
return []PurchaseStatus{
|
||||
PurchaseStatusNotArrived,
|
||||
PurchaseStatusReceived,
|
||||
PurchaseStatusPartial,
|
||||
PurchaseStatusCancelled,
|
||||
}
|
||||
}
|
||||
|
||||
type PurchaseStatusKeyValue struct {
|
||||
Key PurchaseStatus
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
PurchaseStatusNotArrivedKeyValue = PurchaseStatusKeyValue{Key: PurchaseStatusNotArrived, Value: "未到货"}
|
||||
PurchaseStatusReceivedKeyValue = PurchaseStatusKeyValue{Key: PurchaseStatusReceived, Value: "已入库"}
|
||||
PurchaseStatusPartialKeyValue = PurchaseStatusKeyValue{Key: PurchaseStatusPartial, Value: "部分入库"}
|
||||
PurchaseStatusCancelledKeyValue = PurchaseStatusKeyValue{Key: PurchaseStatusCancelled, Value: "已取消"}
|
||||
)
|
||||
|
||||
func GetAllPurchaseStatusKeyValue() []PurchaseStatusKeyValue {
|
||||
return []PurchaseStatusKeyValue{
|
||||
PurchaseStatusNotArrivedKeyValue,
|
||||
PurchaseStatusReceivedKeyValue,
|
||||
PurchaseStatusPartialKeyValue,
|
||||
PurchaseStatusCancelledKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var purchaseStatusValueMap = map[PurchaseStatus]string{
|
||||
PurchaseStatusNotArrived: PurchaseStatusNotArrivedKeyValue.Value,
|
||||
PurchaseStatusReceived: PurchaseStatusReceivedKeyValue.Value,
|
||||
PurchaseStatusPartial: PurchaseStatusPartialKeyValue.Value,
|
||||
PurchaseStatusCancelled: PurchaseStatusCancelledKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetPurchaseStatusValueByKey(key PurchaseStatus) (value string) {
|
||||
value, exists := purchaseStatusValueMap[key]
|
||||
if !exists {
|
||||
value = "未知状态"
|
||||
}
|
||||
return
|
||||
}
|
||||
53
consts/procurement/return_item_status.go
Normal file
53
consts/procurement/return_item_status.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package consts
|
||||
|
||||
// ReturnItemStatus 退换明细状态枚举
|
||||
type ReturnItemStatus string
|
||||
|
||||
const (
|
||||
ReturnItemStatusPending ReturnItemStatus = "pending" // 待处理
|
||||
ReturnItemStatusApproved ReturnItemStatus = "approved" // 已批准
|
||||
ReturnItemStatusRejected ReturnItemStatus = "rejected" // 已拒绝
|
||||
ReturnItemStatusShipped ReturnItemStatus = "shipped" // 已发货
|
||||
ReturnItemStatusReceived ReturnItemStatus = "received" // 已收货
|
||||
ReturnItemStatusProcessing ReturnItemStatus = "processing" // 处理中
|
||||
ReturnItemStatusCompleted ReturnItemStatus = "completed" // 已完成
|
||||
ReturnItemStatusCancelled ReturnItemStatus = "cancelled" // 已取消
|
||||
)
|
||||
|
||||
// GetAllReturnItemStatuses 获取所有退换明细状态
|
||||
func GetAllReturnItemStatuses() []ReturnItemStatus {
|
||||
return []ReturnItemStatus{
|
||||
ReturnItemStatusPending,
|
||||
ReturnItemStatusApproved,
|
||||
ReturnItemStatusRejected,
|
||||
ReturnItemStatusShipped,
|
||||
ReturnItemStatusReceived,
|
||||
ReturnItemStatusProcessing,
|
||||
ReturnItemStatusCompleted,
|
||||
ReturnItemStatusCancelled,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取退换明细状态字符串表示
|
||||
func (r ReturnItemStatus) String() string {
|
||||
switch r {
|
||||
case ReturnItemStatusPending:
|
||||
return "待处理"
|
||||
case ReturnItemStatusApproved:
|
||||
return "已批准"
|
||||
case ReturnItemStatusRejected:
|
||||
return "已拒绝"
|
||||
case ReturnItemStatusShipped:
|
||||
return "已发货"
|
||||
case ReturnItemStatusReceived:
|
||||
return "已收货"
|
||||
case ReturnItemStatusProcessing:
|
||||
return "处理中"
|
||||
case ReturnItemStatusCompleted:
|
||||
return "已完成"
|
||||
case ReturnItemStatusCancelled:
|
||||
return "已取消"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
65
consts/procurement/return_reason.go
Normal file
65
consts/procurement/return_reason.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package consts
|
||||
|
||||
// ReturnReason 退换原因枚举
|
||||
type ReturnReason string
|
||||
|
||||
const (
|
||||
ReturnReasonQualityDefect ReturnReason = "quality_defect" // 质量问题
|
||||
ReturnReasonDamaged ReturnReason = "damaged" // 运输损坏
|
||||
ReturnReasonWrongGoods ReturnReason = "wrong_goods" // 错发商品
|
||||
ReturnReasonExpired ReturnReason = "expired" // 商品过期
|
||||
ReturnReasonNotAsDescribed ReturnReason = "not_as_described" // 与描述不符
|
||||
ReturnReasonOverstock ReturnReason = "overstock" // 库存积压
|
||||
ReturnReasonChangeMind ReturnReason = "change_mind" // 改变主意
|
||||
ReturnReasonDuplicateOrder ReturnReason = "duplicate_order" // 重复下单
|
||||
ReturnReasonPriceError ReturnReason = "price_error" // 价格错误
|
||||
ReturnReasonSupplierDelay ReturnReason = "supplier_delay" // 供应商延期
|
||||
ReturnReasonOther ReturnReason = "other" // 其他原因
|
||||
)
|
||||
|
||||
// GetAllReturnReasons 获取所有退换原因
|
||||
func GetAllReturnReasons() []ReturnReason {
|
||||
return []ReturnReason{
|
||||
ReturnReasonQualityDefect,
|
||||
ReturnReasonDamaged,
|
||||
ReturnReasonWrongGoods,
|
||||
ReturnReasonExpired,
|
||||
ReturnReasonNotAsDescribed,
|
||||
ReturnReasonOverstock,
|
||||
ReturnReasonChangeMind,
|
||||
ReturnReasonDuplicateOrder,
|
||||
ReturnReasonPriceError,
|
||||
ReturnReasonSupplierDelay,
|
||||
ReturnReasonOther,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取退换原因字符串表示
|
||||
func (r ReturnReason) String() string {
|
||||
switch r {
|
||||
case ReturnReasonQualityDefect:
|
||||
return "质量问题"
|
||||
case ReturnReasonDamaged:
|
||||
return "运输损坏"
|
||||
case ReturnReasonWrongGoods:
|
||||
return "错发商品"
|
||||
case ReturnReasonExpired:
|
||||
return "商品过期"
|
||||
case ReturnReasonNotAsDescribed:
|
||||
return "与描述不符"
|
||||
case ReturnReasonOverstock:
|
||||
return "库存积压"
|
||||
case ReturnReasonChangeMind:
|
||||
return "改变主意"
|
||||
case ReturnReasonDuplicateOrder:
|
||||
return "重复下单"
|
||||
case ReturnReasonPriceError:
|
||||
return "价格错误"
|
||||
case ReturnReasonSupplierDelay:
|
||||
return "供应商延期"
|
||||
case ReturnReasonOther:
|
||||
return "其他原因"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
57
consts/procurement/return_status.go
Normal file
57
consts/procurement/return_status.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package consts
|
||||
|
||||
// ReturnStatus 退换状态枚举
|
||||
type ReturnStatus string
|
||||
|
||||
const (
|
||||
ReturnStatusDraft ReturnStatus = "draft" // 草稿
|
||||
ReturnStatusPending ReturnStatus = "pending" // 待审核
|
||||
ReturnStatusApproved ReturnStatus = "approved" // 已审核通过
|
||||
ReturnStatusRejected ReturnStatus = "rejected" // 审核拒绝
|
||||
ReturnStatusShipped ReturnStatus = "shipped" // 已发货(退货中)
|
||||
ReturnStatusReceived ReturnStatus = "received" // 已收货
|
||||
ReturnStatusProcessing ReturnStatus = "processing" // 处理中
|
||||
ReturnStatusCompleted ReturnStatus = "completed" // 已完成
|
||||
ReturnStatusCancelled ReturnStatus = "cancelled" // 已取消
|
||||
)
|
||||
|
||||
// GetAllReturnStatuses 获取所有退换状态
|
||||
func GetAllReturnStatuses() []ReturnStatus {
|
||||
return []ReturnStatus{
|
||||
ReturnStatusDraft,
|
||||
ReturnStatusPending,
|
||||
ReturnStatusApproved,
|
||||
ReturnStatusRejected,
|
||||
ReturnStatusShipped,
|
||||
ReturnStatusReceived,
|
||||
ReturnStatusProcessing,
|
||||
ReturnStatusCompleted,
|
||||
ReturnStatusCancelled,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取退换状态字符串表示
|
||||
func (r ReturnStatus) String() string {
|
||||
switch r {
|
||||
case ReturnStatusDraft:
|
||||
return "草稿"
|
||||
case ReturnStatusPending:
|
||||
return "待审核"
|
||||
case ReturnStatusApproved:
|
||||
return "已审核通过"
|
||||
case ReturnStatusRejected:
|
||||
return "审核拒绝"
|
||||
case ReturnStatusShipped:
|
||||
return "已发货(退货中)"
|
||||
case ReturnStatusReceived:
|
||||
return "已收货"
|
||||
case ReturnStatusProcessing:
|
||||
return "处理中"
|
||||
case ReturnStatusCompleted:
|
||||
return "已完成"
|
||||
case ReturnStatusCancelled:
|
||||
return "已取消"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
33
consts/procurement/return_type.go
Normal file
33
consts/procurement/return_type.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package consts
|
||||
|
||||
// ReturnType 退换类型枚举
|
||||
type ReturnType string
|
||||
|
||||
const (
|
||||
ReturnTypeReturn ReturnType = "return" // 退货
|
||||
ReturnTypeRefund ReturnType = "refund" // 退款
|
||||
ReturnTypeExchange ReturnType = "exchange" // 换货
|
||||
)
|
||||
|
||||
// GetAllReturnTypes 获取所有退换类型
|
||||
func GetAllReturnTypes() []ReturnType {
|
||||
return []ReturnType{
|
||||
ReturnTypeReturn,
|
||||
ReturnTypeRefund,
|
||||
ReturnTypeExchange,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取退换类型字符串表示
|
||||
func (r ReturnType) String() string {
|
||||
switch r {
|
||||
case ReturnTypeReturn:
|
||||
return "退货"
|
||||
case ReturnTypeRefund:
|
||||
return "退款"
|
||||
case ReturnTypeExchange:
|
||||
return "换货"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
52
consts/procurement/review_status.go
Normal file
52
consts/procurement/review_status.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package consts
|
||||
|
||||
// ReviewStatus 审核状态枚举
|
||||
type ReviewStatus int
|
||||
|
||||
const (
|
||||
ReviewStatusPending ReviewStatus = 1 // 待审核
|
||||
ReviewStatusApproved ReviewStatus = 2 // 已通过
|
||||
ReviewStatusRejected ReviewStatus = 3 // 已拒绝
|
||||
ReviewStatusCanceled ReviewStatus = 4 // 已撤销
|
||||
)
|
||||
|
||||
// GetAllReviewStatuses 获取所有审核状态
|
||||
func GetAllReviewStatuses() []ReviewStatus {
|
||||
return []ReviewStatus{
|
||||
ReviewStatusPending,
|
||||
ReviewStatusApproved,
|
||||
ReviewStatusRejected,
|
||||
ReviewStatusCanceled,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取审核状态字符串表示
|
||||
func (r ReviewStatus) String() string {
|
||||
switch r {
|
||||
case ReviewStatusPending:
|
||||
return "待审核"
|
||||
case ReviewStatusApproved:
|
||||
return "已通过"
|
||||
case ReviewStatusRejected:
|
||||
return "已拒绝"
|
||||
case ReviewStatusCanceled:
|
||||
return "已撤销"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
type ReviewStatusKeyValue struct {
|
||||
Key int `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// GetAllReviewStatusKeyValue 获取所有审核状态的键值对
|
||||
func GetAllReviewStatusKeyValue() []ReviewStatusKeyValue {
|
||||
return []ReviewStatusKeyValue{
|
||||
{Key: 1, Value: "待审核"},
|
||||
{Key: 2, Value: "已通过"},
|
||||
{Key: 3, Value: "已拒绝"},
|
||||
{Key: 4, Value: "已撤销"},
|
||||
}
|
||||
}
|
||||
29
consts/procurement/supplier_status.go
Normal file
29
consts/procurement/supplier_status.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package consts
|
||||
|
||||
// SupplierStatus 供应商状态枚举
|
||||
type SupplierStatus int
|
||||
|
||||
const (
|
||||
SupplierStatusActive SupplierStatus = 1 // 活跃
|
||||
SupplierStatusInactive SupplierStatus = 0 // 停用
|
||||
)
|
||||
|
||||
// GetAllSupplierStatuses 获取所有供应商状态
|
||||
func GetAllSupplierStatuses() []SupplierStatus {
|
||||
return []SupplierStatus{
|
||||
SupplierStatusActive,
|
||||
SupplierStatusInactive,
|
||||
}
|
||||
}
|
||||
|
||||
// GetSupplierStatusText 获取供应商状态文本
|
||||
func GetSupplierStatusText(status SupplierStatus) string {
|
||||
switch status {
|
||||
case SupplierStatusActive:
|
||||
return "活跃"
|
||||
case SupplierStatusInactive:
|
||||
return "停用"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
32
consts/public/collections.go
Normal file
32
consts/public/collections.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package public
|
||||
|
||||
// MongoDB集合名称常量
|
||||
const (
|
||||
AssetCollection = "assets_asset" // 资产集合
|
||||
CategoryCollection = "assets_category" // 分类集合
|
||||
PrivateCategoryCollection = "private_category" // 私域分类集合
|
||||
StockDetailsCollection = "stock_details" // 库存明细集合
|
||||
StockBatchCollection = "stock_batch" // 库存批次集合
|
||||
PrivateStockCollection = "private_stock" // 私域库存批次集合
|
||||
PurchaseOrderCollection = "purchase_order" // 采购订单主表集合(统一模式)
|
||||
PurchaseOrderItemCollection = "purchase_order_item" // 采购订单明细集合
|
||||
PurchaseBidCollection = "purchase_bid" // 采购投标单集合(供应商抢单参与记录)
|
||||
AssetSkuCollection = "asset_sku" // SKU集合
|
||||
PrivateSkuCollection = "private_sku" // 私域sku集合
|
||||
SupplierCollection = "supplier" // 供应商集合
|
||||
ExpiryMessageCollection = "expiry_message" // 临期消息集合(兼容旧数据)
|
||||
ExpiryMessageHistoryCollection = "expiry_message_history" // 临期消息历史集合(兼容旧数据)
|
||||
InventoryWarningCollection = "inventory_warning" // 库存预警集合
|
||||
InventoryWarningHistoryCollection = "inventory_warning_history" // 库存预警历史集合
|
||||
PurchaseReturnCollection = "purchase_return" // 采购退换单主表集合
|
||||
PurchaseReturnItemCollection = "purchase_return_item" // 采购退换单明细集合
|
||||
PurchaseInboundCollection = "purchase_inbound" // 采购入库记录集合
|
||||
DealerStockCollection = "dealer_stock" // 经销商库存集合
|
||||
WarehouseCollection = "warehouse" // 仓库集合
|
||||
ZoneCollection = "zone" // 库区集合
|
||||
LocationCollection = "location" // 库位集合
|
||||
InventoryCountCollection = "inventory_count" // 库存盘点主表集合
|
||||
InventoryCountDetailCollection = "inventory_count_detail" // 库存盘点明细表集合
|
||||
InventoryCountAdjustHistoryCollection = "inventory_count_adjust_history" // 库存盘点调整历史表集合
|
||||
UnitConversionCollection = "unit_conversion" // 单位换算集合
|
||||
)
|
||||
17
consts/public/currency.go
Normal file
17
consts/public/currency.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package public
|
||||
|
||||
// Currency 货币类型枚举
|
||||
type Currency string
|
||||
|
||||
const (
|
||||
CurrencyCNY Currency = "CNY" // 人民币
|
||||
CurrencyUSD Currency = "USD" // 美元
|
||||
)
|
||||
|
||||
// GetAllCurrencies 获取所有货币类型
|
||||
func GetAllCurrencies() []Currency {
|
||||
return []Currency{
|
||||
CurrencyCNY,
|
||||
CurrencyUSD,
|
||||
}
|
||||
}
|
||||
66
consts/public/duration_type.go
Normal file
66
consts/public/duration_type.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package public
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// DurationType 时长类型枚举
|
||||
type DurationType string
|
||||
|
||||
const (
|
||||
DurationTypeHour DurationType = "hour" // 小时
|
||||
DurationTypeDay DurationType = "day" // 天
|
||||
DurationTypeMonth DurationType = "month" // 月
|
||||
DurationTypeYear DurationType = "year" // 年
|
||||
)
|
||||
|
||||
// GetAllDurationTypes 获取所有时长类型
|
||||
func GetAllDurationTypes() []DurationType {
|
||||
return []DurationType{
|
||||
DurationTypeHour,
|
||||
DurationTypeDay,
|
||||
DurationTypeMonth,
|
||||
DurationTypeYear,
|
||||
}
|
||||
}
|
||||
|
||||
type DurationTypeKeyValue struct {
|
||||
Key DurationType // 对应原有常量值
|
||||
Value string // 对应描述信息
|
||||
}
|
||||
|
||||
// 定义枚举实例(Key-Value 绑定),相当于改造后的常量
|
||||
var (
|
||||
DurationTypeHourKeyValue = DurationTypeKeyValue{Key: DurationTypeHour, Value: "小时"}
|
||||
DurationTypeDayKeyValue = DurationTypeKeyValue{Key: DurationTypeDay, Value: "天"}
|
||||
DurationTypeMonthKeyValue = DurationTypeKeyValue{Key: DurationTypeMonth, Value: "月"}
|
||||
DurationTypeYearKeyValue = DurationTypeKeyValue{Key: DurationTypeYear, Value: "年"}
|
||||
)
|
||||
|
||||
func GetAllDurationTypeKeyValue() []DurationTypeKeyValue {
|
||||
return []DurationTypeKeyValue{
|
||||
DurationTypeHourKeyValue,
|
||||
DurationTypeDayKeyValue,
|
||||
DurationTypeMonthKeyValue,
|
||||
DurationTypeYearKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
// AddTime 根据时长类型和数量计算到期时间
|
||||
func (dt DurationType) AddTime(count int) *gtime.Time {
|
||||
now := gtime.Now()
|
||||
switch dt {
|
||||
case DurationTypeHour:
|
||||
return gtime.NewFromTime(now.Time.Add(time.Hour * time.Duration(count)))
|
||||
case DurationTypeDay:
|
||||
return gtime.NewFromTime(now.Time.AddDate(0, 0, count))
|
||||
case DurationTypeMonth:
|
||||
return gtime.NewFromTime(now.Time.AddDate(0, count, 0))
|
||||
case DurationTypeYear:
|
||||
return gtime.NewFromTime(now.Time.AddDate(count, 0, 0))
|
||||
default:
|
||||
return now
|
||||
}
|
||||
}
|
||||
17
consts/public/redis_key.go
Normal file
17
consts/public/redis_key.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package public
|
||||
|
||||
const StockDetailLockKey = "stock:lock:skuId-%s"
|
||||
|
||||
// 消费者配置(从 Redis Stream 消费请求)
|
||||
const StockDetailQueueName = "assets:stock:detail:request:stream" // 请求 Stream 键名(与发消息的key一致)
|
||||
const StockDetailGroupName = "assets:stock:detail:consumer:group" // 消费者组名
|
||||
const StockDetailConsumerName = "message-consumer-1" // 消费者名称(唯一标识)
|
||||
const StockDetailPrefetchCount = 1 // 批处理大小(每次读取1条)
|
||||
const StockDetailAutoAck = false // ACK是否自动确认(true自动确认,false不确认)
|
||||
|
||||
// 业务自增序列号前缀 Redis Key
|
||||
const (
|
||||
StockInventoryNoKeyPrefix = "IC" // 序列号Key前缀,如 IC-202602101215-000001
|
||||
StockInboundNoKeyPrefix = "INB" // 序列号Key前缀,如 INB-202602101215-000001
|
||||
StockBatchNoKeyPrefix = "BATCH" // 序列号Key前缀,如 BATCH-202602101215-000001
|
||||
)
|
||||
145
consts/public/sync_platform.go
Normal file
145
consts/public/sync_platform.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package public
|
||||
|
||||
import "fmt"
|
||||
|
||||
// SyncPlatform 同步渠道平台枚举
|
||||
type SyncPlatform string
|
||||
|
||||
const (
|
||||
SyncPlatformTaobao SyncPlatform = "taobao" // 淘宝
|
||||
SyncPlatformJD SyncPlatform = "jd" // 京东
|
||||
SyncPlatformKuaishou SyncPlatform = "kuaishou" // 快手
|
||||
SyncPlatformDouyin SyncPlatform = "douyin" // 抖音
|
||||
SyncPlatformXiaohongshu SyncPlatform = "xiaohongshu" // 小红书
|
||||
SyncPlatformPinduoduo SyncPlatform = "pinduoduo" // 拼多多
|
||||
SyncPlatformXianyu SyncPlatform = "xianyu" // 闲鱼
|
||||
SyncPlatformBlockchain SyncPlatform = "blockchain" // 区块链平台
|
||||
SyncPlatformInternal SyncPlatform = "internal" // 内部平台
|
||||
)
|
||||
|
||||
// SyncStatus 同步状态枚举
|
||||
type SyncStatus string
|
||||
|
||||
const (
|
||||
SyncStatusPending SyncStatus = "pending" // 等待同步
|
||||
SyncStatusSyncing SyncStatus = "syncing" // 同步中
|
||||
SyncStatusSuccess SyncStatus = "success" // 同步成功
|
||||
SyncStatusFailed SyncStatus = "failed" // 同步失败
|
||||
)
|
||||
|
||||
// SyncType 同步类型
|
||||
type SyncType string
|
||||
|
||||
const (
|
||||
SyncTypeIncremental SyncType = "incremental" // 增量同步
|
||||
)
|
||||
|
||||
// PlatformSyncConfig 平台同步配置结构
|
||||
type PlatformSyncConfig struct {
|
||||
Platform SyncPlatform // 平台名称
|
||||
IsEnabled bool // 是否启用
|
||||
SyncInterval int // 同步间隔(秒)
|
||||
BatchSize int // 批量同步数量
|
||||
MaxRetries int // 最大重试次数
|
||||
APIEndpoint string // API端点地址
|
||||
Description string // 平台描述
|
||||
}
|
||||
|
||||
// GetPlatformSyncConfig 获取平台默认同步配置
|
||||
func GetPlatformSyncConfig(platform SyncPlatform) (PlatformSyncConfig, error) {
|
||||
switch platform {
|
||||
case SyncPlatformTaobao:
|
||||
return PlatformSyncConfig{
|
||||
Platform: SyncPlatformTaobao,
|
||||
IsEnabled: true,
|
||||
SyncInterval: 300, // 5分钟
|
||||
BatchSize: 50, // 淘宝API限制较严
|
||||
MaxRetries: 3,
|
||||
APIEndpoint: "https://eco.taobao.com/router/rest",
|
||||
Description: "淘宝电商平台,API限制严格",
|
||||
}, nil
|
||||
case SyncPlatformJD:
|
||||
return PlatformSyncConfig{
|
||||
Platform: SyncPlatformJD,
|
||||
IsEnabled: true,
|
||||
SyncInterval: 240, // 4分钟
|
||||
BatchSize: 100, // 京东API支持较大批次
|
||||
MaxRetries: 3,
|
||||
APIEndpoint: "https://api.jd.com/routerjson",
|
||||
Description: "京东电商平台,API相对稳定",
|
||||
}, nil
|
||||
case SyncPlatformKuaishou:
|
||||
return PlatformSyncConfig{
|
||||
Platform: SyncPlatformKuaishou,
|
||||
IsEnabled: true,
|
||||
SyncInterval: 180, // 3分钟,直播数据更新快
|
||||
BatchSize: 80,
|
||||
MaxRetries: 2, // 快手API相对不稳定
|
||||
APIEndpoint: "https://open.kuaishou.com/api",
|
||||
Description: "快手直播平台,数据更新频繁",
|
||||
}, nil
|
||||
case SyncPlatformDouyin:
|
||||
return PlatformSyncConfig{
|
||||
Platform: SyncPlatformDouyin,
|
||||
IsEnabled: true,
|
||||
SyncInterval: 120, // 2分钟,内容更新非常频繁
|
||||
BatchSize: 60,
|
||||
MaxRetries: 3,
|
||||
APIEndpoint: "https://open.douyin.com/api",
|
||||
Description: "抖音短视频平台,实时性要求高",
|
||||
}, nil
|
||||
case SyncPlatformXiaohongshu:
|
||||
return PlatformSyncConfig{
|
||||
Platform: SyncPlatformXiaohongshu,
|
||||
IsEnabled: true,
|
||||
SyncInterval: 300, // 5分钟
|
||||
BatchSize: 40, // 小红书API限制严格
|
||||
MaxRetries: 2,
|
||||
APIEndpoint: "https://open.xiaohongshu.com/api",
|
||||
Description: "小红书内容平台,API调用频率限制严格",
|
||||
}, nil
|
||||
case SyncPlatformPinduoduo:
|
||||
return PlatformSyncConfig{
|
||||
Platform: SyncPlatformPinduoduo,
|
||||
IsEnabled: true,
|
||||
SyncInterval: 360, // 6分钟,避免频率限制
|
||||
BatchSize: 120, // 拼多多支持大批次
|
||||
MaxRetries: 3,
|
||||
APIEndpoint: "https://open.pinduoduo.com/api",
|
||||
Description: "拼多多电商平台,需要控制调用频率",
|
||||
}, nil
|
||||
case SyncPlatformXianyu:
|
||||
return PlatformSyncConfig{
|
||||
Platform: SyncPlatformXianyu,
|
||||
IsEnabled: false, // 默认关闭
|
||||
SyncInterval: 600, // 10分钟,闲鱼更新较慢
|
||||
BatchSize: 30,
|
||||
MaxRetries: 1,
|
||||
APIEndpoint: "https://api.xianyu.com/api",
|
||||
Description: "闲鱼二手平台,数据更新较慢,谨慎使用",
|
||||
}, nil
|
||||
case SyncPlatformBlockchain:
|
||||
return PlatformSyncConfig{
|
||||
Platform: SyncPlatformBlockchain,
|
||||
IsEnabled: true,
|
||||
SyncInterval: 60, // 1分钟,需要高实时性
|
||||
BatchSize: 20, // 区块链数据复杂,减小批次
|
||||
MaxRetries: 5, // 区块链网络可能不稳定
|
||||
APIEndpoint: "https://api.blockchain.com/api",
|
||||
Description: "区块链平台,数据需要高实时性和稳定性",
|
||||
}, nil
|
||||
case SyncPlatformInternal:
|
||||
return PlatformSyncConfig{
|
||||
Platform: SyncPlatformInternal,
|
||||
IsEnabled: true,
|
||||
SyncInterval: 30, // 30秒,内部系统实时性高
|
||||
BatchSize: 200, // 内部系统支持大批次
|
||||
MaxRetries: 1, // 内部系统稳定
|
||||
APIEndpoint: "http://localhost:3004/api",
|
||||
Description: "内部系统平台,高实时性和大批次处理能力",
|
||||
}, nil
|
||||
default:
|
||||
// 返回错误,未知平台
|
||||
return PlatformSyncConfig{}, fmt.Errorf("unsupported sync platform: %s", platform)
|
||||
}
|
||||
}
|
||||
21
consts/stock/batch_status.go
Normal file
21
consts/stock/batch_status.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package stock
|
||||
|
||||
// BatchStatus 批次状态枚举
|
||||
type BatchStatus int
|
||||
|
||||
const (
|
||||
BatchStatusActive BatchStatus = 1 // 活跃
|
||||
BatchStatusExpiring BatchStatus = 2 // 临期
|
||||
BatchStatusExpired BatchStatus = 3 // 过期
|
||||
BatchStatusSoldOut BatchStatus = 4 // 售罄
|
||||
)
|
||||
|
||||
// GetAllBatchStatuses 获取所有批次状态
|
||||
func GetAllBatchStatuses() []BatchStatus {
|
||||
return []BatchStatus{
|
||||
BatchStatusActive,
|
||||
BatchStatusExpiring,
|
||||
BatchStatusExpired,
|
||||
BatchStatusSoldOut,
|
||||
}
|
||||
}
|
||||
57
consts/stock/capacity_unit_area.go
Normal file
57
consts/stock/capacity_unit_area.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package stock
|
||||
|
||||
// CapacityUnitArea 面积单位枚举
|
||||
type CapacityUnitArea string
|
||||
|
||||
const (
|
||||
CapacityUnitAreaSquareM CapacityUnitArea = "M2" // 平方米
|
||||
CapacityUnitAreaSquareFT CapacityUnitArea = "FT2" // 平方英尺
|
||||
CapacityUnitAreaSquareIN CapacityUnitArea = "IN2" // 平方英寸
|
||||
CapacityUnitAreaSquareCM CapacityUnitArea = "CM2" // 平方厘米
|
||||
)
|
||||
|
||||
// GetAllCapacityUnitAreas 获取所有面积单位
|
||||
func GetAllCapacityUnitAreas() []CapacityUnitArea {
|
||||
return []CapacityUnitArea{
|
||||
CapacityUnitAreaSquareM,
|
||||
CapacityUnitAreaSquareFT,
|
||||
CapacityUnitAreaSquareIN,
|
||||
CapacityUnitAreaSquareCM,
|
||||
}
|
||||
}
|
||||
|
||||
type CapacityUnitAreaKeyValue struct {
|
||||
Key CapacityUnitArea
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
CapacityUnitAreaSquareMKeyValue = CapacityUnitAreaKeyValue{Key: CapacityUnitAreaSquareM, Value: "平方米"}
|
||||
CapacityUnitAreaSquareFTKeyValue = CapacityUnitAreaKeyValue{Key: CapacityUnitAreaSquareFT, Value: "平方英尺"}
|
||||
CapacityUnitAreaSquareINKeyValue = CapacityUnitAreaKeyValue{Key: CapacityUnitAreaSquareIN, Value: "平方英寸"}
|
||||
CapacityUnitAreaSquareCMKeyValue = CapacityUnitAreaKeyValue{Key: CapacityUnitAreaSquareCM, Value: "平方厘米"}
|
||||
)
|
||||
|
||||
func GetAllCapacityUnitAreaKeyValue() []CapacityUnitAreaKeyValue {
|
||||
return []CapacityUnitAreaKeyValue{
|
||||
CapacityUnitAreaSquareMKeyValue,
|
||||
CapacityUnitAreaSquareFTKeyValue,
|
||||
CapacityUnitAreaSquareINKeyValue,
|
||||
CapacityUnitAreaSquareCMKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var capacityUnitAreaValueMap = map[CapacityUnitArea]string{
|
||||
CapacityUnitAreaSquareM: CapacityUnitAreaSquareMKeyValue.Value,
|
||||
CapacityUnitAreaSquareFT: CapacityUnitAreaSquareFTKeyValue.Value,
|
||||
CapacityUnitAreaSquareIN: CapacityUnitAreaSquareINKeyValue.Value,
|
||||
CapacityUnitAreaSquareCM: CapacityUnitAreaSquareCMKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetCapacityUnitAreaValueByKey(key CapacityUnitArea) (value string) {
|
||||
value, exists := capacityUnitAreaValueMap[key]
|
||||
if !exists {
|
||||
value = "未知单位"
|
||||
}
|
||||
return
|
||||
}
|
||||
72
consts/stock/capacity_unit_length.go
Normal file
72
consts/stock/capacity_unit_length.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package stock
|
||||
|
||||
// CapacityUnitLength 长度单位枚举
|
||||
type CapacityUnitLength string
|
||||
|
||||
const (
|
||||
CapacityUnitLengthM CapacityUnitLength = "M" // 米
|
||||
CapacityUnitLengthCM CapacityUnitLength = "CM" // 厘米
|
||||
CapacityUnitLengthMM CapacityUnitLength = "MM" // 毫米
|
||||
CapacityUnitLengthKM CapacityUnitLength = "KM" // 千米
|
||||
CapacityUnitLengthFT CapacityUnitLength = "FT" // 英尺
|
||||
CapacityUnitLengthIN CapacityUnitLength = "IN" // 英寸
|
||||
CapacityUnitLengthYD CapacityUnitLength = "YD" // 码
|
||||
)
|
||||
|
||||
// GetAllCapacityUnitLengths 获取所有长度单位
|
||||
func GetAllCapacityUnitLengths() []CapacityUnitLength {
|
||||
return []CapacityUnitLength{
|
||||
CapacityUnitLengthM,
|
||||
CapacityUnitLengthCM,
|
||||
CapacityUnitLengthMM,
|
||||
CapacityUnitLengthKM,
|
||||
CapacityUnitLengthFT,
|
||||
CapacityUnitLengthIN,
|
||||
CapacityUnitLengthYD,
|
||||
}
|
||||
}
|
||||
|
||||
type CapacityUnitLengthKeyValue struct {
|
||||
Key CapacityUnitLength
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
CapacityUnitLengthMKeyValue = CapacityUnitLengthKeyValue{Key: CapacityUnitLengthM, Value: "米"}
|
||||
CapacityUnitLengthCMKeyValue = CapacityUnitLengthKeyValue{Key: CapacityUnitLengthCM, Value: "厘米"}
|
||||
CapacityUnitLengthMMKeyValue = CapacityUnitLengthKeyValue{Key: CapacityUnitLengthMM, Value: "毫米"}
|
||||
CapacityUnitLengthKMKeyValue = CapacityUnitLengthKeyValue{Key: CapacityUnitLengthKM, Value: "千米"}
|
||||
CapacityUnitLengthFTKeyValue = CapacityUnitLengthKeyValue{Key: CapacityUnitLengthFT, Value: "英尺"}
|
||||
CapacityUnitLengthINKeyValue = CapacityUnitLengthKeyValue{Key: CapacityUnitLengthIN, Value: "英寸"}
|
||||
CapacityUnitLengthYDKeyValue = CapacityUnitLengthKeyValue{Key: CapacityUnitLengthYD, Value: "码"}
|
||||
)
|
||||
|
||||
func GetAllCapacityUnitLengthKeyValue() []CapacityUnitLengthKeyValue {
|
||||
return []CapacityUnitLengthKeyValue{
|
||||
CapacityUnitLengthMKeyValue,
|
||||
CapacityUnitLengthCMKeyValue,
|
||||
CapacityUnitLengthMMKeyValue,
|
||||
CapacityUnitLengthKMKeyValue,
|
||||
CapacityUnitLengthFTKeyValue,
|
||||
CapacityUnitLengthINKeyValue,
|
||||
CapacityUnitLengthYDKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var capacityUnitLengthValueMap = map[CapacityUnitLength]string{
|
||||
CapacityUnitLengthM: CapacityUnitLengthMKeyValue.Value,
|
||||
CapacityUnitLengthCM: CapacityUnitLengthCMKeyValue.Value,
|
||||
CapacityUnitLengthMM: CapacityUnitLengthMMKeyValue.Value,
|
||||
CapacityUnitLengthKM: CapacityUnitLengthKMKeyValue.Value,
|
||||
CapacityUnitLengthFT: CapacityUnitLengthFTKeyValue.Value,
|
||||
CapacityUnitLengthIN: CapacityUnitLengthINKeyValue.Value,
|
||||
CapacityUnitLengthYD: CapacityUnitLengthYDKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetCapacityUnitLengthValueByKey(key CapacityUnitLength) (value string) {
|
||||
value, exists := capacityUnitLengthValueMap[key]
|
||||
if !exists {
|
||||
value = "未知单位"
|
||||
}
|
||||
return
|
||||
}
|
||||
252
consts/stock/capacity_unit_packaging.go
Normal file
252
consts/stock/capacity_unit_packaging.go
Normal file
@@ -0,0 +1,252 @@
|
||||
package stock
|
||||
|
||||
// CapacityUnitPackaging 包装单位枚举
|
||||
type CapacityUnitPackaging string
|
||||
|
||||
const (
|
||||
// 纸箱类
|
||||
CapacityUnitPackagingCartonInner CapacityUnitPackaging = "CARTON_INNER" // 内盒
|
||||
CapacityUnitPackagingCartonOuter CapacityUnitPackaging = "CARTON_OUTER" // 外箱
|
||||
CapacityUnitPackagingCarton CapacityUnitPackaging = "CARTON" // 纸箱
|
||||
CapacityUnitPackagingCase CapacityUnitPackaging = "CASE" // 箱/盒
|
||||
CapacityUnitPackagingBox CapacityUnitPackaging = "BOX" // 箱
|
||||
CapacityUnitPackagingMiniBox CapacityUnitPackaging = "MINI_BOX" // 迷你盒
|
||||
|
||||
// 托盘/容器类
|
||||
CapacityUnitPackagingPallet CapacityUnitPackaging = "PALLET" // 托盘
|
||||
CapacityUnitPackagingTray CapacityUnitPackaging = "TRAY" // 托盘/托架
|
||||
CapacityUnitPackagingContainer CapacityUnitPackaging = "CONTAINER" // 集装箱/货柜
|
||||
CapacityUnitPackagingBin CapacityUnitPackaging = "BIN" // 料箱
|
||||
CapacityUnitPackagingCrate CapacityUnitPackaging = "CRATE" // 条板箱
|
||||
CapacityUnitPackagingBasket CapacityUnitPackaging = "BASKET" // 篮子
|
||||
CapacityUnitPackagingCart CapacityUnitPackaging = "CART" // 手推车
|
||||
|
||||
// 袋/包/捆类
|
||||
CapacityUnitPackagingBag CapacityUnitPackaging = "BAG" // 袋
|
||||
CapacityUnitPackagingSack CapacityUnitPackaging = "SACK" // 麻袋
|
||||
CapacityUnitPackagingPack CapacityUnitPackaging = "PACK" // 包
|
||||
CapacityUnitPackagingBundle CapacityUnitPackaging = "BUNDLE" // 捆
|
||||
CapacityUnitPackagingBale CapacityUnitPackaging = "BALE" // 大包/捆
|
||||
CapacityUnitPackagingPacket CapacityUnitPackaging = "PACKET" // 小包
|
||||
|
||||
// 瓶/罐/桶类
|
||||
CapacityUnitPackagingBottle CapacityUnitPackaging = "BOTTLE" // 瓶
|
||||
CapacityUnitPackagingDrum CapacityUnitPackaging = "DRUM" // 桶
|
||||
CapacityUnitPackagingJar CapacityUnitPackaging = "JAR" // 罐/瓶
|
||||
CapacityUnitPackagingCan CapacityUnitPackaging = "CAN" // 罐/听
|
||||
CapacityUnitPackagingBarrel CapacityUnitPackaging = "BARREL" // 大桶
|
||||
CapacityUnitPackagingKeg CapacityUnitPackaging = "KEG" // 小桶
|
||||
CapacityUnitPackagingTin CapacityUnitPackaging = "TIN" // 锡罐
|
||||
|
||||
// 卷/轴/管类
|
||||
CapacityUnitPackagingRoll CapacityUnitPackaging = "ROLL" // 卷
|
||||
CapacityUnitPackagingReel CapacityUnitPackaging = "REEL" // 卷盘
|
||||
CapacityUnitPackagingSpool CapacityUnitPackaging = "SPOOL" // 线轴
|
||||
CapacityUnitPackagingTube CapacityUnitPackaging = "TUBE" // 筒/管
|
||||
CapacityUnitPackagingCoil CapacityUnitPackaging = "COIL" // 线圈
|
||||
|
||||
// 板/片/块类
|
||||
CapacityUnitPackagingSheet CapacityUnitPackaging = "SHEET" // 张/片
|
||||
CapacityUnitPackagingPanel CapacityUnitPackaging = "PANEL" // 板
|
||||
CapacityUnitPackagingBlock CapacityUnitPackaging = "BLOCK" // 块
|
||||
CapacityUnitPackagingPlate CapacityUnitPackaging = "PLATE" // 板/片
|
||||
CapacityUnitPackagingSlab CapacityUnitPackaging = "SLAB" // 厚板
|
||||
)
|
||||
|
||||
// GetAllCapacityUnitPackaging 获取所有包装单位
|
||||
func GetAllCapacityUnitPackaging() []CapacityUnitPackaging {
|
||||
return []CapacityUnitPackaging{
|
||||
// 纸箱类
|
||||
CapacityUnitPackagingCartonInner,
|
||||
CapacityUnitPackagingCartonOuter,
|
||||
CapacityUnitPackagingCarton,
|
||||
CapacityUnitPackagingCase,
|
||||
CapacityUnitPackagingBox,
|
||||
CapacityUnitPackagingMiniBox,
|
||||
// 托盘/容器类
|
||||
CapacityUnitPackagingPallet,
|
||||
CapacityUnitPackagingTray,
|
||||
CapacityUnitPackagingContainer,
|
||||
CapacityUnitPackagingBin,
|
||||
CapacityUnitPackagingCrate,
|
||||
CapacityUnitPackagingBasket,
|
||||
CapacityUnitPackagingCart,
|
||||
// 袋/包/捆类
|
||||
CapacityUnitPackagingBag,
|
||||
CapacityUnitPackagingSack,
|
||||
CapacityUnitPackagingPack,
|
||||
CapacityUnitPackagingBundle,
|
||||
CapacityUnitPackagingBale,
|
||||
CapacityUnitPackagingPacket,
|
||||
// 瓶/罐/桶类
|
||||
CapacityUnitPackagingBottle,
|
||||
CapacityUnitPackagingDrum,
|
||||
CapacityUnitPackagingJar,
|
||||
CapacityUnitPackagingCan,
|
||||
CapacityUnitPackagingBarrel,
|
||||
CapacityUnitPackagingKeg,
|
||||
CapacityUnitPackagingTin,
|
||||
// 卷/轴/管类
|
||||
CapacityUnitPackagingRoll,
|
||||
CapacityUnitPackagingReel,
|
||||
CapacityUnitPackagingSpool,
|
||||
CapacityUnitPackagingTube,
|
||||
CapacityUnitPackagingCoil,
|
||||
// 板/片/块类
|
||||
CapacityUnitPackagingSheet,
|
||||
CapacityUnitPackagingPanel,
|
||||
CapacityUnitPackagingBlock,
|
||||
CapacityUnitPackagingPlate,
|
||||
CapacityUnitPackagingSlab,
|
||||
}
|
||||
}
|
||||
|
||||
type CapacityUnitPackagingKeyValue struct {
|
||||
Key CapacityUnitPackaging
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
// 纸箱类
|
||||
CapacityUnitPackagingCartonInnerKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingCartonInner, Value: "内盒"}
|
||||
CapacityUnitPackagingCartonOuterKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingCartonOuter, Value: "外箱"}
|
||||
CapacityUnitPackagingCartonKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingCarton, Value: "纸箱"}
|
||||
CapacityUnitPackagingCaseKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingCase, Value: "箱/盒"}
|
||||
CapacityUnitPackagingBoxKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingBox, Value: "箱"}
|
||||
CapacityUnitPackagingMiniBoxKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingMiniBox, Value: "迷你盒"}
|
||||
// 托盘/容器类
|
||||
CapacityUnitPackagingPalletKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingPallet, Value: "托盘"}
|
||||
CapacityUnitPackagingTrayKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingTray, Value: "托盘/托架"}
|
||||
CapacityUnitPackagingContainerKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingContainer, Value: "集装箱/货柜"}
|
||||
CapacityUnitPackagingBinKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingBin, Value: "料箱"}
|
||||
CapacityUnitPackagingCrateKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingCrate, Value: "条板箱"}
|
||||
CapacityUnitPackagingBasketKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingBasket, Value: "篮子"}
|
||||
CapacityUnitPackagingCartKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingCart, Value: "手推车"}
|
||||
// 袋/包/捆类
|
||||
CapacityUnitPackagingBagKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingBag, Value: "袋"}
|
||||
CapacityUnitPackagingSackKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingSack, Value: "麻袋"}
|
||||
CapacityUnitPackagingPackKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingPack, Value: "包"}
|
||||
CapacityUnitPackagingBundleKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingBundle, Value: "捆"}
|
||||
CapacityUnitPackagingBaleKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingBale, Value: "大包/捆"}
|
||||
CapacityUnitPackagingPacketKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingPacket, Value: "小包"}
|
||||
// 瓶/罐/桶类
|
||||
CapacityUnitPackagingBottleKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingBottle, Value: "瓶"}
|
||||
CapacityUnitPackagingDrumKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingDrum, Value: "桶"}
|
||||
CapacityUnitPackagingJarKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingJar, Value: "罐/瓶"}
|
||||
CapacityUnitPackagingCanKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingCan, Value: "罐/听"}
|
||||
CapacityUnitPackagingBarrelKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingBarrel, Value: "大桶"}
|
||||
CapacityUnitPackagingKegKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingKeg, Value: "小桶"}
|
||||
CapacityUnitPackagingTinKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingTin, Value: "锡罐"}
|
||||
// 卷/轴/管类
|
||||
CapacityUnitPackagingRollKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingRoll, Value: "卷"}
|
||||
CapacityUnitPackagingReelKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingReel, Value: "卷盘"}
|
||||
CapacityUnitPackagingSpoolKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingSpool, Value: "线轴"}
|
||||
CapacityUnitPackagingTubeKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingTube, Value: "筒/管"}
|
||||
CapacityUnitPackagingCoilKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingCoil, Value: "线圈"}
|
||||
// 板/片/块类
|
||||
CapacityUnitPackagingSheetKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingSheet, Value: "张/片"}
|
||||
CapacityUnitPackagingPanelKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingPanel, Value: "板"}
|
||||
CapacityUnitPackagingBlockKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingBlock, Value: "块"}
|
||||
CapacityUnitPackagingPlateKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingPlate, Value: "板/片"}
|
||||
CapacityUnitPackagingSlabKeyValue = CapacityUnitPackagingKeyValue{Key: CapacityUnitPackagingSlab, Value: "厚板"}
|
||||
)
|
||||
|
||||
func GetAllCapacityUnitPackagingKeyValue() []CapacityUnitPackagingKeyValue {
|
||||
return []CapacityUnitPackagingKeyValue{
|
||||
// 纸箱类
|
||||
CapacityUnitPackagingCartonInnerKeyValue,
|
||||
CapacityUnitPackagingCartonOuterKeyValue,
|
||||
CapacityUnitPackagingCartonKeyValue,
|
||||
CapacityUnitPackagingCaseKeyValue,
|
||||
CapacityUnitPackagingBoxKeyValue,
|
||||
CapacityUnitPackagingMiniBoxKeyValue,
|
||||
// 托盘/容器类
|
||||
CapacityUnitPackagingPalletKeyValue,
|
||||
CapacityUnitPackagingTrayKeyValue,
|
||||
CapacityUnitPackagingContainerKeyValue,
|
||||
CapacityUnitPackagingBinKeyValue,
|
||||
CapacityUnitPackagingCrateKeyValue,
|
||||
CapacityUnitPackagingBasketKeyValue,
|
||||
CapacityUnitPackagingCartKeyValue,
|
||||
// 袋/包/捆类
|
||||
CapacityUnitPackagingBagKeyValue,
|
||||
CapacityUnitPackagingSackKeyValue,
|
||||
CapacityUnitPackagingPackKeyValue,
|
||||
CapacityUnitPackagingBundleKeyValue,
|
||||
CapacityUnitPackagingBaleKeyValue,
|
||||
CapacityUnitPackagingPacketKeyValue,
|
||||
// 瓶/罐/桶类
|
||||
CapacityUnitPackagingBottleKeyValue,
|
||||
CapacityUnitPackagingDrumKeyValue,
|
||||
CapacityUnitPackagingJarKeyValue,
|
||||
CapacityUnitPackagingCanKeyValue,
|
||||
CapacityUnitPackagingBarrelKeyValue,
|
||||
CapacityUnitPackagingKegKeyValue,
|
||||
CapacityUnitPackagingTinKeyValue,
|
||||
// 卷/轴/管类
|
||||
CapacityUnitPackagingRollKeyValue,
|
||||
CapacityUnitPackagingReelKeyValue,
|
||||
CapacityUnitPackagingSpoolKeyValue,
|
||||
CapacityUnitPackagingTubeKeyValue,
|
||||
CapacityUnitPackagingCoilKeyValue,
|
||||
// 板/片/块类
|
||||
CapacityUnitPackagingSheetKeyValue,
|
||||
CapacityUnitPackagingPanelKeyValue,
|
||||
CapacityUnitPackagingBlockKeyValue,
|
||||
CapacityUnitPackagingPlateKeyValue,
|
||||
CapacityUnitPackagingSlabKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var capacityUnitPackagingValueMap = map[CapacityUnitPackaging]string{
|
||||
// 纸箱类
|
||||
CapacityUnitPackagingCartonInner: CapacityUnitPackagingCartonInnerKeyValue.Value,
|
||||
CapacityUnitPackagingCartonOuter: CapacityUnitPackagingCartonOuterKeyValue.Value,
|
||||
CapacityUnitPackagingCarton: CapacityUnitPackagingCartonKeyValue.Value,
|
||||
CapacityUnitPackagingCase: CapacityUnitPackagingCaseKeyValue.Value,
|
||||
CapacityUnitPackagingBox: CapacityUnitPackagingBoxKeyValue.Value,
|
||||
CapacityUnitPackagingMiniBox: CapacityUnitPackagingMiniBoxKeyValue.Value,
|
||||
// 托盘/容器类
|
||||
CapacityUnitPackagingPallet: CapacityUnitPackagingPalletKeyValue.Value,
|
||||
CapacityUnitPackagingTray: CapacityUnitPackagingTrayKeyValue.Value,
|
||||
CapacityUnitPackagingContainer: CapacityUnitPackagingContainerKeyValue.Value,
|
||||
CapacityUnitPackagingBin: CapacityUnitPackagingBinKeyValue.Value,
|
||||
CapacityUnitPackagingCrate: CapacityUnitPackagingCrateKeyValue.Value,
|
||||
CapacityUnitPackagingBasket: CapacityUnitPackagingBasketKeyValue.Value,
|
||||
CapacityUnitPackagingCart: CapacityUnitPackagingCartKeyValue.Value,
|
||||
// 袋/包/捆类
|
||||
CapacityUnitPackagingBag: CapacityUnitPackagingBagKeyValue.Value,
|
||||
CapacityUnitPackagingSack: CapacityUnitPackagingSackKeyValue.Value,
|
||||
CapacityUnitPackagingPack: CapacityUnitPackagingPackKeyValue.Value,
|
||||
CapacityUnitPackagingBundle: CapacityUnitPackagingBundleKeyValue.Value,
|
||||
CapacityUnitPackagingBale: CapacityUnitPackagingBaleKeyValue.Value,
|
||||
CapacityUnitPackagingPacket: CapacityUnitPackagingPacketKeyValue.Value,
|
||||
// 瓶/罐/桶类
|
||||
CapacityUnitPackagingBottle: CapacityUnitPackagingBottleKeyValue.Value,
|
||||
CapacityUnitPackagingDrum: CapacityUnitPackagingDrumKeyValue.Value,
|
||||
CapacityUnitPackagingJar: CapacityUnitPackagingJarKeyValue.Value,
|
||||
CapacityUnitPackagingCan: CapacityUnitPackagingCanKeyValue.Value,
|
||||
CapacityUnitPackagingBarrel: CapacityUnitPackagingBarrelKeyValue.Value,
|
||||
CapacityUnitPackagingKeg: CapacityUnitPackagingKegKeyValue.Value,
|
||||
CapacityUnitPackagingTin: CapacityUnitPackagingTinKeyValue.Value,
|
||||
// 卷/轴/管类
|
||||
CapacityUnitPackagingRoll: CapacityUnitPackagingRollKeyValue.Value,
|
||||
CapacityUnitPackagingReel: CapacityUnitPackagingReelKeyValue.Value,
|
||||
CapacityUnitPackagingSpool: CapacityUnitPackagingSpoolKeyValue.Value,
|
||||
CapacityUnitPackagingTube: CapacityUnitPackagingTubeKeyValue.Value,
|
||||
CapacityUnitPackagingCoil: CapacityUnitPackagingCoilKeyValue.Value,
|
||||
// 板/片/块类
|
||||
CapacityUnitPackagingSheet: CapacityUnitPackagingSheetKeyValue.Value,
|
||||
CapacityUnitPackagingPanel: CapacityUnitPackagingPanelKeyValue.Value,
|
||||
CapacityUnitPackagingBlock: CapacityUnitPackagingBlockKeyValue.Value,
|
||||
CapacityUnitPackagingPlate: CapacityUnitPackagingPlateKeyValue.Value,
|
||||
CapacityUnitPackagingSlab: CapacityUnitPackagingSlabKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetCapacityUnitPackagingValueByKey(key CapacityUnitPackaging) (value string) {
|
||||
value, exists := capacityUnitPackagingValueMap[key]
|
||||
if !exists {
|
||||
value = "未知单位"
|
||||
}
|
||||
return
|
||||
}
|
||||
92
consts/stock/capacity_unit_quantity.go
Normal file
92
consts/stock/capacity_unit_quantity.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package stock
|
||||
|
||||
// CapacityUnitQuantity 数量单位枚举
|
||||
type CapacityUnitQuantity string
|
||||
|
||||
const (
|
||||
CapacityUnitQuantityPCS CapacityUnitQuantity = "PCS" // 件
|
||||
CapacityUnitQuantityPiece CapacityUnitQuantity = "PIECE" // 个
|
||||
CapacityUnitQuantityUnit CapacityUnitQuantity = "UNIT" // 单位
|
||||
CapacityUnitQuantityItem CapacityUnitQuantity = "ITEM" // 项
|
||||
CapacityUnitQuantityEach CapacityUnitQuantity = "EACH" // 每一个
|
||||
CapacityUnitQuantityPair CapacityUnitQuantity = "PAIR" // 双/对
|
||||
CapacityUnitQuantitySet CapacityUnitQuantity = "SET" // 套
|
||||
CapacityUnitQuantityKit CapacityUnitQuantity = "KIT" // 成套件
|
||||
CapacityUnitQuantityGroup CapacityUnitQuantity = "GROUP" // 组
|
||||
CapacityUnitQuantityLot CapacityUnitQuantity = "LOT" // 批
|
||||
CapacityUnitQuantityBatch CapacityUnitQuantity = "BATCH" // 批次
|
||||
)
|
||||
|
||||
// GetAllCapacityUnitQuantities 获取所有数量单位
|
||||
func GetAllCapacityUnitQuantities() []CapacityUnitQuantity {
|
||||
return []CapacityUnitQuantity{
|
||||
CapacityUnitQuantityPCS,
|
||||
CapacityUnitQuantityPiece,
|
||||
CapacityUnitQuantityUnit,
|
||||
CapacityUnitQuantityItem,
|
||||
CapacityUnitQuantityEach,
|
||||
CapacityUnitQuantityPair,
|
||||
CapacityUnitQuantitySet,
|
||||
CapacityUnitQuantityKit,
|
||||
CapacityUnitQuantityGroup,
|
||||
CapacityUnitQuantityLot,
|
||||
CapacityUnitQuantityBatch,
|
||||
}
|
||||
}
|
||||
|
||||
type CapacityUnitQuantityKeyValue struct {
|
||||
Key CapacityUnitQuantity
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
CapacityUnitQuantityPCSKeyValue = CapacityUnitQuantityKeyValue{Key: CapacityUnitQuantityPCS, Value: "件"}
|
||||
CapacityUnitQuantityPieceKeyValue = CapacityUnitQuantityKeyValue{Key: CapacityUnitQuantityPiece, Value: "个"}
|
||||
CapacityUnitQuantityUnitKeyValue = CapacityUnitQuantityKeyValue{Key: CapacityUnitQuantityUnit, Value: "单位"}
|
||||
CapacityUnitQuantityItemKeyValue = CapacityUnitQuantityKeyValue{Key: CapacityUnitQuantityItem, Value: "项"}
|
||||
CapacityUnitQuantityEachKeyValue = CapacityUnitQuantityKeyValue{Key: CapacityUnitQuantityEach, Value: "每一个"}
|
||||
CapacityUnitQuantityPairKeyValue = CapacityUnitQuantityKeyValue{Key: CapacityUnitQuantityPair, Value: "双/对"}
|
||||
CapacityUnitQuantitySetKeyValue = CapacityUnitQuantityKeyValue{Key: CapacityUnitQuantitySet, Value: "套"}
|
||||
CapacityUnitQuantityKitKeyValue = CapacityUnitQuantityKeyValue{Key: CapacityUnitQuantityKit, Value: "成套件"}
|
||||
CapacityUnitQuantityGroupKeyValue = CapacityUnitQuantityKeyValue{Key: CapacityUnitQuantityGroup, Value: "组"}
|
||||
CapacityUnitQuantityLotKeyValue = CapacityUnitQuantityKeyValue{Key: CapacityUnitQuantityLot, Value: "批"}
|
||||
CapacityUnitQuantityBatchKeyValue = CapacityUnitQuantityKeyValue{Key: CapacityUnitQuantityBatch, Value: "批次"}
|
||||
)
|
||||
|
||||
func GetAllCapacityUnitQuantityKeyValue() []CapacityUnitQuantityKeyValue {
|
||||
return []CapacityUnitQuantityKeyValue{
|
||||
CapacityUnitQuantityPCSKeyValue,
|
||||
CapacityUnitQuantityPieceKeyValue,
|
||||
CapacityUnitQuantityUnitKeyValue,
|
||||
CapacityUnitQuantityItemKeyValue,
|
||||
CapacityUnitQuantityEachKeyValue,
|
||||
CapacityUnitQuantityPairKeyValue,
|
||||
CapacityUnitQuantitySetKeyValue,
|
||||
CapacityUnitQuantityKitKeyValue,
|
||||
CapacityUnitQuantityGroupKeyValue,
|
||||
CapacityUnitQuantityLotKeyValue,
|
||||
CapacityUnitQuantityBatchKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var capacityUnitQuantityValueMap = map[CapacityUnitQuantity]string{
|
||||
CapacityUnitQuantityPCS: CapacityUnitQuantityPCSKeyValue.Value,
|
||||
CapacityUnitQuantityPiece: CapacityUnitQuantityPieceKeyValue.Value,
|
||||
CapacityUnitQuantityUnit: CapacityUnitQuantityUnitKeyValue.Value,
|
||||
CapacityUnitQuantityItem: CapacityUnitQuantityItemKeyValue.Value,
|
||||
CapacityUnitQuantityEach: CapacityUnitQuantityEachKeyValue.Value,
|
||||
CapacityUnitQuantityPair: CapacityUnitQuantityPairKeyValue.Value,
|
||||
CapacityUnitQuantitySet: CapacityUnitQuantitySetKeyValue.Value,
|
||||
CapacityUnitQuantityKit: CapacityUnitQuantityKitKeyValue.Value,
|
||||
CapacityUnitQuantityGroup: CapacityUnitQuantityGroupKeyValue.Value,
|
||||
CapacityUnitQuantityLot: CapacityUnitQuantityLotKeyValue.Value,
|
||||
CapacityUnitQuantityBatch: CapacityUnitQuantityBatchKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetCapacityUnitQuantityValueByKey(key CapacityUnitQuantity) (value string) {
|
||||
value, exists := capacityUnitQuantityValueMap[key]
|
||||
if !exists {
|
||||
value = "未知单位"
|
||||
}
|
||||
return
|
||||
}
|
||||
67
consts/stock/capacity_unit_type.go
Normal file
67
consts/stock/capacity_unit_type.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package stock
|
||||
|
||||
// CapacityUnitType 容量单位类型枚举
|
||||
type CapacityUnitType string
|
||||
|
||||
const (
|
||||
CapacityUnitTypeQuantity CapacityUnitType = "quantity" // 数量单位
|
||||
CapacityUnitTypeWeight CapacityUnitType = "weight" // 重量单位
|
||||
CapacityUnitTypeVolume CapacityUnitType = "volume" // 体积单位
|
||||
CapacityUnitTypeArea CapacityUnitType = "area" // 面积单位
|
||||
CapacityUnitTypeLength CapacityUnitType = "length" // 长度单位
|
||||
CapacityUnitTypePackaging CapacityUnitType = "packaging" // 包装单位
|
||||
)
|
||||
|
||||
// GetAllCapacityUnitTypes 获取所有容量单位类型
|
||||
func GetAllCapacityUnitTypes() []CapacityUnitType {
|
||||
return []CapacityUnitType{
|
||||
CapacityUnitTypeQuantity,
|
||||
CapacityUnitTypeWeight,
|
||||
CapacityUnitTypeVolume,
|
||||
CapacityUnitTypeArea,
|
||||
CapacityUnitTypeLength,
|
||||
CapacityUnitTypePackaging,
|
||||
}
|
||||
}
|
||||
|
||||
type CapacityUnitTypeKeyValue struct {
|
||||
Key CapacityUnitType
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
CapacityUnitTypeQuantityKeyValue = CapacityUnitTypeKeyValue{Key: CapacityUnitTypeQuantity, Value: "数量单位"}
|
||||
CapacityUnitTypeWeightKeyValue = CapacityUnitTypeKeyValue{Key: CapacityUnitTypeWeight, Value: "重量单位"}
|
||||
CapacityUnitTypeVolumeKeyValue = CapacityUnitTypeKeyValue{Key: CapacityUnitTypeVolume, Value: "体积单位"}
|
||||
CapacityUnitTypeAreaKeyValue = CapacityUnitTypeKeyValue{Key: CapacityUnitTypeArea, Value: "面积单位"}
|
||||
CapacityUnitTypeLengthKeyValue = CapacityUnitTypeKeyValue{Key: CapacityUnitTypeLength, Value: "长度单位"}
|
||||
CapacityUnitTypePackagingKeyValue = CapacityUnitTypeKeyValue{Key: CapacityUnitTypePackaging, Value: "包装单位"}
|
||||
)
|
||||
|
||||
func GetAllCapacityUnitTypeKeyValue() []CapacityUnitTypeKeyValue {
|
||||
return []CapacityUnitTypeKeyValue{
|
||||
CapacityUnitTypeQuantityKeyValue,
|
||||
CapacityUnitTypeWeightKeyValue,
|
||||
CapacityUnitTypeVolumeKeyValue,
|
||||
CapacityUnitTypeAreaKeyValue,
|
||||
CapacityUnitTypeLengthKeyValue,
|
||||
CapacityUnitTypePackagingKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var capacityUnitTypeValueMap = map[CapacityUnitType]string{
|
||||
CapacityUnitTypeQuantity: CapacityUnitTypeQuantityKeyValue.Value,
|
||||
CapacityUnitTypeWeight: CapacityUnitTypeWeightKeyValue.Value,
|
||||
CapacityUnitTypeVolume: CapacityUnitTypeVolumeKeyValue.Value,
|
||||
CapacityUnitTypeArea: CapacityUnitTypeAreaKeyValue.Value,
|
||||
CapacityUnitTypeLength: CapacityUnitTypeLengthKeyValue.Value,
|
||||
CapacityUnitTypePackaging: CapacityUnitTypePackagingKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetCapacityUnitTypeValueByKey(key CapacityUnitType) (value string) {
|
||||
value, exists := capacityUnitTypeValueMap[key]
|
||||
if !exists {
|
||||
value = "未知类型"
|
||||
}
|
||||
return
|
||||
}
|
||||
62
consts/stock/capacity_unit_volume.go
Normal file
62
consts/stock/capacity_unit_volume.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package stock
|
||||
|
||||
// CapacityUnitVolume 体积单位枚举
|
||||
type CapacityUnitVolume string
|
||||
|
||||
const (
|
||||
CapacityUnitVolumeCBM CapacityUnitVolume = "CBM" // 立方米
|
||||
CapacityUnitVolumeM3 CapacityUnitVolume = "M3" // 立方米
|
||||
CapacityUnitVolumeL CapacityUnitVolume = "L" // 升
|
||||
CapacityUnitVolumeML CapacityUnitVolume = "ML" // 毫升
|
||||
CapacityUnitVolumeGAL CapacityUnitVolume = "GAL" // 加仑
|
||||
)
|
||||
|
||||
// GetAllCapacityUnitVolumes 获取所有体积单位
|
||||
func GetAllCapacityUnitVolumes() []CapacityUnitVolume {
|
||||
return []CapacityUnitVolume{
|
||||
CapacityUnitVolumeCBM,
|
||||
CapacityUnitVolumeM3,
|
||||
CapacityUnitVolumeL,
|
||||
CapacityUnitVolumeML,
|
||||
CapacityUnitVolumeGAL,
|
||||
}
|
||||
}
|
||||
|
||||
type CapacityUnitVolumeKeyValue struct {
|
||||
Key CapacityUnitVolume
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
CapacityUnitVolumeCBMKeyValue = CapacityUnitVolumeKeyValue{Key: CapacityUnitVolumeCBM, Value: "立方米"}
|
||||
CapacityUnitVolumeM3KeyValue = CapacityUnitVolumeKeyValue{Key: CapacityUnitVolumeM3, Value: "立方米"}
|
||||
CapacityUnitVolumeLKeyValue = CapacityUnitVolumeKeyValue{Key: CapacityUnitVolumeL, Value: "升"}
|
||||
CapacityUnitVolumeMLKeyValue = CapacityUnitVolumeKeyValue{Key: CapacityUnitVolumeML, Value: "毫升"}
|
||||
CapacityUnitVolumeGALKeyValue = CapacityUnitVolumeKeyValue{Key: CapacityUnitVolumeGAL, Value: "加仑"}
|
||||
)
|
||||
|
||||
func GetAllCapacityUnitVolumeKeyValue() []CapacityUnitVolumeKeyValue {
|
||||
return []CapacityUnitVolumeKeyValue{
|
||||
CapacityUnitVolumeCBMKeyValue,
|
||||
CapacityUnitVolumeM3KeyValue,
|
||||
CapacityUnitVolumeLKeyValue,
|
||||
CapacityUnitVolumeMLKeyValue,
|
||||
CapacityUnitVolumeGALKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var capacityUnitVolumeValueMap = map[CapacityUnitVolume]string{
|
||||
CapacityUnitVolumeCBM: CapacityUnitVolumeCBMKeyValue.Value,
|
||||
CapacityUnitVolumeM3: CapacityUnitVolumeM3KeyValue.Value,
|
||||
CapacityUnitVolumeL: CapacityUnitVolumeLKeyValue.Value,
|
||||
CapacityUnitVolumeML: CapacityUnitVolumeMLKeyValue.Value,
|
||||
CapacityUnitVolumeGAL: CapacityUnitVolumeGALKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetCapacityUnitVolumeValueByKey(key CapacityUnitVolume) (value string) {
|
||||
value, exists := capacityUnitVolumeValueMap[key]
|
||||
if !exists {
|
||||
value = "未知单位"
|
||||
}
|
||||
return
|
||||
}
|
||||
67
consts/stock/capacity_unit_weight.go
Normal file
67
consts/stock/capacity_unit_weight.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package stock
|
||||
|
||||
// CapacityUnitWeight 重量单位枚举
|
||||
type CapacityUnitWeight string
|
||||
|
||||
const (
|
||||
CapacityUnitWeightKG CapacityUnitWeight = "KG" // 千克
|
||||
CapacityUnitWeightTon CapacityUnitWeight = "TON" // 吨
|
||||
CapacityUnitWeightG CapacityUnitWeight = "G" // 克
|
||||
CapacityUnitWeightMG CapacityUnitWeight = "MG" // 毫克
|
||||
CapacityUnitWeightLB CapacityUnitWeight = "LB" // 磅
|
||||
CapacityUnitWeightOZ CapacityUnitWeight = "OZ" // 盎司
|
||||
)
|
||||
|
||||
// GetAllCapacityUnitWeights 获取所有重量单位
|
||||
func GetAllCapacityUnitWeights() []CapacityUnitWeight {
|
||||
return []CapacityUnitWeight{
|
||||
CapacityUnitWeightKG,
|
||||
CapacityUnitWeightTon,
|
||||
CapacityUnitWeightG,
|
||||
CapacityUnitWeightMG,
|
||||
CapacityUnitWeightLB,
|
||||
CapacityUnitWeightOZ,
|
||||
}
|
||||
}
|
||||
|
||||
type CapacityUnitWeightKeyValue struct {
|
||||
Key CapacityUnitWeight
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
CapacityUnitWeightKGKeyValue = CapacityUnitWeightKeyValue{Key: CapacityUnitWeightKG, Value: "千克"}
|
||||
CapacityUnitWeightTonKeyValue = CapacityUnitWeightKeyValue{Key: CapacityUnitWeightTon, Value: "吨"}
|
||||
CapacityUnitWeightGKeyValue = CapacityUnitWeightKeyValue{Key: CapacityUnitWeightG, Value: "克"}
|
||||
CapacityUnitWeightMGKeyValue = CapacityUnitWeightKeyValue{Key: CapacityUnitWeightMG, Value: "毫克"}
|
||||
CapacityUnitWeightLBKeyValue = CapacityUnitWeightKeyValue{Key: CapacityUnitWeightLB, Value: "磅"}
|
||||
CapacityUnitWeightOZKeyValue = CapacityUnitWeightKeyValue{Key: CapacityUnitWeightOZ, Value: "盎司"}
|
||||
)
|
||||
|
||||
func GetAllCapacityUnitWeightKeyValue() []CapacityUnitWeightKeyValue {
|
||||
return []CapacityUnitWeightKeyValue{
|
||||
CapacityUnitWeightKGKeyValue,
|
||||
CapacityUnitWeightTonKeyValue,
|
||||
CapacityUnitWeightGKeyValue,
|
||||
CapacityUnitWeightMGKeyValue,
|
||||
CapacityUnitWeightLBKeyValue,
|
||||
CapacityUnitWeightOZKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var capacityUnitWeightValueMap = map[CapacityUnitWeight]string{
|
||||
CapacityUnitWeightKG: CapacityUnitWeightKGKeyValue.Value,
|
||||
CapacityUnitWeightTon: CapacityUnitWeightTonKeyValue.Value,
|
||||
CapacityUnitWeightG: CapacityUnitWeightGKeyValue.Value,
|
||||
CapacityUnitWeightMG: CapacityUnitWeightMGKeyValue.Value,
|
||||
CapacityUnitWeightLB: CapacityUnitWeightLBKeyValue.Value,
|
||||
CapacityUnitWeightOZ: CapacityUnitWeightOZKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetCapacityUnitWeightValueByKey(key CapacityUnitWeight) (value string) {
|
||||
value, exists := capacityUnitWeightValueMap[key]
|
||||
if !exists {
|
||||
value = "未知单位"
|
||||
}
|
||||
return
|
||||
}
|
||||
45
consts/stock/discrepancy_type.go
Normal file
45
consts/stock/discrepancy_type.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package stock
|
||||
|
||||
// DiscrepancyType 差异类型枚举
|
||||
type DiscrepancyType int
|
||||
|
||||
const (
|
||||
DiscrepancyTypeNone DiscrepancyType = 0 // 无差异
|
||||
DiscrepancyTypeOverflow DiscrepancyType = 1 // 盘盈
|
||||
DiscrepancyTypeShortage DiscrepancyType = 2 // 盘亏
|
||||
DiscrepancyTypeWrongItem DiscrepancyType = 3 // 错货
|
||||
DiscrepancyTypeDamage DiscrepancyType = 4 // 损坏
|
||||
DiscrepancyTypeExpired DiscrepancyType = 5 // 过期
|
||||
)
|
||||
|
||||
// GetAllDiscrepancyTypes 获取所有差异类型
|
||||
func GetAllDiscrepancyTypes() []DiscrepancyType {
|
||||
return []DiscrepancyType{
|
||||
DiscrepancyTypeNone,
|
||||
DiscrepancyTypeOverflow,
|
||||
DiscrepancyTypeShortage,
|
||||
DiscrepancyTypeWrongItem,
|
||||
DiscrepancyTypeDamage,
|
||||
DiscrepancyTypeExpired,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取差异类型字符串表示
|
||||
func (d DiscrepancyType) String() string {
|
||||
switch d {
|
||||
case DiscrepancyTypeNone:
|
||||
return "无差异"
|
||||
case DiscrepancyTypeOverflow:
|
||||
return "盘盈"
|
||||
case DiscrepancyTypeShortage:
|
||||
return "盘亏"
|
||||
case DiscrepancyTypeWrongItem:
|
||||
return "错货"
|
||||
case DiscrepancyTypeDamage:
|
||||
return "损坏"
|
||||
case DiscrepancyTypeExpired:
|
||||
return "过期"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
38
consts/stock/expiry_message_type.go
Normal file
38
consts/stock/expiry_message_type.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package stock
|
||||
|
||||
// ExpiryMessageStatus 临期消息状态
|
||||
type ExpiryMessageStatus int
|
||||
|
||||
const (
|
||||
ExpiryMessageStatusPending ExpiryMessageStatus = 1 // 待处理
|
||||
ExpiryMessageStatusCompleted ExpiryMessageStatus = 2 // 已处理
|
||||
)
|
||||
|
||||
// ExpiryProcessMethod 临期处理方式
|
||||
type ExpiryProcessMethod int
|
||||
|
||||
const (
|
||||
ExpiryProcessMethodSupplierRecycle ExpiryProcessMethod = 1 // 供货商回收
|
||||
ExpiryProcessMethodReprocess ExpiryProcessMethod = 2 // 二次加工
|
||||
ExpiryProcessMethodScrap ExpiryProcessMethod = 3 // 报废
|
||||
ExpiryProcessMethodInternal ExpiryProcessMethod = 4 // 内部消化
|
||||
ExpiryProcessMethodPromotion ExpiryProcessMethod = 5 // 促销
|
||||
)
|
||||
|
||||
// GetProcessMethodName 获取处理方式名称
|
||||
func GetProcessMethodName(method ExpiryProcessMethod) string {
|
||||
switch method {
|
||||
case ExpiryProcessMethodSupplierRecycle:
|
||||
return "供货商回收"
|
||||
case ExpiryProcessMethodReprocess:
|
||||
return "二次加工"
|
||||
case ExpiryProcessMethodScrap:
|
||||
return "报废"
|
||||
case ExpiryProcessMethodInternal:
|
||||
return "内部消化"
|
||||
case ExpiryProcessMethodPromotion:
|
||||
return "促销"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
41
consts/stock/inventory_count_scope.go
Normal file
41
consts/stock/inventory_count_scope.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package stock
|
||||
|
||||
// InventoryCountScope 库存盘点范围枚举
|
||||
type InventoryCountScope int
|
||||
|
||||
const (
|
||||
InventoryCountScopeWarehouse InventoryCountScope = 1 // 按仓库盘点
|
||||
InventoryCountScopeZone InventoryCountScope = 2 // 按库区盘点
|
||||
InventoryCountScopeLocation InventoryCountScope = 3 // 按库位盘点
|
||||
InventoryCountScopeSku InventoryCountScope = 4 // 按SKU盘点
|
||||
InventoryCountScopeAsset InventoryCountScope = 5 // 按资产盘点
|
||||
)
|
||||
|
||||
// GetAllInventoryCountScopes 获取所有盘点范围
|
||||
func GetAllInventoryCountScopes() []InventoryCountScope {
|
||||
return []InventoryCountScope{
|
||||
InventoryCountScopeWarehouse,
|
||||
InventoryCountScopeZone,
|
||||
InventoryCountScopeLocation,
|
||||
InventoryCountScopeSku,
|
||||
InventoryCountScopeAsset,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取盘点范围字符串表示
|
||||
func (i InventoryCountScope) String() string {
|
||||
switch i {
|
||||
case InventoryCountScopeWarehouse:
|
||||
return "按仓库盘点"
|
||||
case InventoryCountScopeZone:
|
||||
return "按库区盘点"
|
||||
case InventoryCountScopeLocation:
|
||||
return "按库位盘点"
|
||||
case InventoryCountScopeSku:
|
||||
return "按SKU盘点"
|
||||
case InventoryCountScopeAsset:
|
||||
return "按资产盘点"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
33
consts/stock/inventory_count_status.go
Normal file
33
consts/stock/inventory_count_status.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package stock
|
||||
|
||||
// InventoryCountStatus 库存盘点状态枚举
|
||||
type InventoryCountStatus int
|
||||
|
||||
const (
|
||||
InventoryCountStatusInProgress InventoryCountStatus = 1 // 进行中
|
||||
InventoryCountStatusCompleted InventoryCountStatus = 2 // 已完成
|
||||
InventoryCountStatusCancelled InventoryCountStatus = 3 // 已取消
|
||||
)
|
||||
|
||||
// GetAllInventoryCountStatuses 获取所有盘点状态
|
||||
func GetAllInventoryCountStatuses() []InventoryCountStatus {
|
||||
return []InventoryCountStatus{
|
||||
InventoryCountStatusInProgress,
|
||||
InventoryCountStatusCompleted,
|
||||
InventoryCountStatusCancelled,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取盘点状态字符串表示
|
||||
func (i InventoryCountStatus) String() string {
|
||||
switch i {
|
||||
case InventoryCountStatusInProgress:
|
||||
return "进行中"
|
||||
case InventoryCountStatusCompleted:
|
||||
return "已完成"
|
||||
case InventoryCountStatusCancelled:
|
||||
return "已取消"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
29
consts/stock/inventory_count_type.go
Normal file
29
consts/stock/inventory_count_type.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package stock
|
||||
|
||||
// InventoryCountType 库存盘点类型枚举
|
||||
type InventoryCountType int
|
||||
|
||||
const (
|
||||
OpenPrice InventoryCountType = 1 // 明盘
|
||||
HiddenPrice InventoryCountType = 2 // 盲盘
|
||||
)
|
||||
|
||||
// GetAllInventoryCountTypes 获取所有盘点类型
|
||||
func GetAllInventoryCountTypes() []InventoryCountType {
|
||||
return []InventoryCountType{
|
||||
OpenPrice,
|
||||
HiddenPrice,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取盘点类型字符串表示
|
||||
func (i InventoryCountType) String() string {
|
||||
switch i {
|
||||
case OpenPrice:
|
||||
return "明盘"
|
||||
case HiddenPrice:
|
||||
return "盲盘"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
29
consts/stock/inventory_detail_status.go
Normal file
29
consts/stock/inventory_detail_status.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package stock
|
||||
|
||||
// InventoryDetailStatus 库存盘点明细状态枚举
|
||||
type InventoryDetailStatus int
|
||||
|
||||
const (
|
||||
InventoryDetailStatusPending InventoryDetailStatus = 1 // 待盘点(创建时默认)
|
||||
InventoryDetailStatusCompleted InventoryDetailStatus = 2 // 已完成(Excel导入后)
|
||||
)
|
||||
|
||||
// GetAllInventoryDetailStatuses 获取所有明细状态
|
||||
func GetAllInventoryDetailStatuses() []InventoryDetailStatus {
|
||||
return []InventoryDetailStatus{
|
||||
InventoryDetailStatusPending,
|
||||
InventoryDetailStatusCompleted,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取明细状态字符串表示
|
||||
func (i InventoryDetailStatus) String() string {
|
||||
switch i {
|
||||
case InventoryDetailStatusPending:
|
||||
return "待盘点"
|
||||
case InventoryDetailStatusCompleted:
|
||||
return "已完成"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
57
consts/stock/location_status.go
Normal file
57
consts/stock/location_status.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package stock
|
||||
|
||||
// LocationStatus 库位状态枚举
|
||||
type LocationStatus string
|
||||
|
||||
const (
|
||||
LocationStatusIdle LocationStatus = "idle" // 空闲
|
||||
LocationStatusOccupied LocationStatus = "occupied" // 占用
|
||||
LocationStatusDisabled LocationStatus = "disable" // 禁用
|
||||
LocationStatusReserved LocationStatus = "reserved" // 预留
|
||||
)
|
||||
|
||||
// GetAllLocationStatuses 获取所有库位状态
|
||||
func GetAllLocationStatuses() []LocationStatus {
|
||||
return []LocationStatus{
|
||||
LocationStatusIdle,
|
||||
LocationStatusOccupied,
|
||||
LocationStatusDisabled,
|
||||
LocationStatusReserved,
|
||||
}
|
||||
}
|
||||
|
||||
type LocationStatusKeyValue struct {
|
||||
Key LocationStatus
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
LocationStatusIdleKeyValue = LocationStatusKeyValue{Key: LocationStatusIdle, Value: "空闲"}
|
||||
LocationStatusOccupiedKeyValue = LocationStatusKeyValue{Key: LocationStatusOccupied, Value: "占用"}
|
||||
LocationStatusDisabledKeyValue = LocationStatusKeyValue{Key: LocationStatusDisabled, Value: "禁用"}
|
||||
LocationStatusReservedKeyValue = LocationStatusKeyValue{Key: LocationStatusReserved, Value: "预留"}
|
||||
)
|
||||
|
||||
func GetAllLocationStatusKeyValue() []LocationStatusKeyValue {
|
||||
return []LocationStatusKeyValue{
|
||||
LocationStatusIdleKeyValue,
|
||||
LocationStatusOccupiedKeyValue,
|
||||
LocationStatusDisabledKeyValue,
|
||||
LocationStatusReservedKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var locationStatusValueMap = map[LocationStatus]string{
|
||||
LocationStatusIdle: LocationStatusIdleKeyValue.Value,
|
||||
LocationStatusOccupied: LocationStatusOccupiedKeyValue.Value,
|
||||
LocationStatusDisabled: LocationStatusDisabledKeyValue.Value,
|
||||
LocationStatusReserved: LocationStatusReservedKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetLocationStatusValueByKey(key LocationStatus) (value string) {
|
||||
value, exists := locationStatusValueMap[key]
|
||||
if !exists {
|
||||
value = "未知状态"
|
||||
}
|
||||
return
|
||||
}
|
||||
72
consts/stock/location_type.go
Normal file
72
consts/stock/location_type.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package stock
|
||||
|
||||
// LocationType 库位类型枚举
|
||||
type LocationType string
|
||||
|
||||
const (
|
||||
LocationTypeShelf LocationType = "shelf" // 货架
|
||||
LocationTypeStack LocationType = "stack" // 堆垛
|
||||
LocationTypeCold LocationType = "cold" // 冷藏位
|
||||
LocationTypeFreeze LocationType = "freeze" // 冷冻位
|
||||
LocationTypeBin LocationType = "bin" // 料箱位
|
||||
LocationTypePallet LocationType = "pallet" // 托盘位
|
||||
LocationTypeFloor LocationType = "floor" // 地面堆放
|
||||
)
|
||||
|
||||
// GetAllLocationTypes 获取所有库位类型
|
||||
func GetAllLocationTypes() []LocationType {
|
||||
return []LocationType{
|
||||
LocationTypeShelf,
|
||||
LocationTypeStack,
|
||||
LocationTypeCold,
|
||||
LocationTypeFreeze,
|
||||
LocationTypeBin,
|
||||
LocationTypePallet,
|
||||
LocationTypeFloor,
|
||||
}
|
||||
}
|
||||
|
||||
type LocationTypeKeyValue struct {
|
||||
Key LocationType
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
LocationTypeShelfKeyValue = LocationTypeKeyValue{Key: LocationTypeShelf, Value: "货架"}
|
||||
LocationTypeStackKeyValue = LocationTypeKeyValue{Key: LocationTypeStack, Value: "堆垛"}
|
||||
LocationTypeColdKeyValue = LocationTypeKeyValue{Key: LocationTypeCold, Value: "冷藏位"}
|
||||
LocationTypeFreezeKeyValue = LocationTypeKeyValue{Key: LocationTypeFreeze, Value: "冷冻位"}
|
||||
LocationTypeBinKeyValue = LocationTypeKeyValue{Key: LocationTypeBin, Value: "料箱位"}
|
||||
LocationTypePalletKeyValue = LocationTypeKeyValue{Key: LocationTypePallet, Value: "托盘位"}
|
||||
LocationTypeFloorKeyValue = LocationTypeKeyValue{Key: LocationTypeFloor, Value: "地面堆放"}
|
||||
)
|
||||
|
||||
func GetAllLocationTypeKeyValue() []LocationTypeKeyValue {
|
||||
return []LocationTypeKeyValue{
|
||||
LocationTypeShelfKeyValue,
|
||||
LocationTypeStackKeyValue,
|
||||
LocationTypeColdKeyValue,
|
||||
LocationTypeFreezeKeyValue,
|
||||
LocationTypeBinKeyValue,
|
||||
LocationTypePalletKeyValue,
|
||||
LocationTypeFloorKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var locationTypeValueMap = map[LocationType]string{
|
||||
LocationTypeShelf: LocationTypeShelfKeyValue.Value,
|
||||
LocationTypeStack: LocationTypeStackKeyValue.Value,
|
||||
LocationTypeCold: LocationTypeColdKeyValue.Value,
|
||||
LocationTypeFreeze: LocationTypeFreezeKeyValue.Value,
|
||||
LocationTypeBin: LocationTypeBinKeyValue.Value,
|
||||
LocationTypePallet: LocationTypePalletKeyValue.Value,
|
||||
LocationTypeFloor: LocationTypeFloorKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetLocationTypeValueByKey(key LocationType) (value string) {
|
||||
value, exists := locationTypeValueMap[key]
|
||||
if !exists {
|
||||
value = "未知类型"
|
||||
}
|
||||
return
|
||||
}
|
||||
33
consts/stock/stock_location_type.go
Normal file
33
consts/stock/stock_location_type.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package stock
|
||||
|
||||
// StockLocationType 库存位置关联类型枚举
|
||||
type StockLocationType int
|
||||
|
||||
const (
|
||||
StockLocationTypeStockDetails StockLocationType = 1 // StockDetails库存的位置关联
|
||||
StockLocationTypePrivateStock StockLocationType = 2 // PrivateStock库存的位置关联
|
||||
StockLocationTypeStockBatch StockLocationType = 3 // StockBatch库存的位置关联
|
||||
)
|
||||
|
||||
// GetAllStockLocationTypes 获取所有库存位置关联类型
|
||||
func GetAllStockLocationTypes() []StockLocationType {
|
||||
return []StockLocationType{
|
||||
StockLocationTypeStockDetails,
|
||||
StockLocationTypePrivateStock,
|
||||
StockLocationTypeStockBatch,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取库存位置关联类型字符串表示
|
||||
func (s StockLocationType) String() string {
|
||||
switch s {
|
||||
case StockLocationTypeStockDetails:
|
||||
return "StockDetails库存"
|
||||
case StockLocationTypePrivateStock:
|
||||
return "PrivateStock库存"
|
||||
case StockLocationTypeStockBatch:
|
||||
return "StockBatch库存"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
17
consts/stock/stock_mode.go
Normal file
17
consts/stock/stock_mode.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package stock
|
||||
|
||||
// StockMode 库存管理模式枚举
|
||||
type StockMode int
|
||||
|
||||
const (
|
||||
StockModeDetail StockMode = 1 // 明细模式(每件一条记录)
|
||||
StockModeBatch StockMode = 2 // 批次模式(批次记录)
|
||||
)
|
||||
|
||||
// GetAllStockModes 获取所有库存管理模式
|
||||
func GetAllStockModes() []StockMode {
|
||||
return []StockMode{
|
||||
StockModeDetail,
|
||||
StockModeBatch,
|
||||
}
|
||||
}
|
||||
21
consts/stock/stock_status.go
Normal file
21
consts/stock/stock_status.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package stock
|
||||
|
||||
// StockStatus 库存状态枚举
|
||||
type StockStatus int
|
||||
|
||||
const (
|
||||
StockStatusAvailable StockStatus = 1 // 可用,未分配渠道
|
||||
StockStatusSold StockStatus = 2 // 已售出
|
||||
StockStatusReserved StockStatus = 3 // 预留
|
||||
StockStatusLocked StockStatus = 4 // 锁定
|
||||
)
|
||||
|
||||
// GetAllStockStatuses 获取所有库存状态
|
||||
func GetAllStockStatuses() []StockStatus {
|
||||
return []StockStatus{
|
||||
StockStatusAvailable,
|
||||
StockStatusSold,
|
||||
StockStatusReserved,
|
||||
StockStatusLocked,
|
||||
}
|
||||
}
|
||||
47
consts/stock/warehouse_status.go
Normal file
47
consts/stock/warehouse_status.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package stock
|
||||
|
||||
// WarehouseStatus 仓库状态枚举
|
||||
type WarehouseStatus string
|
||||
|
||||
const (
|
||||
WarehouseStatusEnabled WarehouseStatus = "enable" // 启用
|
||||
WarehouseStatusDisabled WarehouseStatus = "disable" // 停用
|
||||
)
|
||||
|
||||
// GetAllWarehouseStatuses 获取所有仓库状态
|
||||
func GetAllWarehouseStatuses() []WarehouseStatus {
|
||||
return []WarehouseStatus{
|
||||
WarehouseStatusEnabled,
|
||||
WarehouseStatusDisabled,
|
||||
}
|
||||
}
|
||||
|
||||
type WarehouseStatusKeyValue struct {
|
||||
Key WarehouseStatus
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
WarehouseStatusEnabledKeyValue = WarehouseStatusKeyValue{Key: WarehouseStatusEnabled, Value: "启用"}
|
||||
WarehouseStatusDisabledKeyValue = WarehouseStatusKeyValue{Key: WarehouseStatusDisabled, Value: "停用"}
|
||||
)
|
||||
|
||||
func GetAllWarehouseStatusKeyValue() []WarehouseStatusKeyValue {
|
||||
return []WarehouseStatusKeyValue{
|
||||
WarehouseStatusEnabledKeyValue,
|
||||
WarehouseStatusDisabledKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var warehouseStatusValueMap = map[WarehouseStatus]string{
|
||||
WarehouseStatusEnabled: WarehouseStatusEnabledKeyValue.Value,
|
||||
WarehouseStatusDisabled: WarehouseStatusDisabledKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetWarehouseStatusValueByKey(key WarehouseStatus) (value string) {
|
||||
value, exists := warehouseStatusValueMap[key]
|
||||
if !exists {
|
||||
value = "未知状态"
|
||||
}
|
||||
return
|
||||
}
|
||||
42
consts/stock/warning_type.go
Normal file
42
consts/stock/warning_type.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package stock
|
||||
|
||||
// WarningType 预警类型枚举
|
||||
type WarningType int
|
||||
|
||||
const (
|
||||
WarningTypeExpiry WarningType = 1 // 临期预警
|
||||
WarningTypeLowStock WarningType = 2 // 库存不足预警
|
||||
)
|
||||
|
||||
// GetAllWarningTypes 获取所有预警类型
|
||||
func GetAllWarningTypes() []WarningType {
|
||||
return []WarningType{
|
||||
WarningTypeExpiry,
|
||||
WarningTypeLowStock,
|
||||
}
|
||||
}
|
||||
|
||||
// String 获取预警类型字符串表示
|
||||
func (w WarningType) String() string {
|
||||
switch w {
|
||||
case WarningTypeExpiry:
|
||||
return "临期预警"
|
||||
case WarningTypeLowStock:
|
||||
return "库存不足预警"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
type WarningTypeKeyValue struct {
|
||||
Key int `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// GetAllWarningTypeKeyValue 获取所有预警类型的键值对
|
||||
func GetAllWarningTypeKeyValue() []WarningTypeKeyValue {
|
||||
return []WarningTypeKeyValue{
|
||||
{Key: 1, Value: "临期预警"},
|
||||
{Key: 2, Value: "库存不足预警"},
|
||||
}
|
||||
}
|
||||
47
consts/stock/zone_status.go
Normal file
47
consts/stock/zone_status.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package stock
|
||||
|
||||
// ZoneStatus 库区状态枚举
|
||||
type ZoneStatus string
|
||||
|
||||
const (
|
||||
ZoneStatusEnabled ZoneStatus = "enable" // 启用
|
||||
ZoneStatusDisabled ZoneStatus = "disable" // 停用
|
||||
)
|
||||
|
||||
// GetAllZoneStatuses 获取所有库区状态
|
||||
func GetAllZoneStatuses() []ZoneStatus {
|
||||
return []ZoneStatus{
|
||||
ZoneStatusEnabled,
|
||||
ZoneStatusDisabled,
|
||||
}
|
||||
}
|
||||
|
||||
type ZoneStatusKeyValue struct {
|
||||
Key ZoneStatus
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
ZoneStatusEnabledKeyValue = ZoneStatusKeyValue{Key: ZoneStatusEnabled, Value: "启用"}
|
||||
ZoneStatusDisabledKeyValue = ZoneStatusKeyValue{Key: ZoneStatusDisabled, Value: "停用"}
|
||||
)
|
||||
|
||||
func GetAllZoneStatusKeyValue() []ZoneStatusKeyValue {
|
||||
return []ZoneStatusKeyValue{
|
||||
ZoneStatusEnabledKeyValue,
|
||||
ZoneStatusDisabledKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var zoneStatusValueMap = map[ZoneStatus]string{
|
||||
ZoneStatusEnabled: ZoneStatusEnabledKeyValue.Value,
|
||||
ZoneStatusDisabled: ZoneStatusDisabledKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetZoneStatusValueByKey(key ZoneStatus) (value string) {
|
||||
value, exists := zoneStatusValueMap[key]
|
||||
if !exists {
|
||||
value = "未知状态"
|
||||
}
|
||||
return
|
||||
}
|
||||
67
consts/stock/zone_type.go
Normal file
67
consts/stock/zone_type.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package stock
|
||||
|
||||
// ZoneType 库区类型枚举
|
||||
type ZoneType string
|
||||
|
||||
const (
|
||||
ZoneTypeNormal ZoneType = "normal" // 常温区
|
||||
ZoneTypeCold ZoneType = "cold" // 冷藏区
|
||||
ZoneTypeFreeze ZoneType = "freeze" // 冷冻区
|
||||
ZoneTypeFresh ZoneType = "fresh" // 保鲜区
|
||||
ZoneTypeHazardous ZoneType = "hazardous" // 危险品区
|
||||
ZoneTypeBonded ZoneType = "bonded" // 保税区
|
||||
)
|
||||
|
||||
// GetAllZoneTypes 获取所有库区类型
|
||||
func GetAllZoneTypes() []ZoneType {
|
||||
return []ZoneType{
|
||||
ZoneTypeNormal,
|
||||
ZoneTypeCold,
|
||||
ZoneTypeFreeze,
|
||||
ZoneTypeFresh,
|
||||
ZoneTypeHazardous,
|
||||
ZoneTypeBonded,
|
||||
}
|
||||
}
|
||||
|
||||
type ZoneTypeKeyValue struct {
|
||||
Key ZoneType
|
||||
Value string
|
||||
}
|
||||
|
||||
var (
|
||||
ZoneTypeNormalKeyValue = ZoneTypeKeyValue{Key: ZoneTypeNormal, Value: "常温区"}
|
||||
ZoneTypeColdKeyValue = ZoneTypeKeyValue{Key: ZoneTypeCold, Value: "冷藏区"}
|
||||
ZoneTypeFreezeKeyValue = ZoneTypeKeyValue{Key: ZoneTypeFreeze, Value: "冷冻区"}
|
||||
ZoneTypeFreshKeyValue = ZoneTypeKeyValue{Key: ZoneTypeFresh, Value: "保鲜区"}
|
||||
ZoneTypeHazardousKeyValue = ZoneTypeKeyValue{Key: ZoneTypeHazardous, Value: "危险品区"}
|
||||
ZoneTypeBondedKeyValue = ZoneTypeKeyValue{Key: ZoneTypeBonded, Value: "保税区"}
|
||||
)
|
||||
|
||||
func GetAllZoneTypeKeyValue() []ZoneTypeKeyValue {
|
||||
return []ZoneTypeKeyValue{
|
||||
ZoneTypeNormalKeyValue,
|
||||
ZoneTypeColdKeyValue,
|
||||
ZoneTypeFreezeKeyValue,
|
||||
ZoneTypeFreshKeyValue,
|
||||
ZoneTypeHazardousKeyValue,
|
||||
ZoneTypeBondedKeyValue,
|
||||
}
|
||||
}
|
||||
|
||||
var zoneTypeValueMap = map[ZoneType]string{
|
||||
ZoneTypeNormal: ZoneTypeNormalKeyValue.Value,
|
||||
ZoneTypeCold: ZoneTypeColdKeyValue.Value,
|
||||
ZoneTypeFreeze: ZoneTypeFreezeKeyValue.Value,
|
||||
ZoneTypeFresh: ZoneTypeFreshKeyValue.Value,
|
||||
ZoneTypeHazardous: ZoneTypeHazardousKeyValue.Value,
|
||||
ZoneTypeBonded: ZoneTypeBondedKeyValue.Value,
|
||||
}
|
||||
|
||||
func GetZoneTypeValueByKey(key ZoneType) (value string) {
|
||||
value, exists := zoneTypeValueMap[key]
|
||||
if !exists {
|
||||
value = "未知类型"
|
||||
}
|
||||
return
|
||||
}
|
||||
56
controller/asset/asset_controller.go
Normal file
56
controller/asset/asset_controller.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/asset"
|
||||
service "assets/service/asset"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type asset struct{}
|
||||
|
||||
// Asset 资产控制器
|
||||
var Asset = new(asset)
|
||||
|
||||
// init 初始化表单配置
|
||||
func init() {
|
||||
}
|
||||
|
||||
// CreateAsset 创建资产
|
||||
func (c *asset) CreateAsset(ctx context.Context, req *dto.CreateAssetReq) (res *dto.CreateAssetRes, err error) {
|
||||
return service.Asset.Create(ctx, req)
|
||||
}
|
||||
|
||||
// ListAsset 获取资产列表
|
||||
func (c *asset) ListAsset(ctx context.Context, req *dto.ListAssetReq) (res *dto.ListAssetRes, err error) {
|
||||
return service.Asset.List(ctx, req)
|
||||
}
|
||||
|
||||
// GetAsset 获取资产详情
|
||||
func (c *asset) GetAsset(ctx context.Context, req *dto.GetAssetReq) (res *dto.GetAssetRes, err error) {
|
||||
return service.Asset.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
// GetAssetAndSuk 获取资产详情
|
||||
func (c *asset) GetAssetAndSuk(ctx context.Context, req *dto.GetAssetAndSkuReq) (res *dto.GetAssetAndSkuRes, err error) {
|
||||
return service.Asset.GetAssetAndSku(ctx, req)
|
||||
}
|
||||
|
||||
// UpdateAsset 更新资产
|
||||
func (c *asset) UpdateAsset(ctx context.Context, req *dto.UpdateAssetReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Asset.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateAssetStatus 更新资产状态
|
||||
func (c *asset) UpdateAssetStatus(ctx context.Context, req *dto.UpdateAssetStatusReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Asset.UpdateStatus(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteAsset 删除资产
|
||||
func (c *asset) DeleteAsset(ctx context.Context, req *dto.DeleteAssetReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Asset.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
45
controller/asset/asset_sku_controller.go
Normal file
45
controller/asset/asset_sku_controller.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/asset"
|
||||
service "assets/service/asset"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type assetSku struct{}
|
||||
|
||||
// AssetSku 资产SKU控制器
|
||||
var AssetSku = new(assetSku)
|
||||
|
||||
// init 初始化表单配置
|
||||
func init() {
|
||||
}
|
||||
|
||||
// CreateAssetSku 创建SKU
|
||||
func (c *assetSku) CreateAssetSku(ctx context.Context, req *dto.CreateAssetSkuReq) (res *dto.CreateAssetSkuRes, err error) {
|
||||
return service.AssetSku.CreateAssetSku(ctx, req)
|
||||
}
|
||||
|
||||
// UpdateAssetSku 更新SKU
|
||||
func (c *assetSku) UpdateAssetSku(ctx context.Context, req *dto.UpdateAssetSkuReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.AssetSku.UpdateAssetSku(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteAssetSku 删除SKU
|
||||
func (c *assetSku) DeleteAssetSku(ctx context.Context, req *dto.DeleteAssetSkuReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.AssetSku.DeleteAssetSku(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// GetAssetSku 获取SKU详情
|
||||
func (c *assetSku) GetAssetSku(ctx context.Context, req *dto.GetAssetSkuReq) (res *dto.GetAssetSkuRes, err error) {
|
||||
return service.AssetSku.GetAssetSku(ctx, req)
|
||||
}
|
||||
|
||||
// ListAssetSkus 获取SKU列表
|
||||
func (c *assetSku) ListAssetSkus(ctx context.Context, req *dto.ListAssetSkuReq) (res *dto.ListAssetSkuRes, err error) {
|
||||
return service.AssetSku.ListAssetSkus(ctx, req)
|
||||
}
|
||||
56
controller/asset/category_controller.go
Normal file
56
controller/asset/category_controller.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/asset"
|
||||
service "assets/service/asset"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type category struct{}
|
||||
|
||||
// Category 分类控制器
|
||||
var Category = new(category)
|
||||
|
||||
// init 初始化表单配置
|
||||
func init() {
|
||||
}
|
||||
|
||||
// GetCategory 获取分类详情
|
||||
func (c *category) GetCategory(ctx context.Context, req *dto.GetCategoryReq) (res *dto.GetCategoryRes, err error) {
|
||||
return service.Category.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
// ListCategory 获取分类列表
|
||||
func (c *category) ListCategory(ctx context.Context, req *dto.ListCategoryReq) (res *dto.ListCategoryRes, err error) {
|
||||
return service.Category.List(ctx, req)
|
||||
}
|
||||
|
||||
// GetCategoryTree 获取分类树
|
||||
func (c *category) GetCategoryTree(ctx context.Context, req *dto.GetCategoryTreeReq) (res *dto.GetCategoryTreeRes, err error) {
|
||||
return service.Category.GetTree(ctx, req)
|
||||
}
|
||||
|
||||
// CreateCategory 创建分类
|
||||
func (c *category) CreateCategory(ctx context.Context, req *dto.CreateCategoryReq) (res *dto.CreateCategoryRes, err error) {
|
||||
return service.Category.Create(ctx, req)
|
||||
}
|
||||
|
||||
// UpdateCategory 更新分类
|
||||
func (c *category) UpdateCategory(ctx context.Context, req *dto.UpdateCategoryReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Category.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateCategoryStatus 更新分类状态
|
||||
func (c *category) UpdateCategoryStatus(ctx context.Context, req *dto.UpdateCategoryStatusReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Category.UpdateStatus(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteCategory 删除分类
|
||||
func (c *category) DeleteCategory(ctx context.Context, req *dto.DeleteCategoryReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Category.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
116
controller/asset/private_category_controller.go
Normal file
116
controller/asset/private_category_controller.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/asset"
|
||||
service "assets/service/asset"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type privateCategory struct{}
|
||||
|
||||
// PrivateCategory 私域分类控制器
|
||||
var PrivateCategory = new(privateCategory)
|
||||
|
||||
// CreatePrivateCategory 创建私域分类
|
||||
// @Summary 创建私域分类
|
||||
// @Tags 私域分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body asset.CreatePrivateCategoryReq true "创建私域分类请求"
|
||||
// @Success 200 {object} asset.CreatePrivateCategoryRes
|
||||
// @Router /privateCategory/createPrivateCategory [post]
|
||||
func (c *privateCategory) CreatePrivateCategory(ctx context.Context, req *dto.CreatePrivateCategoryReq) (res *dto.CreatePrivateCategoryRes, err error) {
|
||||
return service.PrivateCategory.CreatePrivateCategory(ctx, req)
|
||||
}
|
||||
|
||||
// BatchCreatePrivateCategory 批量创建私域分类
|
||||
// @Summary 批量创建私域分类
|
||||
// @Tags 私域分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body asset.BatchCreatePrivateCategoryReq true "批量创建私域分类请求"
|
||||
// @Success 200 {object} asset.BatchCreatePrivateCategoryRes
|
||||
// @Router /privateCategory/batchCreatePrivateCategory [post]
|
||||
func (c *privateCategory) BatchCreatePrivateCategory(ctx context.Context, req *dto.BatchCreatePrivateCategoryReq) (res *dto.BatchCreatePrivateCategoryRes, err error) {
|
||||
return service.PrivateCategory.BatchCreatePrivateCategory(ctx, req)
|
||||
}
|
||||
|
||||
// UpdatePrivateCategory 更新私域分类
|
||||
// @Summary 更新私域分类
|
||||
// @Tags 私域分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body asset.UpdatePrivateCategoryReq true "更新私域分类请求"
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /privateCategory/updatePrivateCategory [put]
|
||||
func (c *privateCategory) UpdatePrivateCategory(ctx context.Context, req *dto.UpdatePrivateCategoryReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateCategory.UpdatePrivateCategory(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// DeletePrivateCategory 删除私域分类
|
||||
// @Summary 删除私域分类
|
||||
// @Tags 私域分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id query string true "私域分类ID"
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /privateCategory/deletePrivateCategory [delete]
|
||||
func (c *privateCategory) DeletePrivateCategory(ctx context.Context, req *dto.DeletePrivateCategoryReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateCategory.DeletePrivateCategory(ctx, req.ID)
|
||||
return
|
||||
}
|
||||
|
||||
// GetPrivateCategory 获取私域分类详情
|
||||
// @Summary 获取私域分类详情
|
||||
// @Tags 私域分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id query string true "私域分类ID"
|
||||
// @Success 200 {object} asset.GetPrivateCategoryRes
|
||||
// @Router /privateCategory/getPrivateCategory [get]
|
||||
func (c *privateCategory) GetPrivateCategory(ctx context.Context, req *dto.GetPrivateCategoryReq) (res *dto.GetPrivateCategoryRes, err error) {
|
||||
return service.PrivateCategory.GetPrivateCategory(ctx, req.ID)
|
||||
}
|
||||
|
||||
// ListPrivateCategory 获取私域分类列表
|
||||
// @Summary 获取私域分类列表
|
||||
// @Tags 私域分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param name query string false "分类名称"
|
||||
// @Param parentId query string false "父分类ID"
|
||||
// @Param level query int false "分类层级"
|
||||
// @Param isLeafNode query bool false "是否叶子节点"
|
||||
// @Param pageNum query int false "页码" default(1)
|
||||
// @Param pageSize query int false "每页大小" default(10)
|
||||
// @Success 200 {object} asset.ListPrivateCategoryRes
|
||||
// @Router /privateCategory/listPrivateCategory [get]
|
||||
func (c *privateCategory) ListPrivateCategory(ctx context.Context, req *dto.ListPrivateCategoryReq) (res *dto.ListPrivateCategoryRes, err error) {
|
||||
return service.PrivateCategory.ListPrivateCategory(ctx, req)
|
||||
}
|
||||
|
||||
// GetPrivateCategoryTree 获取私域分类树
|
||||
// @Summary 获取私域分类树
|
||||
// @Tags 私域分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} asset.GetPrivateCategoryTreeRes
|
||||
// @Router /privateCategory/getPrivateCategoryTree [get]
|
||||
func (c *privateCategory) GetPrivateCategoryTree(ctx context.Context, req *dto.GetPrivateCategoryTreeReq) (res *dto.GetPrivateCategoryTreeRes, err error) {
|
||||
return service.PrivateCategory.GetPrivateCategoryTree(ctx)
|
||||
}
|
||||
|
||||
// GenerateTestData 生成测试数据
|
||||
// @Summary 生成测试数据
|
||||
// @Tags 私域分类管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /privateCategory/generateTestData [post]
|
||||
func (c *privateCategory) GenerateTestData(ctx context.Context, req *dto.GeneratePrivateCategoryTestDataReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateCategory.GenerateTestData(ctx)
|
||||
return
|
||||
}
|
||||
118
controller/asset/private_sku_controller.go
Normal file
118
controller/asset/private_sku_controller.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/asset"
|
||||
service "assets/service/asset"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type privateSku struct{}
|
||||
|
||||
// PrivateSku 私域SKU控制器
|
||||
var PrivateSku = new(privateSku)
|
||||
|
||||
// CreatePrivateSku 创建私域SKU
|
||||
// @Summary 创建私域SKU
|
||||
// @Tags 私域SKU管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body asset.CreatePrivateSkuReq true "创建私域SKU请求"
|
||||
// @Success 200 {object} asset.CreatePrivateSkuRes
|
||||
// @Router /privateSku/createPrivateSku [post]
|
||||
func (c *privateSku) CreatePrivateSku(ctx context.Context, req *dto.CreatePrivateSkuReq) (res *dto.CreatePrivateSkuRes, err error) {
|
||||
return service.PrivateSku.CreatePrivateSku(ctx, req)
|
||||
}
|
||||
|
||||
// BatchCreatePrivateSku 批量创建私域SKU
|
||||
// @Summary 批量创建私域SKU
|
||||
// @Tags 私域SKU管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body asset.BatchCreatePrivateSkuReq true "批量创建私域SKU请求"
|
||||
// @Success 200 {object} asset.BatchCreatePrivateSkuRes
|
||||
// @Router /privateSku/batchCreatePrivateSku [post]
|
||||
func (c *privateSku) BatchCreatePrivateSku(ctx context.Context, req *dto.BatchCreatePrivateSkuReq) (res *dto.BatchCreatePrivateSkuRes, err error) {
|
||||
return service.PrivateSku.BatchCreatePrivateSku(ctx, req)
|
||||
}
|
||||
|
||||
// UpdatePrivateSku 更新私域SKU
|
||||
// @Summary 更新私域SKU
|
||||
// @Tags 私域SKU管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body asset.UpdatePrivateSkuReq true "更新私域SKU请求"
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /privateSku/updatePrivateSku [put]
|
||||
func (c *privateSku) UpdatePrivateSku(ctx context.Context, req *dto.UpdatePrivateSkuReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateSku.UpdatePrivateSku(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// DeletePrivateSku 删除私域SKU
|
||||
// @Summary 删除私域SKU
|
||||
// @Tags 私域SKU管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id query string true "私域SKU ID"
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /privateSku/deletePrivateSku [delete]
|
||||
func (c *privateSku) DeletePrivateSku(ctx context.Context, req *dto.DeletePrivateSkuReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateSku.DeletePrivateSku(ctx, req.ID)
|
||||
return
|
||||
}
|
||||
|
||||
// GetPrivateSku 获取私域SKU详情
|
||||
// @Summary 获取私域SKU详情
|
||||
// @Tags 私域SKU管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id query string true "私域SKU ID"
|
||||
// @Success 200 {object} asset.GetPrivateSkuRes
|
||||
// @Router /privateSku/getPrivateSku [get]
|
||||
func (c *privateSku) GetPrivateSku(ctx context.Context, req *dto.GetPrivateSkuReq) (res *dto.GetPrivateSkuRes, err error) {
|
||||
return service.PrivateSku.GetPrivateSku(ctx, req.ID)
|
||||
}
|
||||
|
||||
// ListPrivateSku 获取私域SKU列表
|
||||
// @Summary 获取私域SKU列表
|
||||
// @Tags 私域SKU管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param skuName query string false "SKU名称"
|
||||
// @Param privateCategoryPath query string false "分类路径"
|
||||
// @Param minPrice query int false "最低价格"
|
||||
// @Param maxPrice query int false "最高价格"
|
||||
// @Param pageNum query int false "页码" default(1)
|
||||
// @Param pageSize query int false "每页大小" default(10)
|
||||
// @Success 200 {object} asset.ListPrivateSkuRes
|
||||
// @Router /privateSku/listPrivateSku [get]
|
||||
func (c *privateSku) ListPrivateSku(ctx context.Context, req *dto.ListPrivateSkuReq) (res *dto.ListPrivateSkuRes, err error) {
|
||||
return service.PrivateSku.ListPrivateSku(ctx, req)
|
||||
}
|
||||
|
||||
// UpdatePrivateSkuStock 更新私域SKU库存
|
||||
// @Summary 更新私域SKU库存
|
||||
// @Tags 私域SKU管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body asset.UpdatePrivateSkuStockReq true "更新库存请求"
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /privateSku/updatePrivateSkuStock [put]
|
||||
func (c *privateSku) UpdatePrivateSkuStock(ctx context.Context, req *dto.UpdatePrivateSkuStockReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateSku.UpdatePrivateSkuStock(ctx, req.ID, req.StockChange)
|
||||
return
|
||||
}
|
||||
|
||||
// GenerateTestData 生成测试数据
|
||||
// @Summary 生成测试数据
|
||||
// @Tags 私域SKU管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /privateSku/generateTestData [post]
|
||||
func (c *privateSku) GenerateTestData(ctx context.Context, req *dto.GeneratePrivateSkuTestDataReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateSku.GenerateTestData(ctx)
|
||||
return
|
||||
}
|
||||
31
controller/enum/enum_controller.go
Normal file
31
controller/enum/enum_controller.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"assets/model/dto/enum"
|
||||
"assets/service/enum"
|
||||
"context"
|
||||
)
|
||||
|
||||
type enum struct{}
|
||||
|
||||
// Enum 枚举控制器
|
||||
var Enum = new(enum)
|
||||
|
||||
// init 初始化表单配置
|
||||
func init() {
|
||||
}
|
||||
|
||||
// GetAssetType 获取资产类型
|
||||
func (c *enum) GetAssetType(ctx context.Context, req *dto.GetAssetTypeReq) (res *dto.GetAssetTypeRes, err error) {
|
||||
return service.Enum.GetAssetType(ctx, req)
|
||||
}
|
||||
|
||||
// GetCategoryAttrType 获取分类属性类型
|
||||
func (c *enum) GetCategoryAttrType(ctx context.Context, req *dto.GetCategoryAttrTypeReq) (res *dto.GetCategoryAttrTypeRes, err error) {
|
||||
return service.Enum.GetCategoryAttrType(ctx, req)
|
||||
}
|
||||
|
||||
// GetSpecsUnit 获取规格单位
|
||||
func (c *enum) GetSpecsUnit(ctx context.Context, req *dto.GetSpecsUnitReq) (res *dto.GetSpecsUnitRes, err error) {
|
||||
return service.Enum.GetSpecsUnit(ctx, req)
|
||||
}
|
||||
26
controller/procurement/purchase_inbound_controller.go
Normal file
26
controller/procurement/purchase_inbound_controller.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/procurement"
|
||||
service "assets/service/procurement"
|
||||
"context"
|
||||
)
|
||||
|
||||
type purchaseInbound struct{}
|
||||
|
||||
var PurchaseInbound = new(purchaseInbound)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *purchaseInbound) CreatePurchaseInbound(ctx context.Context, req *dto.CreatePurchaseInboundReq) (res *dto.CreatePurchaseInboundRes, err error) {
|
||||
return service.PurchaseInbound.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (c *purchaseInbound) GetPurchaseInbound(ctx context.Context, req *dto.GetPurchaseInboundReq) (res *dto.GetPurchaseInboundRes, err error) {
|
||||
return service.PurchaseInbound.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *purchaseInbound) ListPurchaseInbounds(ctx context.Context, req *dto.ListPurchaseInboundReq) (res *dto.ListPurchaseInboundRes, err error) {
|
||||
return service.PurchaseInbound.List(ctx, req)
|
||||
}
|
||||
106
controller/procurement/purchase_order_controller.go
Normal file
106
controller/procurement/purchase_order_controller.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/procurement"
|
||||
service "assets/service/procurement"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type purchaseOrder struct{}
|
||||
|
||||
// PurchaseOrder 采购订单控制器
|
||||
var PurchaseOrder = new(purchaseOrder)
|
||||
|
||||
// CreatePurchaseOrder 创建采购订单
|
||||
// @Summary 创建采购订单
|
||||
// @Tags 采购订单管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body procurement.CreatePurchaseOrderReq true "创建采购订单请求"
|
||||
// @Success 200 {object} procurement.CreatePurchaseOrderRes
|
||||
// @Router /purchaseOrder/createPurchaseOrder [post]
|
||||
func (c *purchaseOrder) CreatePurchaseOrder(ctx context.Context, req *dto.CreatePurchaseOrderReq) (res *dto.CreatePurchaseOrderRes, err error) {
|
||||
return service.PurchaseOrder.CreatePurchaseOrder(ctx, req)
|
||||
}
|
||||
|
||||
// BatchCreatePurchaseOrders 批量创建采购订单
|
||||
// @Summary 批量创建采购订单
|
||||
// @Tags 采购订单管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body procurement.BatchCreatePurchaseOrdersReq true "批量创建采购订单请求"
|
||||
// @Success 200 {object} procurement.BatchCreatePurchaseOrdersRes
|
||||
// @Router /purchaseOrder/batchCreatePurchaseOrders [post]
|
||||
func (c *purchaseOrder) BatchCreatePurchaseOrders(ctx context.Context, req *dto.BatchCreatePurchaseOrdersReq) (res *dto.BatchCreatePurchaseOrdersRes, err error) {
|
||||
return service.PurchaseOrder.BatchCreatePurchaseOrders(ctx, req)
|
||||
}
|
||||
|
||||
// UpdatePurchaseOrder 更新采购订单
|
||||
// @Summary 更新采购订单
|
||||
// @Tags 采购订单管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body procurement.UpdatePurchaseOrderReq true "更新采购订单请求"
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /purchaseOrder/updatePurchaseOrder [put]
|
||||
func (c *purchaseOrder) UpdatePurchaseOrder(ctx context.Context, req *dto.UpdatePurchaseOrderReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PurchaseOrder.UpdatePurchaseOrder(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// DeletePurchaseOrder 删除采购订单
|
||||
// @Summary 删除采购订单
|
||||
// @Tags 采购订单管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id query string true "采购订单ID"
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /purchaseOrder/deletePurchaseOrder [delete]
|
||||
func (c *purchaseOrder) DeletePurchaseOrder(ctx context.Context, req *dto.DeletePurchaseOrderReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PurchaseOrder.DeletePurchaseOrder(ctx, req.ID)
|
||||
return
|
||||
}
|
||||
|
||||
// GetPurchaseOrder 获取采购订单详情
|
||||
// @Summary 获取采购订单详情
|
||||
// @Tags 采购订单管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id query string true "采购订单ID"
|
||||
// @Success 200 {object} procurement.GetPurchaseOrderRes
|
||||
// @Router /purchaseOrder/getPurchaseOrder [get]
|
||||
func (c *purchaseOrder) GetPurchaseOrder(ctx context.Context, req *dto.GetPurchaseOrderReq) (res *dto.GetPurchaseOrderRes, err error) {
|
||||
return service.PurchaseOrder.GetPurchaseOrder(ctx, req.ID)
|
||||
}
|
||||
|
||||
// ListPurchaseOrders 获取采购订单列表
|
||||
// @Summary 获取采购订单列表
|
||||
// @Tags 采购订单管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param orderNo query string false "订单编号"
|
||||
// @Param title query string false "订单标题"
|
||||
// @Param buyerId query string false "采购方ID"
|
||||
// @Param orderType query string false "订单类型"
|
||||
// @Param status query int false "订单状态"
|
||||
// @Param pageNum query int false "页码" default(1)
|
||||
// @Param pageSize query int false "每页大小" default(10)
|
||||
// @Success 200 {object} procurement.ListPurchaseOrdersRes
|
||||
// @Router /purchaseOrder/listPurchaseOrders [get]
|
||||
func (c *purchaseOrder) ListPurchaseOrders(ctx context.Context, req *dto.ListPurchaseOrdersReq) (res *dto.ListPurchaseOrdersRes, err error) {
|
||||
return service.PurchaseOrder.ListPurchaseOrders(ctx, req)
|
||||
}
|
||||
|
||||
// GenerateTestData 生成测试数据
|
||||
// @Summary 生成测试数据
|
||||
// @Tags 采购订单管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /purchaseOrder/generateTestData [post]
|
||||
func (c *purchaseOrder) GenerateTestData(ctx context.Context, req *dto.GeneratePurchaseOrderTestDataReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PurchaseOrder.GenerateTestData(ctx)
|
||||
return
|
||||
}
|
||||
106
controller/procurement/purchase_order_item_controller.go
Normal file
106
controller/procurement/purchase_order_item_controller.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/procurement"
|
||||
service "assets/service/procurement"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type purchaseOrderItem struct{}
|
||||
|
||||
// PurchaseOrderItem 采购订单明细控制器
|
||||
var PurchaseOrderItem = new(purchaseOrderItem)
|
||||
|
||||
// CreatePurchaseOrderItem 创建采购订单明细
|
||||
// @Summary 创建采购订单明细
|
||||
// @Tags 采购订单明细管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body procurement.CreatePurchaseOrderItemReq true "创建采购订单明细请求"
|
||||
// @Success 200 {object} procurement.CreatePurchaseOrderItemRes
|
||||
// @Router /purchaseOrderItem/createPurchaseOrderItem [post]
|
||||
func (c *purchaseOrderItem) CreatePurchaseOrderItem(ctx context.Context, req *dto.CreatePurchaseOrderItemReq) (res *dto.CreatePurchaseOrderItemRes, err error) {
|
||||
return service.PurchaseOrderItem.CreatePurchaseOrderItem(ctx, req)
|
||||
}
|
||||
|
||||
// BatchCreatePurchaseOrderItems 批量创建采购订单明细
|
||||
// @Summary 批量创建采购订单明细
|
||||
// @Tags 采购订单明细管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body procurement.BatchCreatePurchaseOrderItemsReq true "批量创建采购订单明细请求"
|
||||
// @Success 200 {object} procurement.BatchCreatePurchaseOrderItemsRes
|
||||
// @Router /purchaseOrderItem/batchCreatePurchaseOrderItems [post]
|
||||
func (c *purchaseOrderItem) BatchCreatePurchaseOrderItems(ctx context.Context, req *dto.BatchCreatePurchaseOrderItemsReq) (res *dto.BatchCreatePurchaseOrderItemsRes, err error) {
|
||||
return service.PurchaseOrderItem.BatchCreatePurchaseOrderItems(ctx, req)
|
||||
}
|
||||
|
||||
// UpdatePurchaseOrderItem 更新采购订单明细
|
||||
// @Summary 更新采购订单明细
|
||||
// @Tags 采购订单明细管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body procurement.UpdatePurchaseOrderItemReq true "更新采购订单明细请求"
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /purchaseOrderItem/updatePurchaseOrderItem [put]
|
||||
func (c *purchaseOrderItem) UpdatePurchaseOrderItem(ctx context.Context, req *dto.UpdatePurchaseOrderItemReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PurchaseOrderItem.UpdatePurchaseOrderItem(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// DeletePurchaseOrderItem 删除采购订单明细
|
||||
// @Summary 删除采购订单明细
|
||||
// @Tags 采购订单明细管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id query string true "采购订单明细ID"
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /purchaseOrderItem/deletePurchaseOrderItem [delete]
|
||||
func (c *purchaseOrderItem) DeletePurchaseOrderItem(ctx context.Context, req *dto.DeletePurchaseOrderItemReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PurchaseOrderItem.DeletePurchaseOrderItem(ctx, req.ID)
|
||||
return
|
||||
}
|
||||
|
||||
// GetPurchaseOrderItem 获取采购订单明细详情
|
||||
// @Summary 获取采购订单明细详情
|
||||
// @Tags 采购订单明细管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id query string true "采购订单明细ID"
|
||||
// @Success 200 {object} procurement.GetPurchaseOrderItemRes
|
||||
// @Router /purchaseOrderItem/getPurchaseOrderItem [get]
|
||||
func (c *purchaseOrderItem) GetPurchaseOrderItem(ctx context.Context, req *dto.GetPurchaseOrderItemReq) (res *dto.GetPurchaseOrderItemRes, err error) {
|
||||
return service.PurchaseOrderItem.GetPurchaseOrderItem(ctx, req.ID)
|
||||
}
|
||||
|
||||
// ListPurchaseOrderItems 获取采购订单明细列表
|
||||
// @Summary 获取采购订单明细列表
|
||||
// @Tags 采购订单明细管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param orderId query string false "订单ID"
|
||||
// @Param assetId query string false "资产ID"
|
||||
// @Param assetSkuId query string false "资产SKU ID"
|
||||
// @Param productName query string false "商品名称"
|
||||
// @Param brand query string false "品牌"
|
||||
// @Param pageNum query int false "页码" default(1)
|
||||
// @Param pageSize query int false "每页大小" default(10)
|
||||
// @Success 200 {object} procurement.ListPurchaseOrderItemsRes
|
||||
// @Router /purchaseOrderItem/listPurchaseOrderItems [get]
|
||||
func (c *purchaseOrderItem) ListPurchaseOrderItems(ctx context.Context, req *dto.ListPurchaseOrderItemsReq) (res *dto.ListPurchaseOrderItemsRes, err error) {
|
||||
return service.PurchaseOrderItem.ListPurchaseOrderItems(ctx, req)
|
||||
}
|
||||
|
||||
// GenerateTestData 生成测试数据
|
||||
// @Summary 生成测试数据
|
||||
// @Tags 采购订单明细管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /purchaseOrderItem/generateTestData [post]
|
||||
func (c *purchaseOrderItem) GenerateTestData(ctx context.Context, req *dto.GeneratePurchaseOrderItemTestDataReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PurchaseOrderItem.GenerateTestData(ctx)
|
||||
return
|
||||
}
|
||||
121
controller/procurement/supplier_controller.go
Normal file
121
controller/procurement/supplier_controller.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/procurement"
|
||||
service "assets/service/procurement"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type supplier struct{}
|
||||
|
||||
// Supplier 供应商控制器
|
||||
var Supplier = new(supplier)
|
||||
|
||||
// CreateSupplier 创建供应商
|
||||
// @Summary 创建供应商
|
||||
// @Tags 供应商管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body procurement.CreateSupplierReq true "创建供应商请求"
|
||||
// @Success 200 {object} procurement.CreateSupplierRes
|
||||
// @Router /supplier/createSupplier [post]
|
||||
func (c *supplier) CreateSupplier(ctx context.Context, req *dto.CreateSupplierReq) (res *dto.CreateSupplierRes, err error) {
|
||||
return service.Supplier.CreateSupplier(ctx, req)
|
||||
}
|
||||
|
||||
// BatchCreateSuppliers 批量创建供应商
|
||||
// @Summary 批量创建供应商
|
||||
// @Tags 供应商管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body procurement.BatchCreateSuppliersReq true "批量创建供应商请求"
|
||||
// @Success 200 {object} procurement.BatchCreateSuppliersRes
|
||||
// @Router /supplier/batchCreateSuppliers [post]
|
||||
func (c *supplier) BatchCreateSuppliers(ctx context.Context, req *dto.BatchCreateSuppliersReq) (res *dto.BatchCreateSuppliersRes, err error) {
|
||||
return service.Supplier.BatchCreateSuppliers(ctx, req)
|
||||
}
|
||||
|
||||
// UpdateSupplier 更新供应商
|
||||
// @Summary 更新供应商
|
||||
// @Tags 供应商管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body procurement.UpdateSupplierReq true "更新供应商请求"
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /supplier/updateSupplier [put]
|
||||
func (c *supplier) UpdateSupplier(ctx context.Context, req *dto.UpdateSupplierReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Supplier.UpdateSupplier(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteSupplier 删除供应商
|
||||
// @Summary 删除供应商
|
||||
// @Tags 供应商管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id query string true "供应商ID"
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /supplier/deleteSupplier [delete]
|
||||
func (c *supplier) DeleteSupplier(ctx context.Context, req *dto.DeleteSupplierReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Supplier.DeleteSupplier(ctx, req.ID)
|
||||
return
|
||||
}
|
||||
|
||||
// GetSupplier 获取供应商详情
|
||||
// @Summary 获取供应商详情
|
||||
// @Tags 供应商管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id query string true "供应商ID"
|
||||
// @Success 200 {object} procurement.GetSupplierRes
|
||||
// @Router /supplier/getSupplier [get]
|
||||
func (c *supplier) GetSupplier(ctx context.Context, req *dto.GetSupplierReq) (res *dto.GetSupplierRes, err error) {
|
||||
return service.Supplier.GetSupplier(ctx, req.ID)
|
||||
}
|
||||
|
||||
// ListSuppliers 获取供应商列表
|
||||
// @Summary 获取供应商列表
|
||||
// @Tags 供应商管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param name query string false "供应商名称"
|
||||
// @Param code query string false "供应商编码"
|
||||
// @Param status query int false "供应商状态"
|
||||
// @Param pageNum query int false "页码" default(1)
|
||||
// @Param pageSize query int false "每页大小" default(10)
|
||||
// @Success 200 {object} procurement.ListSuppliersRes
|
||||
// @Router /supplier/listSuppliers [get]
|
||||
func (c *supplier) ListSuppliers(ctx context.Context, req *dto.ListSuppliersReq) (res *dto.ListSuppliersRes, err error) {
|
||||
return service.Supplier.ListSuppliers(ctx, req)
|
||||
}
|
||||
|
||||
// GetSupplierOptions 获取供应商选项
|
||||
// @Summary 获取供应商选项(用于下拉选择)
|
||||
// @Tags 供应商管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} procurement.GetSupplierOptionsRes
|
||||
// @Router /supplier/getSupplierOptions [get]
|
||||
func (c *supplier) GetSupplierOptions(ctx context.Context, req *dto.GetSupplierOptionsReq) (res *dto.GetSupplierOptionsRes, err error) {
|
||||
list, err := service.Supplier.GetSupplierOptions(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.GetSupplierOptionsRes{
|
||||
List: list,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GenerateTestData 生成测试数据
|
||||
// @Summary 生成测试数据
|
||||
// @Tags 供应商管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} beans.ResponseEmpty
|
||||
// @Router /supplier/generateTestData [post]
|
||||
func (c *supplier) GenerateTestData(ctx context.Context, req *dto.GenerateSupplierTestDataReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Supplier.GenerateTestData(ctx)
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type inventoryCountAdjustHistory struct{}
|
||||
|
||||
var InventoryCountAdjustHistory = new(inventoryCountAdjustHistory)
|
||||
|
||||
func init() {}
|
||||
|
||||
// CreateInventoryCountAdjustHistory 创建盘点调整历史记录
|
||||
func (c *inventoryCountAdjustHistory) CreateInventoryCountAdjustHistory(ctx context.Context, req *dto.CreateInventoryCountAdjustHistoryReq) (res *dto.CreateInventoryCountAdjustHistoryRes, err error) {
|
||||
res, err = service.InventoryCountAdjustHistory.Create(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// GetInventoryCountAdjustHistory 获取盘点调整历史记录详情
|
||||
func (c *inventoryCountAdjustHistory) GetInventoryCountAdjustHistory(ctx context.Context, req *dto.GetInventoryCountAdjustHistoryReq) (res *dto.GetInventoryCountAdjustHistoryRes, err error) {
|
||||
res, err = service.InventoryCountAdjustHistory.GetOne(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteInventoryCountAdjustHistory 删除盘点调整历史记录
|
||||
func (c *inventoryCountAdjustHistory) DeleteInventoryCountAdjustHistory(ctx context.Context, req *dto.DeleteInventoryCountAdjustHistoryReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.InventoryCountAdjustHistory.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// ListInventoryCountAdjustHistories 分页查询盘点调整历史列表
|
||||
func (c *inventoryCountAdjustHistory) ListInventoryCountAdjustHistories(ctx context.Context, req *dto.ListInventoryCountAdjustHistoryReq) (res *dto.ListInventoryCountAdjustHistoryRes, err error) {
|
||||
res, err = service.InventoryCountAdjustHistory.List(ctx, req)
|
||||
return
|
||||
}
|
||||
76
controller/stock/inventory_count_controller.go
Normal file
76
controller/stock/inventory_count_controller.go
Normal file
@@ -0,0 +1,76 @@
|
||||
// 盘点任务控制器
|
||||
// 职责:盘点任务CRUD、完成/取消、导出模板、导入Excel
|
||||
// 调用服务:service.InventoryCount
|
||||
// 注意:ImportInventoryCount从multipart form读取文件,Update/Delete返回*beans.ResponseEmpty
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
type inventoryCount struct{}
|
||||
|
||||
var InventoryCount = new(inventoryCount)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *inventoryCount) CreateInventoryCount(ctx context.Context, req *dto.CreateInventoryCountReq) (res *dto.CreateInventoryCountRes, err error) {
|
||||
g.Log().Debugf(ctx, "[CreateInventoryCount] req: %+v", req)
|
||||
return service.InventoryCount.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (c *inventoryCount) UpdateInventoryCount(ctx context.Context, req *dto.UpdateInventoryCountReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.InventoryCount.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *inventoryCount) DeleteInventoryCount(ctx context.Context, req *dto.DeleteInventoryCountReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.InventoryCount.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *inventoryCount) GetInventoryCount(ctx context.Context, req *dto.GetInventoryCountReq) (res *dto.GetInventoryCountRes, err error) {
|
||||
return service.InventoryCount.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *inventoryCount) ListInventoryCounts(ctx context.Context, req *dto.ListInventoryCountReq) (res *dto.ListInventoryCountRes, err error) {
|
||||
return service.InventoryCount.List(ctx, req)
|
||||
}
|
||||
|
||||
func (c *inventoryCount) CompleteInventoryCount(ctx context.Context, req *dto.CompleteInventoryCountReq) (res *dto.CompleteInventoryCountRes, err error) {
|
||||
return service.InventoryCount.Complete(ctx, req)
|
||||
}
|
||||
|
||||
func (c *inventoryCount) CancelInventoryCount(ctx context.Context, req *dto.CancelInventoryCountReq) (res *dto.CancelInventoryCountRes, err error) {
|
||||
return service.InventoryCount.Cancel(ctx, req)
|
||||
}
|
||||
|
||||
func (c *inventoryCount) ExportInventoryCountTemplate(ctx context.Context, req *dto.ExportInventoryCountTemplateReq) (res *dto.ExportInventoryCountTemplateRes, err error) {
|
||||
return service.InventoryCount.ExportTemplate(ctx, req)
|
||||
}
|
||||
|
||||
// ImportInventoryCount 上传盘点Excel
|
||||
// 从multipart form读取文件数据并调用Service层解析导入
|
||||
func (c *inventoryCount) ImportInventoryCount(ctx context.Context, req *dto.ImportInventoryCountReq) (res *dto.ImportInventoryCountRes, err error) {
|
||||
r := g.RequestFromCtx(ctx)
|
||||
file, _, err := r.Request.FormFile("file")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取上传文件失败: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
fileData, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取文件内容失败: %v", err)
|
||||
}
|
||||
|
||||
return service.InventoryCount.ImportInventoryCount(ctx, req, fileData)
|
||||
}
|
||||
47
controller/stock/inventory_count_detail_controller.go
Normal file
47
controller/stock/inventory_count_detail_controller.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// 盘点明细控制器
|
||||
// 职责:盘点明细CRUD、相似商品查询
|
||||
// 调用服务:service.InventoryCountDetail
|
||||
// 注意:Update/Delete返回*beans.ResponseEmpty,直接return
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type inventoryCountDetail struct{}
|
||||
|
||||
var InventoryCountDetail = new(inventoryCountDetail)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *inventoryCountDetail) CreateInventoryCountDetail(ctx context.Context, req *dto.CreateInventoryCountDetailReq) (res *dto.CreateInventoryCountDetailRes, err error) {
|
||||
return service.InventoryCountDetail.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (c *inventoryCountDetail) UpdateInventoryCountDetail(ctx context.Context, req *dto.UpdateInventoryCountDetailReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.InventoryCountDetail.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *inventoryCountDetail) DeleteInventoryCountDetail(ctx context.Context, req *dto.DeleteInventoryCountDetailReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.InventoryCountDetail.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *inventoryCountDetail) GetInventoryCountDetail(ctx context.Context, req *dto.GetInventoryCountDetailReq) (res *dto.GetInventoryCountDetailRes, err error) {
|
||||
return service.InventoryCountDetail.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *inventoryCountDetail) ListInventoryCountDetails(ctx context.Context, req *dto.ListInventoryCountDetailReq) (res *dto.ListInventoryCountDetailRes, err error) {
|
||||
return service.InventoryCountDetail.List(ctx, req)
|
||||
}
|
||||
|
||||
// SearchSimilarAssets 查询相似商品
|
||||
func (c *inventoryCountDetail) SearchSimilarAssets(ctx context.Context, req *dto.SearchSimilarAssetsReq) (res *dto.SearchSimilarAssetsRes, err error) {
|
||||
return service.InventoryCountDetail.SearchSimilarAssets(ctx, req)
|
||||
}
|
||||
26
controller/stock/inventory_warning_controller.go
Normal file
26
controller/stock/inventory_warning_controller.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// 库存预警控制器
|
||||
// 职责:预警查询接口(无Create/Update/Delete,由系统自动生成)
|
||||
// 调用服务:service.InventoryWarning
|
||||
// 注意:只读接口,无写操作
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
)
|
||||
|
||||
type inventoryWarning struct{}
|
||||
|
||||
var InventoryWarning = new(inventoryWarning)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *inventoryWarning) GetInventoryWarning(ctx context.Context, req *dto.GetInventoryWarningReq) (res *dto.GetInventoryWarningRes, err error) {
|
||||
return service.InventoryWarning.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *inventoryWarning) ListInventoryWarnings(ctx context.Context, req *dto.ListInventoryWarningReq) (res *dto.ListInventoryWarningRes, err error) {
|
||||
return service.InventoryWarning.List(ctx, req)
|
||||
}
|
||||
33
controller/stock/inventory_warning_history_controller.go
Normal file
33
controller/stock/inventory_warning_history_controller.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// 库存预警历史控制器
|
||||
// 职责:预警历史查询、删除(无Create/Update,由系统自动归档)
|
||||
// 调用服务:service.InventoryWarningHistory
|
||||
// 注意:Delete返回*beans.ResponseEmpty,直接return
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type inventoryWarningHistory struct{}
|
||||
|
||||
var InventoryWarningHistory = new(inventoryWarningHistory)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *inventoryWarningHistory) GetInventoryWarningHistory(ctx context.Context, req *dto.GetInventoryWarningHistoryReq) (res *dto.GetInventoryWarningHistoryRes, err error) {
|
||||
return service.InventoryWarningHistory.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *inventoryWarningHistory) ListInventoryWarningHistories(ctx context.Context, req *dto.ListInventoryWarningHistoryReq) (res *dto.ListInventoryWarningHistoryRes, err error) {
|
||||
return service.InventoryWarningHistory.List(ctx, req)
|
||||
}
|
||||
|
||||
func (c *inventoryWarningHistory) DeleteInventoryWarningHistory(ctx context.Context, req *dto.DeleteInventoryWarningHistoryReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.InventoryWarningHistory.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
47
controller/stock/location_controller.go
Normal file
47
controller/stock/location_controller.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// 库位控制器
|
||||
// 职责:库位CRUD接口、状态更新接口
|
||||
// 调用服务:service.Location
|
||||
// 注意:Update/Delete/UpdateStatus返回*beans.ResponseEmpty,直接return
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type location struct{}
|
||||
|
||||
var Location = new(location)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *location) CreateLocation(ctx context.Context, req *dto.CreateLocationReq) (res *dto.CreateLocationRes, err error) {
|
||||
return service.Location.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (c *location) UpdateLocation(ctx context.Context, req *dto.UpdateLocationReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Location.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *location) DeleteLocation(ctx context.Context, req *dto.DeleteLocationReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Location.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *location) UpdateLocationStatus(ctx context.Context, req *dto.UpdateLocationStatusReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Location.UpdateStatus(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *location) GetLocation(ctx context.Context, req *dto.GetLocationReq) (res *dto.GetLocationRes, err error) {
|
||||
return service.Location.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *location) ListLocations(ctx context.Context, req *dto.ListLocationReq) (res *dto.ListLocationRes, err error) {
|
||||
return service.Location.List(ctx, req)
|
||||
}
|
||||
57
controller/stock/private_stock_controller.go
Normal file
57
controller/stock/private_stock_controller.go
Normal file
@@ -0,0 +1,57 @@
|
||||
// 实物库存批次控制器
|
||||
// 职责:CRUD接口、移库(MoveStock)、调拨(TransferStock)、出库(Outbound)
|
||||
// 调用服务:service.PrivateStock
|
||||
// 注意:Update/Delete/MoveStock/TransferStock/Outbound返回*beans.ResponseEmpty,直接return
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type privateStockController struct{}
|
||||
|
||||
var PrivateStock = new(privateStockController)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *privateStockController) CreatePrivateStock(ctx context.Context, req *dto.CreatePrivateStockReq) (res *dto.CreatePrivateStockRes, err error) {
|
||||
return service.PrivateStock.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (c *privateStockController) UpdatePrivateStock(ctx context.Context, req *dto.UpdatePrivateStockReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateStock.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *privateStockController) DeletePrivateStock(ctx context.Context, req *dto.DeletePrivateStockReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateStock.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *privateStockController) GetPrivateStock(ctx context.Context, req *dto.GetPrivateStockReq) (res *dto.GetPrivateStockRes, err error) {
|
||||
return service.PrivateStock.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *privateStockController) ListPrivateStocks(ctx context.Context, req *dto.ListPrivateStockReq) (res *dto.ListPrivateStockRes, err error) {
|
||||
return service.PrivateStock.List(ctx, req)
|
||||
}
|
||||
|
||||
func (c *privateStockController) MoveStock(ctx context.Context, req *dto.MoveStockReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateStock.MoveStock(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *privateStockController) TransferStock(ctx context.Context, req *dto.TransferStockReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateStock.TransferStock(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *privateStockController) OutboundPrivateStock(ctx context.Context, req *dto.OutboundPrivateStockReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.PrivateStock.Outbound(ctx, req)
|
||||
return
|
||||
}
|
||||
42
controller/stock/stock_batch_controller.go
Normal file
42
controller/stock/stock_batch_controller.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// 批次库存控制器(逻辑库存)
|
||||
// 职责:批次CRUD接口
|
||||
// 调用服务:service.StockBatch
|
||||
// 注意:Update/Delete返回*beans.ResponseEmpty,直接return
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type stockBatchController struct{}
|
||||
|
||||
var StockBatch = new(stockBatchController)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *stockBatchController) CreateBatch(ctx context.Context, req *dto.CreateBatchReq) (res *dto.CreateBatchRes, err error) {
|
||||
return service.StockBatch.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (c *stockBatchController) UpdateBatch(ctx context.Context, req *dto.UpdateBatchReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.StockBatch.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *stockBatchController) DeleteBatch(ctx context.Context, req *dto.DeleteBatchReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.StockBatch.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *stockBatchController) GetBatch(ctx context.Context, req *dto.GetBatchReq) (res *dto.GetBatchRes, err error) {
|
||||
return service.StockBatch.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *stockBatchController) ListBatches(ctx context.Context, req *dto.ListBatchReq) (res *dto.ListBatchRes, err error) {
|
||||
return service.StockBatch.List(ctx, req)
|
||||
}
|
||||
27
controller/stock/stock_details_controller.go
Normal file
27
controller/stock/stock_details_controller.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// 库存明细控制器(逻辑库存)
|
||||
// 职责:库存明细查询接口(无Create/Update/Delete,由StockManage管理)
|
||||
// 调用服务:service.StockDetails
|
||||
// 注意:只读接口,无写操作
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
)
|
||||
|
||||
type stockDetails struct{}
|
||||
|
||||
// StockDetails 库存控制器
|
||||
var StockDetails = new(stockDetails)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *stockDetails) GetStockDetails(ctx context.Context, req *dto.GetStockDetailsReq) (res *dto.GetStockDetailsRes, err error) {
|
||||
return service.StockDetails.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *stockDetails) ListStockDetails(ctx context.Context, req *dto.ListStockDetailsReq) (res *dto.ListStockDetailsRes, err error) {
|
||||
return service.StockDetails.List(ctx, req)
|
||||
}
|
||||
31
controller/stock/stock_manage_controller.go
Normal file
31
controller/stock/stock_manage_controller.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// 库存管理控制器(Stock公共库存)
|
||||
// 职责:获取库存操作表单字段、入库/出库操作(StockOperation)
|
||||
// 调用服务:service.StockManage
|
||||
// 注意:StockOperation返回*beans.ResponseEmpty,直接return
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type stockManage struct{}
|
||||
|
||||
// StockManage 库存控制器
|
||||
var StockManage = new(stockManage)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
// GetStockFormFields 获取库存操作表单字段
|
||||
func (c *stockManage) GetStockFormFields(ctx context.Context, req *dto.GetStockFormFieldsReq) (res *dto.GetStockFormFieldsRes, err error) {
|
||||
return service.StockManage.GetStockFormFields(ctx, req)
|
||||
}
|
||||
|
||||
func (c *stockManage) StockOperation(ctx context.Context, req *dto.StockOperationReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.StockManage.StockOperation(ctx, req)
|
||||
return
|
||||
}
|
||||
41
controller/stock/unit_conversion_controller.go
Normal file
41
controller/stock/unit_conversion_controller.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// 单位换算控制器
|
||||
// 职责:单位换算规则CRUD接口
|
||||
// 调用服务:service.UnitConversion
|
||||
// 注意:Update/Delete返回*beans.ResponseEmpty,直接return
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type unitConversionController struct{}
|
||||
|
||||
var UnitConversion = new(unitConversionController)
|
||||
|
||||
func init() {}
|
||||
|
||||
// Create 创建单位换算规则
|
||||
func (c *unitConversionController) Create(ctx context.Context, req *dto.CreateUnitConversionReq) (res *dto.CreateUnitConversionRes, err error) {
|
||||
return service.UnitConversion.Create(ctx, req)
|
||||
}
|
||||
|
||||
// Update 更新单位换算规则
|
||||
func (c *unitConversionController) Update(ctx context.Context, req *dto.UpdateUnitConversionReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.UnitConversion.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete 删除单位换算规则
|
||||
func (c *unitConversionController) Delete(ctx context.Context, req *dto.DeleteUnitConversionReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.UnitConversion.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// List 查询单位换算列表
|
||||
func (c *unitConversionController) List(ctx context.Context, req *dto.ListUnitConversionReq) (res *dto.ListUnitConversionRes, err error) {
|
||||
return service.UnitConversion.List(ctx, req)
|
||||
}
|
||||
47
controller/stock/warehouse_controller.go
Normal file
47
controller/stock/warehouse_controller.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// 仓库控制器
|
||||
// 职责:仓库CRUD接口、状态更新接口
|
||||
// 调用服务:service.Warehouse
|
||||
// 注意:Update/Delete/UpdateStatus返回*beans.ResponseEmpty,直接return
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type warehouse struct{}
|
||||
|
||||
var Warehouse = new(warehouse)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *warehouse) CreateWarehouse(ctx context.Context, req *dto.CreateWarehouseReq) (res *dto.CreateWarehouseRes, err error) {
|
||||
return service.Warehouse.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (c *warehouse) UpdateWarehouse(ctx context.Context, req *dto.UpdateWarehouseReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Warehouse.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *warehouse) DeleteWarehouse(ctx context.Context, req *dto.DeleteWarehouseReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Warehouse.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *warehouse) UpdateWarehouseStatus(ctx context.Context, req *dto.UpdateWarehouseStatusReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Warehouse.UpdateStatus(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *warehouse) GetWarehouse(ctx context.Context, req *dto.GetWarehouseReq) (res *dto.GetWarehouseRes, err error) {
|
||||
return service.Warehouse.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *warehouse) ListWarehouses(ctx context.Context, req *dto.ListWarehouseReq) (res *dto.ListWarehouseRes, err error) {
|
||||
return service.Warehouse.List(ctx, req)
|
||||
}
|
||||
47
controller/stock/zone_controller.go
Normal file
47
controller/stock/zone_controller.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// 库区控制器
|
||||
// 职责:库区CRUD接口、状态更新接口
|
||||
// 调用服务:service.Zone
|
||||
// 注意:Update/Delete/UpdateStatus返回*beans.ResponseEmpty,直接return
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type zone struct{}
|
||||
|
||||
var Zone = new(zone)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *zone) CreateZone(ctx context.Context, req *dto.CreateZoneReq) (res *dto.CreateZoneRes, err error) {
|
||||
return service.Zone.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (c *zone) UpdateZone(ctx context.Context, req *dto.UpdateZoneReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Zone.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *zone) DeleteZone(ctx context.Context, req *dto.DeleteZoneReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Zone.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *zone) UpdateZoneStatus(ctx context.Context, req *dto.UpdateZoneStatusReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Zone.UpdateStatus(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *zone) GetZone(ctx context.Context, req *dto.GetZoneReq) (res *dto.GetZoneRes, err error) {
|
||||
return service.Zone.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *zone) ListZones(ctx context.Context, req *dto.ListZoneReq) (res *dto.ListZoneRes, err error) {
|
||||
return service.Zone.List(ctx, req)
|
||||
}
|
||||
97
controller/sync/sync_controller.go
Normal file
97
controller/sync/sync_controller.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/sync"
|
||||
service "assets/service/sync"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type syncController struct{}
|
||||
|
||||
// Sync 同步控制器
|
||||
var Sync = new(syncController)
|
||||
|
||||
// CreateSyncTask 创建同步任务
|
||||
func (c *syncController) CreateSyncTask(ctx context.Context, req *dto.CreateSyncTaskReq) (res *dto.CreateSyncTaskRes, err error) {
|
||||
taskID, err := service.Sync.CreateSyncTask(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.CreateSyncTaskRes{
|
||||
TaskID: taskID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListSyncTasks 获取同步任务列表
|
||||
func (c *syncController) ListSyncTasks(ctx context.Context, req *dto.ListSyncTaskReq) (res *dto.ListSyncTaskRes, err error) {
|
||||
list, total, err := service.Sync.ListSyncTasks(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.ListSyncTaskRes{
|
||||
List: list,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetSyncTask 获取同步任务详情
|
||||
func (c *syncController) GetSyncTask(ctx context.Context, req *dto.GetSyncTaskReq) (res *dto.GetSyncTaskRes, err error) {
|
||||
return service.Sync.GetSyncTask(ctx, req.ID)
|
||||
}
|
||||
|
||||
// UpdateSyncTaskStatus 更新同步任务状态
|
||||
func (c *syncController) UpdateSyncTaskStatus(ctx context.Context, req *dto.UpdateSyncTaskStatusReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.Sync.UpdateSyncTaskStatus(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// SyncAsset 同步资产
|
||||
func (c *syncController) SyncAsset(ctx context.Context, req *dto.SyncAssetReq) (res *dto.SyncAssetRes, err error) {
|
||||
taskID, err := service.Sync.SyncAsset(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.SyncAssetRes{
|
||||
TaskID: taskID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SyncAssetSku 同步资产SKU
|
||||
func (c *syncController) SyncAssetSku(ctx context.Context, req *dto.SyncAssetSkuReq) (res *dto.SyncAssetSkuRes, err error) {
|
||||
taskID, err := service.Sync.SyncAssetSku(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.SyncAssetSkuRes{
|
||||
TaskID: taskID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SyncStock 同步库存
|
||||
func (c *syncController) SyncStock(ctx context.Context, req *dto.SyncStockReq) (res *dto.SyncStockRes, err error) {
|
||||
taskID, err := service.Sync.SyncStock(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.SyncStockRes{
|
||||
TaskID: taskID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BatchSyncAssets 批量同步资产
|
||||
func (c *syncController) BatchSyncAssets(ctx context.Context, req *dto.BatchSyncAssetsReq) (res *dto.BatchSyncAssetsRes, err error) {
|
||||
taskIDs, err := service.Sync.BatchSyncAssets(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dto.BatchSyncAssetsRes{
|
||||
TaskIDs: taskIDs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetPlatformSyncStatus 获取平台同步状态
|
||||
func (c *syncController) GetPlatformSyncStatus(ctx context.Context, req *dto.GetPlatformSyncStatusReq) (res *dto.GetPlatformSyncStatusRes, err error) {
|
||||
return service.Sync.GetPlatformSyncStatus(ctx, req)
|
||||
}
|
||||
110
dao/asset/asset_dao.go
Normal file
110
dao/asset/asset_dao.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/asset"
|
||||
entity "assets/model/entity/asset"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
var Asset = new(assetDao)
|
||||
|
||||
type assetDao struct {
|
||||
}
|
||||
|
||||
// Insert 插入资产
|
||||
func (d *assetDao) Insert(ctx context.Context, req *dto.CreateAssetReq) (id int64, err error) {
|
||||
var result entity.Asset
|
||||
if err = gconv.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
return gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Data(&result).InsertAndGetId()
|
||||
}
|
||||
|
||||
// GetOne 获取单个资产
|
||||
func (d *assetDao) GetOne(ctx context.Context, req *dto.GetAssetReq) (res *entity.Asset, err error) {
|
||||
err = gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Where("id", req.Id).Scan(&res)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新资产
|
||||
func (d *assetDao) Update(ctx context.Context, req *dto.UpdateAssetReq) (err error) {
|
||||
data := g.Map{
|
||||
"name": req.Name,
|
||||
"description": req.Description,
|
||||
"type": req.Type,
|
||||
"category_id": req.CategoryId,
|
||||
"image_url": req.ImageURL,
|
||||
"images": req.Images,
|
||||
"status": req.Status,
|
||||
"online_time": req.OnlineTime,
|
||||
"offline_time": req.OfflineTime,
|
||||
"physical_asset_config": req.PhysicalAssetConfig,
|
||||
"service_asset_config": req.ServiceAssetConfig,
|
||||
"virtual_asset_config": req.VirtualAssetConfig,
|
||||
"metadata": req.Metadata,
|
||||
}
|
||||
_, err = gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Where("id", req.Id).Update(data)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 删除资产-根据id进行假删
|
||||
func (d *assetDao) DeleteFake(ctx context.Context, req *dto.DeleteAssetReq) (err error) {
|
||||
_, err = gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Where("id", req.Id).Update(g.Map{
|
||||
"is_deleted": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// GetOneById 通过ID获取单个资产(内部使用uint64)
|
||||
func (d *assetDao) GetOneById(ctx context.Context, id uint64) (res *entity.Asset, err error) {
|
||||
err = gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Where("id", id).Scan(&res)
|
||||
return
|
||||
}
|
||||
|
||||
// Count 获取资产数量
|
||||
func (d *assetDao) Count(ctx context.Context, req *dto.ListAssetReq) (count int64, err error) {
|
||||
m := d.buildListFilter(ctx, req)
|
||||
c, err := m.Count()
|
||||
return int64(c), err
|
||||
}
|
||||
|
||||
// List 获取资产列表
|
||||
func (d *assetDao) List(ctx context.Context, req *dto.ListAssetReq) (res []entity.Asset, total int, err error) {
|
||||
m := d.buildListFilter(ctx, req)
|
||||
if req.Page != nil {
|
||||
m = m.Page(int(req.Page.PageNum), int(req.Page.PageSize))
|
||||
}
|
||||
err = m.ScanAndCount(&res, &total, false)
|
||||
return
|
||||
}
|
||||
|
||||
// buildListFilter 构建列表查询的过滤条件
|
||||
func (d *assetDao) buildListFilter(ctx context.Context, req *dto.ListAssetReq) *gdb.Model {
|
||||
m := gfdb.DB(ctx).Model(ctx, public.AssetCollection).Cache(ctx).Where("is_deleted", false)
|
||||
|
||||
if !g.IsEmpty(req.Name) {
|
||||
m = m.Where("name", req.Name)
|
||||
}
|
||||
if !g.IsEmpty(req.Type) {
|
||||
m = m.Where("type", req.Type)
|
||||
}
|
||||
if !g.IsEmpty(req.CategoryId) {
|
||||
m = m.Where("category_id", req.CategoryId)
|
||||
}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
m = m.Where("status", req.Status)
|
||||
}
|
||||
if !g.IsEmpty(req.CategoryPath) {
|
||||
m = m.WhereLike("category_path", req.CategoryPath+"%")
|
||||
}
|
||||
if !g.IsEmpty(req.Keyword) {
|
||||
m = m.WhereLike("name", "%"+req.Keyword+"%")
|
||||
}
|
||||
return m
|
||||
}
|
||||
130
dao/asset/asset_sku_dao.go
Normal file
130
dao/asset/asset_sku_dao.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
"assets/model/dto/asset"
|
||||
"assets/model/entity/asset"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var AssetSku = new(assetSku)
|
||||
|
||||
type assetSku struct {
|
||||
}
|
||||
|
||||
// Insert 插入SKU
|
||||
func (d *assetSku) Insert(ctx context.Context, req *dto.CreateAssetSkuReq) (ids []any, err error) {
|
||||
var result *entity.AssetSku
|
||||
if err = utils.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.AssetSkuCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新SKU
|
||||
func (d *assetSku) Update(ctx context.Context, req *dto.UpdateAssetSkuReq) (err error) {
|
||||
buildUpdateData, err := mongo.BuildUpdateData(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{"$set": buildUpdateData}
|
||||
if !g.IsEmpty(req.Stock) {
|
||||
// 从$set中移除stock字段避免$set和$inc冲突
|
||||
delete(buildUpdateData, "stock")
|
||||
update = bson.M{
|
||||
"$inc": bson.M{
|
||||
"stock": req.Stock,
|
||||
},
|
||||
}
|
||||
if len(buildUpdateData) > 0 {
|
||||
update["$set"] = buildUpdateData
|
||||
}
|
||||
}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.AssetSkuCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 删除SKU-根据id进行假删
|
||||
func (d *assetSku) DeleteFake(ctx context.Context, req *dto.DeleteAssetSkuReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.AssetSkuCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 获取单个SKU
|
||||
func (d *assetSku) GetOne(ctx context.Context, req *dto.GetAssetSkuReq, noTenantId bool) (res *entity.AssetSku, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
if noTenantId {
|
||||
err = mongo.DB().NoTenantId().FindOne(ctx, filter, &res, public.AssetSkuCollection)
|
||||
} else {
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.AssetSkuCollection)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetListByAssetIdExcludeCurrentSku 根据资产ID获取SKU列表并且排除当前SKU
|
||||
func (d *assetSku) GetListByAssetIdExcludeCurrentSku(ctx context.Context, assetId *bson.ObjectID, req *dto.ListAssetSkuReq) (res []entity.AssetSku, total int64, err error) {
|
||||
filter := bson.M{"assetId": assetId, "_id": bson.M{"$ne": req.Id}}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.AssetSkuCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取SKU列表
|
||||
func (d *assetSku) List(ctx context.Context, req *dto.ListAssetSkuReq, noTenantId bool) (res []entity.AssetSku, total int64, err error) {
|
||||
// 构建查询过滤条件
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 排序处理
|
||||
req.OrderBy = []beans.OrderBy{
|
||||
{Field: "sort", Order: beans.Asc},
|
||||
{Field: "createdAt", Order: beans.Desc},
|
||||
}
|
||||
if noTenantId {
|
||||
total, err = mongo.DB().NoTenantId().Find(ctx, filter, &res, public.AssetSkuCollection, req.Page, req.OrderBy)
|
||||
} else {
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.AssetSkuCollection, req.Page, req.OrderBy)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// buildListFilter 构建列表查询的过滤条件
|
||||
func (d *assetSku) buildListFilter(ctx context.Context, req *dto.ListAssetSkuReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
if !g.IsEmpty(req.AssetId) {
|
||||
filter["assetId"] = req.AssetId
|
||||
}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
filter["status"] = req.Status
|
||||
}
|
||||
if !g.IsEmpty(req.CategoryPath) {
|
||||
filter["categoryPath"] = bson.M{"$regex": "^" + req.CategoryPath, "$options": "i"}
|
||||
}
|
||||
if !g.IsEmpty(req.Keyword) {
|
||||
orConditions := bson.A{
|
||||
bson.M{"skuName": bson.M{"$regex": req.Keyword, "$options": "i"}},
|
||||
bson.M{"assetName": bson.M{"$regex": req.Keyword, "$options": "i"}},
|
||||
}
|
||||
filter["$or"] = orConditions
|
||||
}
|
||||
if req.MinPrice > 0 {
|
||||
filter["price"] = bson.M{"$gte": req.MinPrice}
|
||||
}
|
||||
if req.MaxPrice > 0 {
|
||||
if filter["price"] == nil {
|
||||
filter["price"] = bson.M{}
|
||||
}
|
||||
filter["price"].(bson.M)["$lte"] = req.MaxPrice
|
||||
}
|
||||
return
|
||||
}
|
||||
95
dao/asset/category_dao.go
Normal file
95
dao/asset/category_dao.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/asset"
|
||||
entity "assets/model/entity/asset"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/gogf/gf/v2/util/guid"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
var Category = new(category)
|
||||
|
||||
type category struct {
|
||||
}
|
||||
|
||||
// Insert 插入分类
|
||||
func (d *category) Insert(ctx context.Context, req *dto.CreateCategoryReq) (res *entity.Category, err error) {
|
||||
if err = gconv.Struct(req, &res); err != nil {
|
||||
return
|
||||
}
|
||||
res.Bid = guid.S()
|
||||
_, err = gfdb.DB(ctx).Model(ctx, public.CategoryCollection).Insert(&res)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Update 更新分类
|
||||
func (d *category) Update(ctx context.Context, req *dto.UpdateCategoryReq) (err error) {
|
||||
model := gfdb.DB(ctx).Model(ctx, public.CategoryCollection).Data(gconv.Map(&req)).OmitEmpty()
|
||||
if !g.IsEmpty(req.Bid) {
|
||||
model.Where("bid", req.Bid)
|
||||
}
|
||||
if !g.IsEmpty(req.Id) {
|
||||
model.Where("id", req.Id)
|
||||
}
|
||||
_, err = model.Update()
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 获取单个分类
|
||||
func (d *category) GetOne(ctx context.Context, req *dto.GetCategoryReq, fields ...string) (category *entity.Category, err error) {
|
||||
model := gfdb.DB(ctx).Model(ctx, public.CategoryCollection)
|
||||
if !g.IsEmpty(req.Bid) {
|
||||
model.Where(entity.CategoryCol.Bid, req.Bid)
|
||||
}
|
||||
if !g.IsEmpty(req.Id) {
|
||||
model.Where(entity.CategoryCol.Id, req.Id)
|
||||
}
|
||||
res, err := model.Fields(fields).One()
|
||||
err = res.Struct(&category)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 删除分类-根据id及父id进行假删
|
||||
func (d *category) DeleteFake(ctx context.Context, req *dto.DeleteCategoryReq) (err error) {
|
||||
model := gfdb.DB(ctx).Model(ctx, public.CategoryCollection)
|
||||
model.Where(entity.CategoryCol.Bid, req.Bid)
|
||||
_, err = model.Delete()
|
||||
return
|
||||
}
|
||||
|
||||
// Count 根据条件统计分类数量
|
||||
func (d *category) Count(ctx context.Context, req *dto.ListCategoryReq) (count int64, err error) {
|
||||
m := d.buildListFilter(ctx, req)
|
||||
c, err := m.Count()
|
||||
return int64(c), err
|
||||
}
|
||||
|
||||
// List 获取分类列表
|
||||
func (d *category) List(ctx context.Context, req *dto.ListCategoryReq, fields ...string) (res []entity.Category, total int, err error) {
|
||||
model := d.buildListFilter(ctx, req)
|
||||
model.Fields(fields)
|
||||
r, total, err := model.AllAndCount(false)
|
||||
err = gconv.Structs(r.List(), &res)
|
||||
return
|
||||
}
|
||||
|
||||
// buildListFilter 构建列表查询的过滤条件
|
||||
func (d *category) buildListFilter(ctx context.Context, req *dto.ListCategoryReq) *gdb.Model {
|
||||
model := gfdb.DB(ctx).Model(ctx, public.CategoryCollection).Model
|
||||
if !g.IsEmpty(req.Keyword) {
|
||||
model.WhereLike(entity.CategoryCol.Name, "%"+req.Keyword+"%")
|
||||
}
|
||||
model.Where(entity.CategoryCol.ParentId, req.ParentId)
|
||||
model.Where(entity.CategoryCol.Status, req.Status)
|
||||
model.OrderAsc(entity.CategoryCol.Sort)
|
||||
model.OrderDesc(entity.CategoryCol.CreatedAt)
|
||||
model.OmitEmptyWhere()
|
||||
return model
|
||||
}
|
||||
116
dao/asset/private_category_dao.go
Normal file
116
dao/asset/private_category_dao.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/asset"
|
||||
entity "assets/model/entity/asset"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var PrivateCategory = new(privateCategory)
|
||||
|
||||
type privateCategory struct{}
|
||||
|
||||
// Insert 插入私域分类
|
||||
func (d *privateCategory) Insert(ctx context.Context, req *dto.CreatePrivateCategoryReq) (ids []interface{}, err error) {
|
||||
var result *entity.PrivateCategory
|
||||
if err = gconv.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.PrivateCategoryCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchInsert 批量插入私域分类
|
||||
func (d *privateCategory) BatchInsert(ctx context.Context, req *dto.BatchCreatePrivateCategoryReq) (ids []interface{}, err error) {
|
||||
items := make([]*entity.PrivateCategory, 0, len(req.Categories))
|
||||
for _, item := range req.Categories {
|
||||
var result *entity.PrivateCategory
|
||||
if err = gconv.Struct(item, &result); err != nil {
|
||||
return
|
||||
}
|
||||
items = append(items, result)
|
||||
}
|
||||
interfaces := make([]interface{}, len(items))
|
||||
for i, item := range items {
|
||||
interfaces[i] = item
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, interfaces, public.PrivateCategoryCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 获取单个私域分类
|
||||
func (d *privateCategory) GetOne(ctx context.Context, id *bson.ObjectID) (category *entity.PrivateCategory, err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &category, public.PrivateCategoryCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新私域分类
|
||||
func (d *privateCategory) Update(ctx context.Context, req *dto.UpdatePrivateCategoryReq) (err error) {
|
||||
buildUpdateData, err := mongo.BuildUpdateData(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
filter := bson.M{"_id": req.ID}
|
||||
update := bson.M{"$set": buildUpdateData}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.PrivateCategoryCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 删除私域分类-根据id进行假删
|
||||
func (d *privateCategory) DeleteFake(ctx context.Context, id *bson.ObjectID) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.PrivateCategoryCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取私域分类列表
|
||||
func (d *privateCategory) List(ctx context.Context, req *dto.ListPrivateCategoryReq) (res []*entity.PrivateCategory, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.PrivateCategoryCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// GetTree 获取私域分类树
|
||||
func (d *privateCategory) GetTree(ctx context.Context) (res []*entity.PrivateCategory, err error) {
|
||||
filter := bson.M{}
|
||||
_, err = mongo.DB().Find(ctx, filter, &res, public.PrivateCategoryCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// GetByParentId 根据父ID获取子分类列表
|
||||
func (d *privateCategory) GetByParentId(ctx context.Context, parentId string) (res []*entity.PrivateCategory, err error) {
|
||||
filter := bson.M{"parentId": parentId}
|
||||
_, err = mongo.DB().Find(ctx, filter, &res, public.PrivateCategoryCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// buildListFilter 构建列表查询的过滤条件
|
||||
func (d *privateCategory) buildListFilter(ctx context.Context, req *dto.ListPrivateCategoryReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
|
||||
if !g.IsEmpty(req.Name) {
|
||||
filter["name"] = bson.M{"$regex": req.Name, "$options": "i"}
|
||||
}
|
||||
if !g.IsEmpty(req.ParentID) {
|
||||
filter["parentId"] = req.ParentID
|
||||
}
|
||||
if !g.IsEmpty(req.Level) {
|
||||
filter["level"] = req.Level
|
||||
}
|
||||
if req.IsLeafNode != nil {
|
||||
filter["isLeafNode"] = *req.IsLeafNode
|
||||
}
|
||||
return
|
||||
}
|
||||
119
dao/asset/private_sku_dao.go
Normal file
119
dao/asset/private_sku_dao.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/asset"
|
||||
entity "assets/model/entity/asset"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var PrivateSku = new(privateSku)
|
||||
|
||||
type privateSku struct{}
|
||||
|
||||
// Insert 插入私域SKU
|
||||
func (d *privateSku) Insert(ctx context.Context, req *dto.CreatePrivateSkuReq) (ids []interface{}, err error) {
|
||||
var result *entity.PrivateSku
|
||||
if err = gconv.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.PrivateSkuCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchInsert 批量插入私域SKU
|
||||
func (d *privateSku) BatchInsert(ctx context.Context, req *dto.BatchCreatePrivateSkuReq) (ids []interface{}, err error) {
|
||||
items := make([]*entity.PrivateSku, 0, len(req.Skus))
|
||||
for _, item := range req.Skus {
|
||||
var result *entity.PrivateSku
|
||||
if err = gconv.Struct(item, &result); err != nil {
|
||||
return
|
||||
}
|
||||
items = append(items, result)
|
||||
}
|
||||
interfaces := make([]interface{}, len(items))
|
||||
for i, item := range items {
|
||||
interfaces[i] = item
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, interfaces, public.PrivateSkuCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 获取单个私域SKU
|
||||
func (d *privateSku) GetOne(ctx context.Context, id *bson.ObjectID) (sku *entity.PrivateSku, err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &sku, public.PrivateSkuCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新私域SKU
|
||||
func (d *privateSku) Update(ctx context.Context, req *dto.UpdatePrivateSkuReq) (err error) {
|
||||
buildUpdateData, err := mongo.BuildUpdateData(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
filter := bson.M{"_id": req.ID}
|
||||
update := bson.M{"$set": buildUpdateData}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.PrivateSkuCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStock 更新库存
|
||||
func (d *privateSku) UpdateStock(ctx context.Context, id *bson.ObjectID, stockChange int) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
update := bson.M{"$inc": bson.M{"stock": stockChange}}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.PrivateSkuCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 删除私域SKU-根据id进行假删
|
||||
func (d *privateSku) DeleteFake(ctx context.Context, id *bson.ObjectID) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.PrivateSkuCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取私域SKU列表
|
||||
func (d *privateSku) List(ctx context.Context, req *dto.ListPrivateSkuReq) (res []*entity.PrivateSku, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.PrivateSkuCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// ListByCategoryPath 根据分类路径获取SKU列表
|
||||
func (d *privateSku) ListByCategoryPath(ctx context.Context, categoryPath string) (res []*entity.PrivateSku, err error) {
|
||||
filter := bson.M{"privateCategoryPath": bson.M{"$regex": "^" + categoryPath, "$options": "i"}}
|
||||
_, err = mongo.DB().Find(ctx, filter, &res, public.PrivateSkuCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// buildListFilter 构建列表查询的过滤条件
|
||||
func (d *privateSku) buildListFilter(ctx context.Context, req *dto.ListPrivateSkuReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
|
||||
if !g.IsEmpty(req.SkuName) {
|
||||
filter["skuName"] = bson.M{"$regex": req.SkuName, "$options": "i"}
|
||||
}
|
||||
if !g.IsEmpty(req.PrivateCategoryPath) {
|
||||
filter["privateCategoryPath"] = bson.M{"$regex": "^" + req.PrivateCategoryPath, "$options": "i"}
|
||||
}
|
||||
if req.MinPrice > 0 {
|
||||
filter["price"] = bson.M{"$gte": req.MinPrice}
|
||||
}
|
||||
if req.MaxPrice > 0 {
|
||||
if filter["price"] == nil {
|
||||
filter["price"] = bson.M{}
|
||||
}
|
||||
filter["price"].(bson.M)["$lte"] = req.MaxPrice
|
||||
}
|
||||
return
|
||||
}
|
||||
325
dao/base/catch_sql.go
Normal file
325
dao/base/catch_sql.go
Normal file
@@ -0,0 +1,325 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// ==================== CatchSQL 全局SQL条件拼接控制 ====================
|
||||
|
||||
// SQLConditionBuilder SQL条件构建器
|
||||
type SQLConditionBuilder struct {
|
||||
// 是否自动添加租户ID条件
|
||||
EnableTenantId bool
|
||||
// 是否自动添加创建人条件
|
||||
EnableCreator bool
|
||||
// 是否自动添加修改人条件
|
||||
EnableUpdater bool
|
||||
// 是否自动添加删除标记条件(只查询未删除数据)
|
||||
EnableDeletedFilter bool
|
||||
// 自定义额外条件
|
||||
ExtraConditions map[string]interface{}
|
||||
}
|
||||
|
||||
// DefaultSQLConditionBuilder 默认SQL条件构建器配置
|
||||
var DefaultSQLConditionBuilder = SQLConditionBuilder{
|
||||
EnableTenantId: true,
|
||||
EnableCreator: false,
|
||||
EnableUpdater: false,
|
||||
EnableDeletedFilter: true,
|
||||
ExtraConditions: make(map[string]interface{}),
|
||||
}
|
||||
|
||||
// ctxKeyCatchSQL 上下文键
|
||||
type ctxKeyCatchSQL string
|
||||
|
||||
const (
|
||||
// ctxKeySQLBuilder SQL构建器上下文键
|
||||
ctxKeySQLBuilder ctxKeyCatchSQL = "catch_sql_builder"
|
||||
// ctxKeySkipCatchSQL 跳过CatchSQL的上下文键
|
||||
ctxKeySkipCatchSQL ctxKeyCatchSQL = "catch_sql_skip"
|
||||
)
|
||||
|
||||
// WithSQLBuilder 设置自定义SQL条件构建器到上下文
|
||||
func WithSQLBuilder(ctx context.Context, builder *SQLConditionBuilder) context.Context {
|
||||
return context.WithValue(ctx, ctxKeySQLBuilder, builder)
|
||||
}
|
||||
|
||||
// GetSQLBuilder 从上下文获取SQL条件构建器
|
||||
func GetSQLBuilder(ctx context.Context) *SQLConditionBuilder {
|
||||
if ctx == nil {
|
||||
return &DefaultSQLConditionBuilder
|
||||
}
|
||||
if builder, ok := ctx.Value(ctxKeySQLBuilder).(*SQLConditionBuilder); ok && builder != nil {
|
||||
return builder
|
||||
}
|
||||
return &DefaultSQLConditionBuilder
|
||||
}
|
||||
|
||||
// SkipCatchSQL 跳过CatchSQL条件拼接
|
||||
func SkipCatchSQL(ctx context.Context) context.Context {
|
||||
return context.WithValue(ctx, ctxKeySkipCatchSQL, true)
|
||||
}
|
||||
|
||||
// IsSkipCatchSQL 检查是否跳过CatchSQL
|
||||
func IsSkipCatchSQL(ctx context.Context) bool {
|
||||
if ctx == nil {
|
||||
return false
|
||||
}
|
||||
v, ok := ctx.Value(ctxKeySkipCatchSQL).(bool)
|
||||
return ok && v
|
||||
}
|
||||
|
||||
// ==================== CatchSQL 核心方法 ====================
|
||||
|
||||
// CatchSQL 全局统一控制SQL条件拼接
|
||||
// 根据上下文自动添加租户ID、创建人、修改人、删除标记等条件
|
||||
// 使用示例:
|
||||
//
|
||||
// // 基础使用(自动添加默认条件)
|
||||
// m := base.CatchSQL(ctx, g.DB().Model("asset"))
|
||||
// m.Where("status", 1).Scan(&result)
|
||||
//
|
||||
// // 自定义条件构建器
|
||||
// builder := &base.SQLConditionBuilder{
|
||||
// EnableTenantId: true,
|
||||
// EnableCreator: true,
|
||||
// }
|
||||
// ctx = base.WithSQLBuilder(ctx, builder)
|
||||
// m := base.CatchSQL(ctx, g.DB().Model("asset"))
|
||||
//
|
||||
// // 跳过CatchSQL
|
||||
// ctx = base.SkipCatchSQL(ctx)
|
||||
// m := base.CatchSQL(ctx, g.DB().Model("asset"))
|
||||
func CatchSQL(ctx context.Context, model *gdb.Model) *gdb.Model {
|
||||
if ctx == nil || model == nil {
|
||||
return model
|
||||
}
|
||||
|
||||
// 检查是否跳过
|
||||
if IsSkipCatchSQL(ctx) {
|
||||
return model
|
||||
}
|
||||
|
||||
builder := GetSQLBuilder(ctx)
|
||||
userInfo, _ := utils.GetUserInfo(ctx)
|
||||
|
||||
// 1. 自动添加租户ID条件
|
||||
if builder.EnableTenantId && !g.IsEmpty(userInfo.TenantId) {
|
||||
model = model.Where("tenant_id", userInfo.TenantId)
|
||||
}
|
||||
|
||||
// 2. 自动添加创建人条件
|
||||
if builder.EnableCreator && !g.IsEmpty(userInfo.UserName) {
|
||||
model = model.Where("creator", userInfo.UserName)
|
||||
}
|
||||
|
||||
// 3. 自动添加修改人条件
|
||||
if builder.EnableUpdater && !g.IsEmpty(userInfo.UserName) {
|
||||
model = model.Where("updater", userInfo.UserName)
|
||||
}
|
||||
|
||||
// 4. 自动添加删除标记条件(只查询未删除数据)
|
||||
if builder.EnableDeletedFilter {
|
||||
model = model.Where("is_deleted", 0)
|
||||
}
|
||||
|
||||
// 5. 添加自定义额外条件
|
||||
for field, value := range builder.ExtraConditions {
|
||||
if field != "" && value != nil {
|
||||
model = model.Where(field, value)
|
||||
}
|
||||
}
|
||||
|
||||
return model
|
||||
}
|
||||
|
||||
// CatchSQLWithTable 指定表名创建带CatchSQL条件的Model
|
||||
// 使用示例:
|
||||
//
|
||||
// m := base.CatchSQLWithTable(ctx, "asset")
|
||||
// m.Where("status", 1).Scan(&result)
|
||||
func CatchSQLWithTable(ctx context.Context, table string) *gdb.Model {
|
||||
if ctx == nil {
|
||||
return g.DB().Model(table).Safe()
|
||||
}
|
||||
model := g.DB().Model(table).Safe().Ctx(ctx)
|
||||
return CatchSQL(ctx, model)
|
||||
}
|
||||
|
||||
// CatchSQLWithSchema 指定Schema和表名创建带CatchSQL条件的Model
|
||||
// 使用示例:
|
||||
//
|
||||
// m := base.CatchSQLWithSchema(ctx, "public", "asset")
|
||||
// m.Where("status", 1).Scan(&result)
|
||||
func CatchSQLWithSchema(ctx context.Context, schema, table string) *gdb.Model {
|
||||
if ctx == nil {
|
||||
return g.DB().Schema(schema).Model(table).Safe()
|
||||
}
|
||||
model := g.DB().Schema(schema).Model(table).Safe().Ctx(ctx)
|
||||
return CatchSQL(ctx, model)
|
||||
}
|
||||
|
||||
// ==================== 快捷条件构建器 ====================
|
||||
|
||||
// NewSQLBuilder 创建新的SQL条件构建器
|
||||
func NewSQLBuilder() *SQLConditionBuilder {
|
||||
return &SQLConditionBuilder{
|
||||
EnableTenantId: true,
|
||||
EnableCreator: false,
|
||||
EnableUpdater: false,
|
||||
EnableDeletedFilter: true,
|
||||
ExtraConditions: make(map[string]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
// WithTenantId 启用/禁用租户ID条件
|
||||
func (b *SQLConditionBuilder) WithTenantId(enable bool) *SQLConditionBuilder {
|
||||
b.EnableTenantId = enable
|
||||
return b
|
||||
}
|
||||
|
||||
// WithCreator 启用/禁用创建人条件
|
||||
func (b *SQLConditionBuilder) WithCreator(enable bool) *SQLConditionBuilder {
|
||||
b.EnableCreator = enable
|
||||
return b
|
||||
}
|
||||
|
||||
// WithUpdater 启用/禁用修改人条件
|
||||
func (b *SQLConditionBuilder) WithUpdater(enable bool) *SQLConditionBuilder {
|
||||
b.EnableUpdater = enable
|
||||
return b
|
||||
}
|
||||
|
||||
// WithDeletedFilter 启用/禁用删除标记过滤
|
||||
func (b *SQLConditionBuilder) WithDeletedFilter(enable bool) *SQLConditionBuilder {
|
||||
b.EnableDeletedFilter = enable
|
||||
return b
|
||||
}
|
||||
|
||||
// WithExtraCondition 添加自定义条件
|
||||
func (b *SQLConditionBuilder) WithExtraCondition(field string, value interface{}) *SQLConditionBuilder {
|
||||
if b.ExtraConditions == nil {
|
||||
b.ExtraConditions = make(map[string]interface{})
|
||||
}
|
||||
b.ExtraConditions[field] = value
|
||||
return b
|
||||
}
|
||||
|
||||
// Build 构建并返回Model
|
||||
func (b *SQLConditionBuilder) Build(ctx context.Context, model *gdb.Model) *gdb.Model {
|
||||
ctx = WithSQLBuilder(ctx, b)
|
||||
return CatchSQL(ctx, model)
|
||||
}
|
||||
|
||||
// ==================== 常用场景快捷方法 ====================
|
||||
|
||||
// CatchSQLForTenant 只添加租户ID条件的快捷方法
|
||||
func CatchSQLForTenant(ctx context.Context, model *gdb.Model) *gdb.Model {
|
||||
builder := NewSQLBuilder().
|
||||
WithTenantId(true).
|
||||
WithDeletedFilter(false)
|
||||
ctx = WithSQLBuilder(ctx, builder)
|
||||
return CatchSQL(ctx, model)
|
||||
}
|
||||
|
||||
// CatchSQLForCreator 只添加创建人条件的快捷方法
|
||||
func CatchSQLForCreator(ctx context.Context, model *gdb.Model) *gdb.Model {
|
||||
builder := NewSQLBuilder().
|
||||
WithTenantId(false).
|
||||
WithCreator(true).
|
||||
WithDeletedFilter(false)
|
||||
ctx = WithSQLBuilder(ctx, builder)
|
||||
return CatchSQL(ctx, model)
|
||||
}
|
||||
|
||||
// CatchSQLForList 列表查询的快捷方法(租户ID + 删除标记)
|
||||
func CatchSQLForList(ctx context.Context, model *gdb.Model) *gdb.Model {
|
||||
builder := NewSQLBuilder().
|
||||
WithTenantId(true).
|
||||
WithDeletedFilter(true)
|
||||
ctx = WithSQLBuilder(ctx, builder)
|
||||
return CatchSQL(ctx, model)
|
||||
}
|
||||
|
||||
// CatchSQLForAdmin 管理员查询的快捷方法(只过滤删除标记,不过滤租户)
|
||||
func CatchSQLForAdmin(ctx context.Context, model *gdb.Model) *gdb.Model {
|
||||
builder := NewSQLBuilder().
|
||||
WithTenantId(false).
|
||||
WithDeletedFilter(true)
|
||||
ctx = WithSQLBuilder(ctx, builder)
|
||||
return CatchSQL(ctx, model)
|
||||
}
|
||||
|
||||
// ==================== DAO层无感知集成 ====================
|
||||
|
||||
// CtxModel 创建带 CatchSQL 条件的 Model(DAO层无感知使用)
|
||||
// 这是推荐的无感知使用方式,直接在 DAO 的 Ctx() 方法中调用
|
||||
//
|
||||
// 使用示例(DAO层):
|
||||
//
|
||||
// func (d *assetDao) Ctx(ctx context.Context) *gdb.Model {
|
||||
// return base.CtxModel(ctx, entity.Asset{})
|
||||
// }
|
||||
//
|
||||
// func (d *assetDao) GetById(ctx context.Context, id uint64) (*entity.Asset, error) {
|
||||
// var result entity.Asset
|
||||
// err := d.Ctx(ctx).Where("id", id).Scan(&result) // 自动带 tenant_id 和 is_deleted=0 条件
|
||||
// return &result, err
|
||||
// }
|
||||
func CtxModel(ctx context.Context, table interface{}) *gdb.Model {
|
||||
if ctx == nil {
|
||||
return g.DB().Model(table).Safe()
|
||||
}
|
||||
model := g.DB().Model(table).Safe().Ctx(ctx)
|
||||
return CatchSQL(ctx, model)
|
||||
}
|
||||
|
||||
// CtxModelWithHook 创建带 CatchSQL 条件和 Hook 的 Model(完整版)
|
||||
// 同时启用 CatchSQL 条件拼接和 CatchSQLHook 自动字段赋值
|
||||
//
|
||||
// 使用示例(DAO层):
|
||||
//
|
||||
// func (d *assetDao) Ctx(ctx context.Context) *gdb.Model {
|
||||
// return base.CtxModelWithHook(ctx, entity.Asset{})
|
||||
// }
|
||||
//
|
||||
// func (d *assetDao) Insert(ctx context.Context, data g.Map) (int64, error) {
|
||||
// return d.Ctx(ctx).Data(data).InsertAndGetId() // 自动赋值 tenant_id, creator, updater
|
||||
// }
|
||||
func CtxModelWithHook(ctx context.Context, table interface{}) *gdb.Model {
|
||||
if ctx == nil {
|
||||
return g.DB().Model(table).Safe()
|
||||
}
|
||||
model := g.DB().Model(table).Safe().Ctx(ctx)
|
||||
// 先应用 CatchSQL 条件
|
||||
model = CatchSQL(ctx, model)
|
||||
// 再应用 Hook(用于 Insert/Update 自动字段赋值)
|
||||
model = model.Hook(CatchSQLHook())
|
||||
return model
|
||||
}
|
||||
|
||||
// ==================== 调试工具 ====================
|
||||
|
||||
// GetCatchSQLInfo 获取当前CatchSQL的配置信息(用于调试)
|
||||
func GetCatchSQLInfo(ctx context.Context) string {
|
||||
if IsSkipCatchSQL(ctx) {
|
||||
return "CatchSQL: skipped"
|
||||
}
|
||||
|
||||
builder := GetSQLBuilder(ctx)
|
||||
userInfo, _ := utils.GetUserInfo(ctx)
|
||||
|
||||
return fmt.Sprintf(
|
||||
"CatchSQL{TenantId:%v(%v), Creator:%v(%v), Updater:%v(%v), DeletedFilter:%v, Extra:%v}",
|
||||
builder.EnableTenantId, userInfo.TenantId,
|
||||
builder.EnableCreator, userInfo.UserName,
|
||||
builder.EnableUpdater, userInfo.UserName,
|
||||
builder.EnableDeletedFilter,
|
||||
len(builder.ExtraConditions),
|
||||
)
|
||||
}
|
||||
75
dao/base/db.go
Normal file
75
dao/base/db.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"github.com/gogf/gf/contrib/drivers/pgsql/v2"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
)
|
||||
|
||||
type GDB struct {
|
||||
*pgsql.Driver
|
||||
}
|
||||
|
||||
var (
|
||||
// customDriverName is my driver name, which is used for registering.
|
||||
customDriverName = "MyDriver"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// It here registers my custom driver in package initialization function "init".
|
||||
// You can later use this type in the database configuration.
|
||||
if err := gdb.Register(customDriverName, &GDB{}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// New creates and returns a database object for mysql.
|
||||
// It implements the interface of gdb.Driver for extra database driver installation.
|
||||
func (d *GDB) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
|
||||
return &GDB{
|
||||
&pgsql.Driver{
|
||||
Core: core,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DoCommit commits current sql and arguments to underlying sql driver.
|
||||
func (d *GDB) DoCommit(ctx context.Context, in gdb.DoCommitInput) (out gdb.DoCommitOutput, err error) {
|
||||
out, err = d.Core.DoCommit(ctx, in)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 其他接口方法
|
||||
func (d *GDB) DoFilter(ctx context.Context, link gdb.Link, sql string, args []any) (string, []any, error) {
|
||||
return d.Core.DoFilter(ctx, link, sql, args)
|
||||
}
|
||||
|
||||
func (d *GDB) DoPrepare(ctx context.Context, link gdb.Link, sql string) (*gdb.Stmt, error) {
|
||||
return d.Core.DoPrepare(ctx, link, sql)
|
||||
}
|
||||
|
||||
func (d *GDB) ConvertValueForField(ctx context.Context, fieldType string, fieldValue any) (any, error) {
|
||||
return fieldValue, nil
|
||||
}
|
||||
func (d *GDB) ConvertValueForLocal(ctx context.Context, fieldType string, fieldValue any) (any, error) {
|
||||
return d.Core.ConvertValueForLocal(ctx, fieldType, fieldValue)
|
||||
}
|
||||
|
||||
func (d *GDB) Exec(ctx context.Context, sql string, args ...any) (sql.Result, error) {
|
||||
in := gdb.DoCommitInput{Type: gdb.SqlTypeExecContext, Sql: sql, Args: args}
|
||||
out, err := d.DoCommit(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Result, nil
|
||||
}
|
||||
func (d *GDB) DoExec(ctx context.Context, link gdb.Link, sql string, args ...any) (sql.Result, error) {
|
||||
in := gdb.DoCommitInput{Type: gdb.SqlTypeExecContext, Sql: sql, Args: args}
|
||||
out, err := d.DoCommit(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Result, nil
|
||||
}
|
||||
456
dao/base/hook.go
Normal file
456
dao/base/hook.go
Normal file
@@ -0,0 +1,456 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"time"
|
||||
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/database/gredis"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcache"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
// ==================== 上下文键定义 ====================
|
||||
|
||||
type ctxKey string
|
||||
|
||||
const (
|
||||
// ctxKeySkipTenant 跳过租户ID自动赋值的上下文键
|
||||
ctxKeySkipTenant ctxKey = "hook_skip_tenant"
|
||||
// ctxKeyCacheEnabled 缓存启用标记的上下文键
|
||||
ctxKeyCacheEnabled ctxKey = "hook_cache_enabled"
|
||||
// ctxKeyCachePrefix 缓存key前缀的上下文键
|
||||
ctxKeyCachePrefix ctxKey = "hook_cache_prefix"
|
||||
)
|
||||
|
||||
// ==================== 租户相关 ====================
|
||||
|
||||
// SkipTenantId 在上下文中标记跳过租户ID自动赋值
|
||||
func SkipTenantId(ctx context.Context) context.Context {
|
||||
return context.WithValue(ctx, ctxKeySkipTenant, true)
|
||||
}
|
||||
|
||||
// isSkipTenant 检查是否跳过租户ID
|
||||
func isSkipTenant(ctx context.Context) bool {
|
||||
if ctx == nil {
|
||||
return false
|
||||
}
|
||||
v, ok := ctx.Value(ctxKeySkipTenant).(bool)
|
||||
return ok && v
|
||||
}
|
||||
|
||||
// ==================== 缓存配置 ====================
|
||||
|
||||
// CacheConfig 缓存配置
|
||||
type CacheConfig struct {
|
||||
// 本地缓存过期时间(秒),默认60秒
|
||||
LocalTTL int
|
||||
// Redis缓存过期时间(秒),默认300秒
|
||||
RedisTTL int
|
||||
}
|
||||
|
||||
// DefaultCacheConfig 默认缓存配置
|
||||
var DefaultCacheConfig = CacheConfig{
|
||||
LocalTTL: 60,
|
||||
RedisTTL: 300,
|
||||
}
|
||||
|
||||
// isCacheEnabled 检查是否启用缓存
|
||||
func isCacheEnabled(ctx context.Context) bool {
|
||||
if ctx == nil {
|
||||
return false
|
||||
}
|
||||
v, ok := ctx.Value(ctxKeyCacheEnabled).(bool)
|
||||
return ok && v
|
||||
}
|
||||
|
||||
// getCachePrefix 获取缓存key前缀
|
||||
func getCachePrefix(ctx context.Context) string {
|
||||
if ctx == nil {
|
||||
return ""
|
||||
}
|
||||
v, ok := ctx.Value(ctxKeyCachePrefix).(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// ==================== 缓存管理器(单例) ====================
|
||||
|
||||
var (
|
||||
localCache *gcache.Cache
|
||||
)
|
||||
|
||||
// getLocalCache 获取本地缓存实例
|
||||
func getLocalCache() *gcache.Cache {
|
||||
if localCache == nil {
|
||||
localCache = gcache.New()
|
||||
}
|
||||
return localCache
|
||||
}
|
||||
|
||||
// buildCacheKey 构建缓存key
|
||||
// 根据表名和查询条件自动生成key
|
||||
func buildCacheKey(prefix string, table string, where ...interface{}) string {
|
||||
// 基础key: prefix:table
|
||||
key := fmt.Sprintf("%s:%s", prefix, table)
|
||||
|
||||
// 如果有where条件,追加到key中
|
||||
if len(where) > 0 {
|
||||
for _, w := range where {
|
||||
key = fmt.Sprintf("%s:%v", key, w)
|
||||
}
|
||||
}
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
// getFromCache 从缓存获取数据(本地缓存 -> Redis)
|
||||
func getFromCache(ctx context.Context, key string) ([]byte, bool) {
|
||||
config := DefaultCacheConfig
|
||||
|
||||
// 1. 先查本地缓存
|
||||
if val, err := getLocalCache().Get(ctx, key); err == nil && val != nil {
|
||||
if data := val.Bytes(); len(data) > 0 {
|
||||
glog.Debugf(ctx, "[Cache] Hit local cache: %s", key)
|
||||
return data, true
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 再查Redis缓存
|
||||
if g.Redis() != nil {
|
||||
result, err := g.Redis().Get(ctx, key)
|
||||
if err == nil && !result.IsEmpty() {
|
||||
data := result.Bytes()
|
||||
// 写入本地缓存
|
||||
getLocalCache().Set(ctx, key, data, time.Duration(config.LocalTTL)*time.Second)
|
||||
glog.Debugf(ctx, "[Cache] Hit redis cache: %s", key)
|
||||
return data, true
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// setToCache 写入缓存(本地缓存 + Redis)
|
||||
func setToCache(ctx context.Context, key string, data []byte) {
|
||||
if len(data) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
config := DefaultCacheConfig
|
||||
|
||||
// 1. 写入本地缓存
|
||||
getLocalCache().Set(ctx, key, data, time.Duration(config.LocalTTL)*time.Second)
|
||||
|
||||
// 2. 写入Redis缓存
|
||||
if g.Redis() != nil {
|
||||
expire := int64(config.RedisTTL)
|
||||
_, err := g.Redis().Set(ctx, key, data, gredis.SetOption{
|
||||
TTLOption: gredis.TTLOption{
|
||||
EX: &expire,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
glog.Warningf(ctx, "[Cache] Failed to set redis cache: %s, err: %v", key, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deleteCache 删除缓存
|
||||
func deleteCache(ctx context.Context, key string) {
|
||||
// 1. 删除本地缓存
|
||||
getLocalCache().Remove(ctx, key)
|
||||
|
||||
// 2. 删除Redis缓存
|
||||
if g.Redis() != nil {
|
||||
_, err := g.Redis().Del(ctx, key)
|
||||
if err != nil {
|
||||
glog.Warningf(ctx, "[Cache] Failed to delete redis cache: %s, err: %v", key, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deleteCacheByPattern 根据模式删除缓存
|
||||
func deleteCacheByPattern(ctx context.Context, pattern string) {
|
||||
// 1. 清空本地缓存(简单实现:清空所有)
|
||||
getLocalCache().Clear(ctx)
|
||||
|
||||
// 2. 删除Redis缓存(使用SCAN+DEL)
|
||||
if g.Redis() != nil {
|
||||
var cursor uint64 = 0
|
||||
for {
|
||||
result, err := g.Redis().Do(ctx, "SCAN", cursor, "MATCH", pattern, "COUNT", 100)
|
||||
if err != nil {
|
||||
glog.Warningf(ctx, "[Cache] Failed to scan redis keys: %s, err: %v", pattern, err)
|
||||
break
|
||||
}
|
||||
|
||||
resultMap := result.Map()
|
||||
cursor = gconv.Uint64(resultMap["cursor"])
|
||||
keys := gconv.Strings(resultMap["keys"])
|
||||
|
||||
if len(keys) > 0 {
|
||||
args := make([]interface{}, len(keys))
|
||||
for i, k := range keys {
|
||||
args[i] = k
|
||||
}
|
||||
_, err = g.Redis().Do(ctx, "DEL", args...)
|
||||
if err != nil {
|
||||
glog.Warningf(ctx, "[Cache] Failed to delete redis keys: %v, err: %v", keys, err)
|
||||
}
|
||||
}
|
||||
|
||||
if cursor == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 统一Hook入口 ====================
|
||||
|
||||
// CatchSQLHook 返回统一的 HookHandler(包含租户自动赋值和缓存)
|
||||
// 使用示例:
|
||||
//
|
||||
// // 基础使用(自动租户赋值,无缓存)
|
||||
// g.DB().Model("user").Hook(base.CatchSQLHook()).Ctx(ctx).Insert(data)
|
||||
//
|
||||
// // 启用缓存(用户无感知,自动处理缓存key)
|
||||
// ctx = base.WithCacheEnabled(ctx, "asset")
|
||||
// Asset.CtxWithCache(ctx).Where("id", 123).Scan(&result)
|
||||
func CatchSQLHook() gdb.HookHandler {
|
||||
return gdb.HookHandler{
|
||||
Insert: insertHook,
|
||||
Update: updateHook,
|
||||
Delete: deleteHook,
|
||||
Select: selectHook,
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Insert钩子 ====================
|
||||
|
||||
func insertHook(ctx context.Context, in *gdb.HookInsertInput) (result sql.Result, err error) {
|
||||
// 1. 自动赋值租户字段
|
||||
userInfo, _ := utils.GetUserInfo(ctx)
|
||||
|
||||
if !g.IsEmpty(userInfo.TenantId) {
|
||||
in.Model.Data("tenant_id", userInfo.TenantId)
|
||||
}
|
||||
if !g.IsEmpty(userInfo.UserName) {
|
||||
in.Model.Data("creator", userInfo.UserName)
|
||||
in.Model.Data("updater", userInfo.UserName)
|
||||
}
|
||||
//for i := range in.Data {
|
||||
// if !g.IsEmpty(userInfo.TenantId) {
|
||||
// if _, ok := in.Data[i]["tenant_id"]; !ok {
|
||||
// in.Data[i]["tenant_id"] = userInfo.TenantId
|
||||
// }
|
||||
// }
|
||||
// if !g.IsEmpty(userInfo.UserId) {
|
||||
// if _, ok := in.Data[i]["creator"]; !ok {
|
||||
// in.Data[i]["creator"] = userInfo.UserId
|
||||
// }
|
||||
// if _, ok := in.Data[i]["updater"]; !ok {
|
||||
// in.Data[i]["updater"] = userInfo.UserId
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
// 2. 执行插入
|
||||
result, err = in.Next(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 3. 清除相关缓存
|
||||
prefix := getCachePrefix(ctx)
|
||||
if prefix != "" {
|
||||
deleteCacheByPattern(ctx, prefix+":*")
|
||||
glog.Debugf(ctx, "[Hook] Cache cleared after insert, prefix: %s", prefix)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ==================== Update钩子 ====================
|
||||
|
||||
func updateHook(ctx context.Context, in *gdb.HookUpdateInput) (result sql.Result, err error) {
|
||||
// 1. 自动赋值修改人
|
||||
userInfo, _ := utils.GetUserInfo(ctx)
|
||||
|
||||
if !g.IsEmpty(userInfo.TenantId) {
|
||||
in.Model.Where("tenant_id", userInfo.TenantId)
|
||||
}
|
||||
if !g.IsEmpty(userInfo.UserName) {
|
||||
in.Model.Where("creator", userInfo.UserName)
|
||||
in.Model.Where("updater", userInfo.UserName)
|
||||
}
|
||||
|
||||
//switch data := in.Data.(type) {
|
||||
//case gdb.Map:
|
||||
// if !g.IsEmpty(userInfo.UserId) {
|
||||
// if _, ok := data["updater"]; !ok {
|
||||
// data["updater"] = userInfo.UserId
|
||||
// }
|
||||
// }
|
||||
//case gdb.List:
|
||||
// for i := range data {
|
||||
// if !g.IsEmpty(userInfo.UserId) {
|
||||
// if _, ok := data[i]["updater"]; !ok {
|
||||
// data[i]["updater"] = userInfo.UserId
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
// 2. 执行更新
|
||||
result, err = in.Next(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 3. 清除相关缓存
|
||||
prefix := getCachePrefix(ctx)
|
||||
if prefix != "" {
|
||||
deleteCacheByPattern(ctx, prefix+":*")
|
||||
glog.Debugf(ctx, "[Hook] Cache cleared after update, prefix: %s", prefix)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ==================== Delete钩子 ====================
|
||||
|
||||
func deleteHook(ctx context.Context, in *gdb.HookDeleteInput) (result sql.Result, err error) {
|
||||
// 1. 执行删除
|
||||
result, err = in.Next(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 2. 清除相关缓存
|
||||
prefix := getCachePrefix(ctx)
|
||||
if prefix != "" {
|
||||
deleteCacheByPattern(ctx, prefix+":*")
|
||||
glog.Debugf(ctx, "[Hook] Cache cleared after delete, prefix: %s", prefix)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ==================== Select钩子(缓存读取) ====================
|
||||
|
||||
func selectHook(ctx context.Context, in *gdb.HookSelectInput) (result gdb.Result, err error) {
|
||||
|
||||
userInfo, _ := utils.GetUserInfo(ctx)
|
||||
|
||||
if !isSkipTenant(ctx) && !g.IsEmpty(userInfo.TenantId) {
|
||||
in.Model.Where("tenant_id", userInfo.TenantId)
|
||||
}
|
||||
|
||||
// 未启用缓存,直接执行查询
|
||||
if !isCacheEnabled(ctx) {
|
||||
return in.Next(ctx)
|
||||
}
|
||||
|
||||
prefix := getCachePrefix(ctx)
|
||||
if prefix == "" {
|
||||
return in.Next(ctx)
|
||||
}
|
||||
|
||||
// 从 SQL 字符串中提取 WHERE 条件部分
|
||||
whereCondition := extractWhereCondition(in.Sql)
|
||||
|
||||
// 构建缓存key:prefix:table:where条件:args
|
||||
cacheKey := buildCacheKey(prefix, in.Table, whereCondition, in.Args)
|
||||
|
||||
glog.Debugf(ctx, "[Hook] Cache key: %s", cacheKey)
|
||||
|
||||
// 1. 先查缓存
|
||||
if data, ok := getFromCache(ctx, cacheKey); ok {
|
||||
var records gdb.Result
|
||||
if err := json.Unmarshal(data, &records); err == nil && len(records) > 0 {
|
||||
glog.Debugf(ctx, "[Hook] Cache hit for key: %s", cacheKey)
|
||||
return records, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 执行数据库查询
|
||||
result, err = in.Next(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 3. 写入缓存
|
||||
if len(result) > 0 {
|
||||
if data, err := json.Marshal(result); err == nil {
|
||||
setToCache(ctx, cacheKey, data)
|
||||
glog.Debugf(ctx, "[Hook] Cache set for key: %s", cacheKey)
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// extractWhereCondition 从 SQL 语句中提取 WHERE 条件部分
|
||||
func extractWhereCondition(sql string) string {
|
||||
// 查找 WHERE 关键字(不区分大小写)
|
||||
whereIndex := gstr.PosI(sql, " WHERE ")
|
||||
if whereIndex == -1 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 提取 WHERE 之后的内容
|
||||
whereClause := sql[whereIndex+7:]
|
||||
|
||||
// 移除 ORDER BY, GROUP BY, HAVING, LIMIT 等后续子句
|
||||
for _, keyword := range []string{" ORDER BY ", " GROUP BY ", " HAVING ", " LIMIT ", " FOR UPDATE"} {
|
||||
if idx := gstr.PosI(whereClause, keyword); idx != -1 {
|
||||
whereClause = whereClause[:idx]
|
||||
}
|
||||
}
|
||||
|
||||
return whereClause
|
||||
}
|
||||
|
||||
// ==================== 快捷方法 ====================
|
||||
|
||||
type gfdb interface {
|
||||
Model(tableNameOrStruct ...any) *Model
|
||||
}
|
||||
type cache interface {
|
||||
Cache(ctx context.Context) *gdb.Model
|
||||
}
|
||||
type Model struct {
|
||||
*gdb.Model
|
||||
}
|
||||
|
||||
type DataBase struct {
|
||||
gdb.DB
|
||||
DbName string
|
||||
}
|
||||
|
||||
func DB(dbName string) gfdb {
|
||||
return &DataBase{
|
||||
DB: g.DB(dbName),
|
||||
DbName: dbName,
|
||||
}
|
||||
}
|
||||
func (d *DataBase) Model(tableNameOrStruct ...any) *Model {
|
||||
return &Model{
|
||||
Model: d.DB.Model(tableNameOrStruct...),
|
||||
}
|
||||
}
|
||||
func (d *Model) Cache(ctx context.Context) *gdb.Model {
|
||||
ctx = context.WithValue(ctx, ctxKeyCachePrefix, true)
|
||||
return d.Model
|
||||
}
|
||||
219
dao/base/interceptor.go
Normal file
219
dao/base/interceptor.go
Normal file
@@ -0,0 +1,219 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// ==================== SQL 拦截器(真正无感知) ====================
|
||||
|
||||
// SQLInterceptor SQL拦截器配置
|
||||
type SQLInterceptor struct {
|
||||
// 是否启用租户ID自动注入
|
||||
EnableTenantId bool
|
||||
// 是否启用删除标记过滤
|
||||
EnableDeletedFilter bool
|
||||
// 需要拦截的表(空表示所有表)
|
||||
IncludeTables []string
|
||||
// 排除的表
|
||||
ExcludeTables []string
|
||||
}
|
||||
|
||||
// DefaultSQLInterceptor 默认拦截器配置
|
||||
var DefaultSQLInterceptor = &SQLInterceptor{
|
||||
EnableTenantId: true,
|
||||
EnableDeletedFilter: true,
|
||||
IncludeTables: []string{},
|
||||
ExcludeTables: []string{"sys_config", "sys_dict"}, // 排除系统表
|
||||
}
|
||||
|
||||
// currentInterceptor 当前使用的拦截器
|
||||
var currentInterceptor = DefaultSQLInterceptor
|
||||
|
||||
// SetSQLInterceptor 设置全局SQL拦截器
|
||||
func SetSQLInterceptor(interceptor *SQLInterceptor) {
|
||||
currentInterceptor = interceptor
|
||||
}
|
||||
|
||||
// GetSQLInterceptor 获取当前SQL拦截器
|
||||
func GetSQLInterceptor() *SQLInterceptor {
|
||||
return currentInterceptor
|
||||
}
|
||||
|
||||
// ==================== 无感知集成方法 ====================
|
||||
|
||||
// InitSQLInterceptor 初始化SQL拦截器(在 main.go 中调用)
|
||||
// 调用后,所有 g.DB().Model() 创建的查询都会自动注入条件
|
||||
//
|
||||
// func main() {
|
||||
// base.InitSQLInterceptor()
|
||||
// // 之后所有 g.DB().Model() 都会自动注入 tenant_id 和 is_deleted=0
|
||||
// }
|
||||
func InitSQLInterceptor() {
|
||||
// 通过设置全局 Hook 实现拦截
|
||||
// 注意:这会替换所有 DB 操作的 Hook
|
||||
hook := gdb.HookHandler{
|
||||
Select: selectInterceptor,
|
||||
}
|
||||
// 保存原始 Hook(如果有)
|
||||
// 这里只是注册,实际需要在每个 Model 上使用
|
||||
_ = hook
|
||||
}
|
||||
|
||||
// selectInterceptor SELECT 查询拦截器
|
||||
func selectInterceptor(ctx context.Context, in *gdb.HookSelectInput) (result gdb.Result, err error) {
|
||||
// 获取当前配置
|
||||
interceptor := GetSQLInterceptor()
|
||||
if interceptor == nil || !interceptor.EnableTenantId {
|
||||
return in.Next(ctx)
|
||||
}
|
||||
|
||||
// 检查是否需要拦截
|
||||
if !shouldIntercept(in.Table) {
|
||||
return in.Next(ctx)
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
userInfo, _ := utils.GetUserInfo(ctx)
|
||||
if g.IsEmpty(userInfo.TenantId) {
|
||||
return in.Next(ctx)
|
||||
}
|
||||
|
||||
// 检查 SQL 是否已包含 tenant_id 条件
|
||||
sql := in.Sql
|
||||
if !strings.Contains(sql, "tenant_id") {
|
||||
// 注入 tenant_id 条件
|
||||
// 注意:这里只是示例,实际修改 SQL 需要解析和重建 SQL
|
||||
// 更简单的方式是在 Model 层处理
|
||||
g.Log().Debug(ctx, "SQL拦截: 需要注入 tenant_id 条件", sql)
|
||||
}
|
||||
|
||||
return in.Next(ctx)
|
||||
}
|
||||
|
||||
// shouldIntercept 检查表是否需要拦截
|
||||
func shouldIntercept(table string) bool {
|
||||
interceptor := GetSQLInterceptor()
|
||||
if interceptor == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查排除列表
|
||||
for _, exclude := range interceptor.ExcludeTables {
|
||||
if table == exclude {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 检查包含列表
|
||||
if len(interceptor.IncludeTables) > 0 {
|
||||
for _, include := range interceptor.IncludeTables {
|
||||
if table == include {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// ==================== 实用方法:修改现有 DAO ====================
|
||||
|
||||
// WrapModel 包装现有 Model,添加自动条件注入
|
||||
// 用于改造现有 DAO,保持业务代码不变
|
||||
//
|
||||
// // 原 DAO 代码:
|
||||
// func (d *assetDao) Ctx(ctx context.Context) *gdb.Model {
|
||||
// return g.DB().Model(entity.Asset{}).Safe()
|
||||
// }
|
||||
//
|
||||
// // 改造后(只需改 Ctx 方法):
|
||||
// func (d *assetDao) Ctx(ctx context.Context) *gdb.Model {
|
||||
// return base.WrapModel(ctx, g.DB().Model(entity.Asset{}).Safe())
|
||||
// }
|
||||
func WrapModel(ctx context.Context, model *gdb.Model) *gdb.Model {
|
||||
if ctx == nil || model == nil {
|
||||
return model
|
||||
}
|
||||
return CatchSQL(ctx, model)
|
||||
}
|
||||
|
||||
// WrapDB 包装 g.DB(),返回带自动条件注入的查询构建器
|
||||
// 这是推荐的无感知使用方式
|
||||
//
|
||||
// // 在 DAO 中使用:
|
||||
// func (d *assetDao) Ctx(ctx context.Context) *gdb.Model {
|
||||
// return base.WrapDB(ctx).Model(entity.Asset{})
|
||||
// }
|
||||
//
|
||||
// // 业务代码保持原生写法:
|
||||
// func (d *assetDao) GetById(ctx context.Context, id uint64) (*entity.Asset, error) {
|
||||
// var result entity.Asset
|
||||
// err := d.Ctx(ctx).Where("id", id).Scan(&result)
|
||||
// return &result, err
|
||||
// }
|
||||
func WrapDB(ctx context.Context) *DBBuilder {
|
||||
return &DBBuilder{
|
||||
ctx: ctx,
|
||||
db: g.DB(),
|
||||
}
|
||||
}
|
||||
|
||||
// DBBuilder 数据库查询构建器
|
||||
type DBBuilder struct {
|
||||
ctx context.Context
|
||||
db gdb.DB
|
||||
}
|
||||
|
||||
// Model 创建 Model,自动注入条件
|
||||
func (b *DBBuilder) Model(tableNameOrStruct ...interface{}) *gdb.Model {
|
||||
model := b.db.Model(tableNameOrStruct...).Safe()
|
||||
if b.ctx != nil {
|
||||
model = CatchSQL(b.ctx, model)
|
||||
}
|
||||
return model
|
||||
}
|
||||
|
||||
// Schema 指定 Schema
|
||||
func (b *DBBuilder) Schema(schema string) *SchemaBuilder {
|
||||
return &SchemaBuilder{
|
||||
ctx: b.ctx,
|
||||
schema: b.db.Schema(schema),
|
||||
}
|
||||
}
|
||||
|
||||
// SchemaBuilder Schema 查询构建器
|
||||
type SchemaBuilder struct {
|
||||
ctx context.Context
|
||||
schema gdb.DB
|
||||
}
|
||||
|
||||
// Model 创建 Model,自动注入条件
|
||||
func (s *SchemaBuilder) Model(tableNameOrStruct ...interface{}) *gdb.Model {
|
||||
model := s.schema.Model(tableNameOrStruct...).Safe()
|
||||
if s.ctx != nil {
|
||||
model = CatchSQL(s.ctx, model)
|
||||
}
|
||||
return model
|
||||
}
|
||||
|
||||
// ==================== 全局替换方案 ====================
|
||||
|
||||
// ReplaceGDB 替换全局 g.DB() 行为(实验性)
|
||||
// 警告:这会修改全局行为,请谨慎使用
|
||||
//
|
||||
// func init() {
|
||||
// base.ReplaceGDB()
|
||||
// }
|
||||
//
|
||||
// // 之后所有 g.DB().Model().Ctx(ctx) 都会自动注入条件
|
||||
func ReplaceGDB() {
|
||||
// 注意:GoFrame 不支持直接替换 g.DB()
|
||||
// 建议使用 WrapDB 或修改 DAO 的 Ctx 方法
|
||||
g.Log().Info(context.Background(), "ReplaceGDB: 请使用 WrapDB 或修改 DAO 的 Ctx 方法来实现无感知集成")
|
||||
}
|
||||
105
dao/procurement/purchase_inbound_dao.go
Normal file
105
dao/procurement/purchase_inbound_dao.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/procurement"
|
||||
entity "assets/model/entity/procurement"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
type purchaseInbound struct{}
|
||||
|
||||
var PurchaseInbound = new(purchaseInbound)
|
||||
|
||||
// Insert 插入
|
||||
func (d *purchaseInbound) Insert(ctx context.Context, req *dto.CreatePurchaseInboundReq) (ids []interface{}, err error) {
|
||||
var result *entity.PurchaseInbound
|
||||
if err = utils.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.PurchaseInboundCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 查询单个
|
||||
func (d *purchaseInbound) GetOne(ctx context.Context, req *dto.GetPurchaseInboundReq) (res *entity.PurchaseInbound, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB(false).FindOne(ctx, filter, &res, public.PurchaseInboundCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// List 查询列表
|
||||
func (d *purchaseInbound) List(ctx context.Context, req *dto.ListPurchaseInboundReq) (list []entity.PurchaseInbound, total int64, err error) {
|
||||
filter := d.buildListFilter(req)
|
||||
var orderBy []beans.OrderBy
|
||||
if req.OrderBy.Field != "" {
|
||||
orderBy = []beans.OrderBy{req.OrderBy}
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &list, public.PurchaseInboundCollection, &req.Page, orderBy)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateDetails 更新入库记录详细信息
|
||||
func (d *purchaseInbound) UpdateDetails(ctx context.Context, id *bson.ObjectID, orderId *bson.ObjectID, inboundNo, batchNo, warehouseName, zoneName, locationName, privateSkuName, privateCategoryPath string) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"orderId": orderId,
|
||||
"inboundNo": inboundNo,
|
||||
"batchNo": batchNo,
|
||||
"warehouseName": warehouseName,
|
||||
"zoneName": zoneName,
|
||||
"locationName": locationName,
|
||||
"privateSkuName": privateSkuName,
|
||||
"privateCategoryPath": privateCategoryPath,
|
||||
},
|
||||
}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.PurchaseInboundCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdatePrivateStockId 更新入库记录关联的库存ID
|
||||
func (d *purchaseInbound) UpdatePrivateStockId(ctx context.Context, id, privateStockId *bson.ObjectID) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"privateStockId": privateStockId,
|
||||
},
|
||||
}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.PurchaseInboundCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// buildListFilter 构建列表过滤条件
|
||||
func (d *purchaseInbound) buildListFilter(req *dto.ListPurchaseInboundReq) bson.M {
|
||||
filter := bson.M{}
|
||||
if !g.IsEmpty(req.OrderId) {
|
||||
filter["orderId"] = req.OrderId
|
||||
}
|
||||
if !g.IsEmpty(req.OrderItemId) {
|
||||
filter["orderItemId"] = req.OrderItemId
|
||||
}
|
||||
if !g.IsEmpty(req.InboundNo) {
|
||||
filter["inboundNo"] = bson.M{"$regex": req.InboundNo, "$options": "i"}
|
||||
}
|
||||
if !g.IsEmpty(req.StartDate) {
|
||||
startTime, _ := gtime.StrToTime(req.StartDate + " 00:00:00")
|
||||
filter["inboundDate"] = bson.M{"$gte": startTime}
|
||||
}
|
||||
if !g.IsEmpty(req.EndDate) {
|
||||
endTime, _ := gtime.StrToTime(req.EndDate + " 23:59:59")
|
||||
if filter["inboundDate"] != nil {
|
||||
filter["inboundDate"].(bson.M)["$lte"] = endTime
|
||||
} else {
|
||||
filter["inboundDate"] = bson.M{"$lte": endTime}
|
||||
}
|
||||
}
|
||||
return filter
|
||||
}
|
||||
113
dao/procurement/purchase_order_dao.go
Normal file
113
dao/procurement/purchase_order_dao.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/procurement"
|
||||
entity "assets/model/entity/procurement"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var PurchaseOrder = new(purchaseOrder)
|
||||
|
||||
type purchaseOrder struct{}
|
||||
|
||||
// Insert 插入采购订单
|
||||
func (d *purchaseOrder) Insert(ctx context.Context, req *dto.CreatePurchaseOrderReq) (ids []any, err error) {
|
||||
var result *entity.PurchaseOrder
|
||||
if err = utils.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.PurchaseOrderCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchInsert 批量插入采购订单
|
||||
func (d *purchaseOrder) BatchInsert(ctx context.Context, req *dto.BatchCreatePurchaseOrdersReq) (ids []any, err error) {
|
||||
items := make([]*entity.PurchaseOrder, 0, len(req.Orders))
|
||||
for _, item := range req.Orders {
|
||||
var result *entity.PurchaseOrder
|
||||
if err = utils.Struct(item, &result); err != nil {
|
||||
return
|
||||
}
|
||||
items = append(items, result)
|
||||
}
|
||||
// 转换为 interface{} 切片
|
||||
interfaces := make([]interface{}, len(items))
|
||||
for i, item := range items {
|
||||
interfaces[i] = item
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, interfaces, public.PurchaseOrderCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 获取单个采购订单
|
||||
func (d *purchaseOrder) GetOne(ctx context.Context, id *bson.ObjectID) (order *entity.PurchaseOrder, err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &order, public.PurchaseOrderCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新采购订单
|
||||
func (d *purchaseOrder) Update(ctx context.Context, req *dto.UpdatePurchaseOrderReq) (err error) {
|
||||
buildUpdateData, err := mongo.BuildUpdateData(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
filter := bson.M{"_id": req.ID}
|
||||
update := bson.M{"$set": buildUpdateData}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.PurchaseOrderCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 删除采购订单-根据id进行假删
|
||||
func (d *purchaseOrder) DeleteFake(ctx context.Context, id *bson.ObjectID) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.PurchaseOrderCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取采购订单列表
|
||||
func (d *purchaseOrder) List(ctx context.Context, req *dto.ListPurchaseOrdersReq) (res []*entity.PurchaseOrder, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.PurchaseOrderCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// ListByBuyerId 根据采购方ID获取采购订单列表
|
||||
func (d *purchaseOrder) ListByBuyerId(ctx context.Context, buyerId *bson.ObjectID) (res []*entity.PurchaseOrder, err error) {
|
||||
filter := bson.M{"buyerId": buyerId}
|
||||
_, err = mongo.DB().Find(ctx, filter, &res, public.PurchaseOrderCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// buildListFilter 构建列表查询的过滤条件
|
||||
func (d *purchaseOrder) buildListFilter(ctx context.Context, req *dto.ListPurchaseOrdersReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
|
||||
if !g.IsEmpty(req.OrderNo) {
|
||||
filter["orderNo"] = req.OrderNo
|
||||
}
|
||||
if !g.IsEmpty(req.Title) {
|
||||
filter["title"] = bson.M{"$regex": req.Title, "$options": "i"}
|
||||
}
|
||||
if req.BuyerId != nil {
|
||||
filter["buyerId"] = req.BuyerId
|
||||
}
|
||||
if req.OrderType != "" {
|
||||
filter["orderType"] = req.OrderType
|
||||
}
|
||||
if req.Status != nil {
|
||||
filter["status"] = *req.Status
|
||||
}
|
||||
return
|
||||
}
|
||||
141
dao/procurement/purchase_order_item_dao.go
Normal file
141
dao/procurement/purchase_order_item_dao.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/procurement"
|
||||
entity "assets/model/entity/procurement"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var PurchaseOrderItem = new(purchaseOrderItem)
|
||||
|
||||
type purchaseOrderItem struct{}
|
||||
|
||||
// Insert 插入采购订单明细
|
||||
func (d *purchaseOrderItem) Insert(ctx context.Context, req *dto.CreatePurchaseOrderItemReq) (ids []any, err error) {
|
||||
var result *entity.PurchaseOrderItem
|
||||
if err = gconv.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.PurchaseOrderItemCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchInsert 批量插入采购订单明细
|
||||
func (d *purchaseOrderItem) BatchInsert(ctx context.Context, req *dto.BatchCreatePurchaseOrderItemsReq) (ids []any, err error) {
|
||||
items := make([]*entity.PurchaseOrderItem, 0, len(req.Items))
|
||||
for _, item := range req.Items {
|
||||
var result *entity.PurchaseOrderItem
|
||||
if err = gconv.Struct(item, &result); err != nil {
|
||||
return
|
||||
}
|
||||
items = append(items, result)
|
||||
}
|
||||
// 转换为 interface{} 切片
|
||||
interfaces := make([]interface{}, len(items))
|
||||
for i, item := range items {
|
||||
interfaces[i] = item
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, interfaces, public.PurchaseOrderItemCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 获取单个采购订单明细
|
||||
func (d *purchaseOrderItem) GetOne(ctx context.Context, id *bson.ObjectID) (item *entity.PurchaseOrderItem, err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &item, public.PurchaseOrderItemCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新采购订单明细
|
||||
func (d *purchaseOrderItem) Update(ctx context.Context, req *dto.UpdatePurchaseOrderItemReq) (err error) {
|
||||
buildUpdateData, err := mongo.BuildUpdateData(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
filter := bson.M{"_id": req.ID}
|
||||
update := bson.M{"$set": buildUpdateData}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.PurchaseOrderItemCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// IncrementInboundQty 原子增加已入库数量(并发安全)
|
||||
// 使用$inc + $expr条件:inboundQty + deltaQty <= passQuantity,防止并发超量入库
|
||||
func (d *purchaseOrderItem) IncrementInboundQty(ctx context.Context, id *bson.ObjectID, deltaQty int) (err error) {
|
||||
filter := bson.M{
|
||||
"_id": id,
|
||||
"$expr": bson.M{
|
||||
"$lte": bson.A{
|
||||
bson.M{"$add": bson.A{"$inboundQty", deltaQty}},
|
||||
"$passQuantity",
|
||||
},
|
||||
},
|
||||
}
|
||||
update := bson.M{
|
||||
"$inc": bson.M{
|
||||
"inboundQty": deltaQty,
|
||||
},
|
||||
}
|
||||
modifiedCount, err := mongo.DB().Update(ctx, filter, update, public.PurchaseOrderItemCollection)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if modifiedCount == 0 {
|
||||
return gerror.Newf("入库数量超出签收数量限制,本次入库%d", deltaQty)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 删除采购订单明细-根据id进行假删
|
||||
func (d *purchaseOrderItem) DeleteFake(ctx context.Context, id *bson.ObjectID) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.PurchaseOrderItemCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取采购订单明细列表
|
||||
func (d *purchaseOrderItem) List(ctx context.Context, req *dto.ListPurchaseOrderItemsReq) (res []*entity.PurchaseOrderItem, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.PurchaseOrderItemCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// ListByOrderId 根据订单ID获取采购订单明细列表
|
||||
func (d *purchaseOrderItem) ListByOrderId(ctx context.Context, orderId *bson.ObjectID) (res []*entity.PurchaseOrderItem, err error) {
|
||||
filter := bson.M{"orderId": orderId}
|
||||
_, err = mongo.DB().Find(ctx, filter, &res, public.PurchaseOrderItemCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// buildListFilter 构建列表查询的过滤条件
|
||||
func (d *purchaseOrderItem) buildListFilter(ctx context.Context, req *dto.ListPurchaseOrderItemsReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
|
||||
if req.OrderId != nil {
|
||||
filter["orderId"] = req.OrderId
|
||||
}
|
||||
if req.AssetId != nil {
|
||||
filter["assetId"] = req.AssetId
|
||||
}
|
||||
if req.AssetSkuId != nil {
|
||||
filter["assetSkuId"] = req.AssetSkuId
|
||||
}
|
||||
if !g.IsEmpty(req.ProductName) {
|
||||
filter["productName"] = bson.M{"$regex": req.ProductName, "$options": "i"}
|
||||
}
|
||||
if !g.IsEmpty(req.Brand) {
|
||||
filter["brand"] = bson.M{"$regex": req.Brand, "$options": "i"}
|
||||
}
|
||||
return
|
||||
}
|
||||
110
dao/procurement/supplier_dao.go
Normal file
110
dao/procurement/supplier_dao.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/procurement"
|
||||
entity "assets/model/entity/procurement"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var Supplier = new(supplier)
|
||||
|
||||
type supplier struct{}
|
||||
|
||||
// Insert 插入供应商
|
||||
func (d *supplier) Insert(ctx context.Context, req *dto.CreateSupplierReq) (ids []any, err error) {
|
||||
var result *entity.Supplier
|
||||
if err = gconv.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.SupplierCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchInsert 批量插入供应商
|
||||
func (d *supplier) BatchInsert(ctx context.Context, req *dto.BatchCreateSuppliersReq) (ids []any, err error) {
|
||||
items := make([]*entity.Supplier, 0, len(req.Suppliers))
|
||||
for _, item := range req.Suppliers {
|
||||
var result *entity.Supplier
|
||||
if err = gconv.Struct(item, &result); err != nil {
|
||||
return
|
||||
}
|
||||
items = append(items, result)
|
||||
}
|
||||
// 转换为 interface{} 切片
|
||||
interfaces := make([]interface{}, len(items))
|
||||
for i, item := range items {
|
||||
interfaces[i] = item
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, interfaces, public.SupplierCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 获取单个供应商
|
||||
func (d *supplier) GetOne(ctx context.Context, id *bson.ObjectID) (supplier *entity.Supplier, err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &supplier, public.SupplierCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新供应商
|
||||
func (d *supplier) Update(ctx context.Context, req *dto.UpdateSupplierReq) (err error) {
|
||||
buildUpdateData, err := mongo.BuildUpdateData(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
filter := bson.M{"_id": req.ID}
|
||||
update := bson.M{"$set": buildUpdateData}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.SupplierCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 删除供应商-根据id进行假删
|
||||
func (d *supplier) DeleteFake(ctx context.Context, id *bson.ObjectID) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.SupplierCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取供应商列表
|
||||
func (d *supplier) List(ctx context.Context, req *dto.ListSuppliersReq) (res []*entity.Supplier, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.SupplierCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// FindActiveSuppliers 获取活跃供应商列表
|
||||
func (d *supplier) FindActiveSuppliers(ctx context.Context) (res []*entity.Supplier, err error) {
|
||||
filter := bson.M{
|
||||
"status": 1, // consts.SupplierStatusActive
|
||||
"isDeleted": false,
|
||||
}
|
||||
_, err = mongo.DB().Find(ctx, filter, &res, public.SupplierCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// buildListFilter 构建列表查询的过滤条件
|
||||
func (d *supplier) buildListFilter(ctx context.Context, req *dto.ListSuppliersReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
|
||||
if !g.IsEmpty(req.Name) {
|
||||
filter["name"] = bson.M{"$regex": req.Name, "$options": "i"}
|
||||
}
|
||||
if !g.IsEmpty(req.Code) {
|
||||
filter["code"] = req.Code
|
||||
}
|
||||
if req.Status != nil {
|
||||
filter["status"] = *req.Status
|
||||
}
|
||||
return
|
||||
}
|
||||
73
dao/stock/inventory_count_adjust_history_dao.go
Normal file
73
dao/stock/inventory_count_adjust_history_dao.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var InventoryCountAdjustHistory = &inventoryCountAdjustHistory{}
|
||||
|
||||
type inventoryCountAdjustHistory struct{}
|
||||
|
||||
// Insert 插入盘点调整历史记录
|
||||
func (d *inventoryCountAdjustHistory) Insert(ctx context.Context, req *dto.CreateInventoryCountAdjustHistoryReq) (ids []interface{}, err error) {
|
||||
var result *entity.InventoryCountAdjustHistory
|
||||
if err = utils.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.InventoryCountAdjustHistoryCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 根据ID查询单条盘点调整历史记录
|
||||
func (d *inventoryCountAdjustHistory) GetOne(ctx context.Context, req *dto.GetInventoryCountAdjustHistoryReq) (res *entity.InventoryCountAdjustHistory, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.InventoryCountAdjustHistoryCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 软删除盘点调整历史记录
|
||||
func (d *inventoryCountAdjustHistory) DeleteFake(ctx context.Context, req *dto.DeleteInventoryCountAdjustHistoryReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.InventoryCountAdjustHistoryCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// List 分页查询盘点调整历史列表
|
||||
func (d *inventoryCountAdjustHistory) List(ctx context.Context, req *dto.ListInventoryCountAdjustHistoryReq) (res []entity.InventoryCountAdjustHistory, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.InventoryCountAdjustHistoryCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
|
||||
// buildListFilter 构建列表查询过滤条件
|
||||
func (d *inventoryCountAdjustHistory) buildListFilter(ctx context.Context, req *dto.ListInventoryCountAdjustHistoryReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
if !g.IsEmpty(req.CountID) {
|
||||
filter["countId"] = req.CountID
|
||||
}
|
||||
if !g.IsEmpty(req.DetailID) {
|
||||
filter["detailId"] = req.DetailID
|
||||
}
|
||||
if !g.IsEmpty(req.AssetSkuID) {
|
||||
filter["assetSkuId"] = req.AssetSkuID
|
||||
}
|
||||
if !g.IsEmpty(req.WarehouseID) {
|
||||
filter["warehouseId"] = req.WarehouseID
|
||||
}
|
||||
if !g.IsEmpty(req.BatchNo) {
|
||||
filter["batchNo"] = req.BatchNo
|
||||
}
|
||||
return
|
||||
}
|
||||
202
dao/stock/inventory_count_dao.go
Normal file
202
dao/stock/inventory_count_dao.go
Normal file
@@ -0,0 +1,202 @@
|
||||
// 盘点任务DAO层
|
||||
// 职责:盘点任务CRUD、检查未完成任务、更新状态/统计
|
||||
// 紧密耦合:service.InventoryCount、dao.InventoryCountDetail(级联删除)
|
||||
// 注意:HasUncompletedTask使用NoCache()跳过缓存,同一时间只允许一个盘点任务
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
"assets/consts/stock"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var InventoryCount = new(inventoryCount)
|
||||
|
||||
type inventoryCount struct{}
|
||||
|
||||
// convertToObjectIDs 将字符串ID列表批量转换为ObjectID列表,跳过空值
|
||||
func convertToObjectIDs(hexIDs []string, label string) ([]*bson.ObjectID, error) {
|
||||
if len(hexIDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
result := make([]*bson.ObjectID, 0, len(hexIDs))
|
||||
for _, hex := range hexIDs {
|
||||
if g.IsEmpty(hex) {
|
||||
continue
|
||||
}
|
||||
id, err := bson.ObjectIDFromHex(hex)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%sID格式错误(值:%s): %v", label, hex, err)
|
||||
}
|
||||
result = append(result, &id)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (d *inventoryCount) Insert(ctx context.Context, req *dto.CreateInventoryCountReq, countNo string) (ids []interface{}, err error) {
|
||||
result := &entity.InventoryCount{
|
||||
CountNo: countNo,
|
||||
Title: req.Title,
|
||||
Description: req.Description,
|
||||
CountType: req.CountType,
|
||||
Scope: req.Scope,
|
||||
AssigneeID: req.AssigneeID,
|
||||
AssigneeName: req.AssigneeName,
|
||||
Participants: req.Participants,
|
||||
Remark: req.Remark,
|
||||
Status: stock.InventoryCountStatusInProgress,
|
||||
}
|
||||
// 批量转换字符串ID为ObjectID
|
||||
if result.WarehouseIDs, err = convertToObjectIDs(req.WarehouseIDs, "仓库"); err != nil {
|
||||
return
|
||||
}
|
||||
if result.ZoneIDs, err = convertToObjectIDs(req.ZoneIDs, "库区"); err != nil {
|
||||
return
|
||||
}
|
||||
if result.LocationIDs, err = convertToObjectIDs(req.LocationIDs, "库位"); err != nil {
|
||||
return
|
||||
}
|
||||
if result.AssetSkuIDs, err = convertToObjectIDs(req.AssetSkuIDs, "资产SKU"); err != nil {
|
||||
return
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{result}, public.InventoryCountCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryCount) GetOne(ctx context.Context, req *dto.GetInventoryCountReq) (res *entity.InventoryCount, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.InventoryCountCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryCount) Update(ctx context.Context, req *dto.UpdateInventoryCountReq) (err error) {
|
||||
var updateData entity.InventoryCount
|
||||
if err = utils.Struct(req, &updateData); err != nil {
|
||||
return
|
||||
}
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{"$set": updateData}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.InventoryCountCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryCount) Delete(ctx context.Context, req *dto.DeleteInventoryCountReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
_, err = mongo.DB().Delete(ctx, filter, public.InventoryCountCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryCount) List(ctx context.Context, req *dto.ListInventoryCountReq) (res []entity.InventoryCount, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.InventoryCountCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryCount) buildListFilter(ctx context.Context, req *dto.ListInventoryCountReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
// 兼容单值和数组参数(优先使用数组)
|
||||
if len(req.WarehouseIDs) > 0 {
|
||||
// 将字符串数组转为 ObjectID 数组
|
||||
var oids []bson.ObjectID
|
||||
for _, id := range req.WarehouseIDs {
|
||||
if oid, e := bson.ObjectIDFromHex(id); e == nil {
|
||||
oids = append(oids, oid)
|
||||
}
|
||||
}
|
||||
if len(oids) > 0 {
|
||||
filter["warehouseIds"] = bson.M{"$in": oids}
|
||||
}
|
||||
} else if !g.IsEmpty(req.WarehouseID) {
|
||||
if wid, e := bson.ObjectIDFromHex(req.WarehouseID); e == nil {
|
||||
filter["warehouseIds"] = wid
|
||||
}
|
||||
}
|
||||
if len(req.ZoneIDs) > 0 {
|
||||
// 将字符串数组转为 ObjectID 数组
|
||||
var oids []bson.ObjectID
|
||||
for _, id := range req.ZoneIDs {
|
||||
if oid, e := bson.ObjectIDFromHex(id); e == nil {
|
||||
oids = append(oids, oid)
|
||||
}
|
||||
}
|
||||
if len(oids) > 0 {
|
||||
filter["zoneIds"] = bson.M{"$in": oids}
|
||||
}
|
||||
} else if !g.IsEmpty(req.ZoneID) {
|
||||
if zid, e := bson.ObjectIDFromHex(req.ZoneID); e == nil {
|
||||
filter["zoneIds"] = zid
|
||||
}
|
||||
}
|
||||
if !g.IsEmpty(req.CountType) {
|
||||
filter["countType"] = req.CountType
|
||||
}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
filter["status"] = req.Status
|
||||
}
|
||||
if !g.IsEmpty(req.AssigneeID) {
|
||||
filter["assigneeId"] = req.AssigneeID
|
||||
}
|
||||
if !g.IsEmpty(req.Keyword) {
|
||||
filter["$or"] = bson.A{
|
||||
bson.M{"countNo": bson.M{"$regex": req.Keyword, "$options": "i"}},
|
||||
bson.M{"title": bson.M{"$regex": req.Keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// HasUncompletedTask 检查是否存在未完成的盘点任务
|
||||
func (d *inventoryCount) HasUncompletedTask(ctx context.Context) (has bool, err error) {
|
||||
filter := bson.M{
|
||||
"status": stock.InventoryCountStatusInProgress,
|
||||
}
|
||||
var result entity.InventoryCount
|
||||
err = mongo.DB().NoCache().FindOne(ctx, filter, &result, public.InventoryCountCollection)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return result.Id != nil, nil
|
||||
}
|
||||
|
||||
// UpdateStatus 更新盘点状态
|
||||
func (d *inventoryCount) UpdateStatus(ctx context.Context, id *bson.ObjectID, status stock.InventoryCountStatus) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"status": status,
|
||||
},
|
||||
}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.InventoryCountCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStats 更新盘点统计信息
|
||||
func (d *inventoryCount) UpdateStats(ctx context.Context, id *bson.ObjectID, totalItems, completedItems, discrepancyItems int) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
var progress float64
|
||||
if totalItems > 0 {
|
||||
progress = float64(completedItems) / float64(totalItems) * 100
|
||||
}
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"totalItems": totalItems,
|
||||
"completedItems": completedItems,
|
||||
"discrepancyItems": discrepancyItems,
|
||||
"progress": progress,
|
||||
},
|
||||
}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.InventoryCountCollection)
|
||||
return
|
||||
}
|
||||
185
dao/stock/inventory_count_detail_dao.go
Normal file
185
dao/stock/inventory_count_detail_dao.go
Normal file
@@ -0,0 +1,185 @@
|
||||
// 盘点明细DAO层
|
||||
// 职责:明细CRUD、批量插入(性能优化)、按盘点ID查询、更新调整状态
|
||||
// 紧密耦合:service.InventoryCountDetail、service.InventoryCount(统计更新)
|
||||
// 注意:InsertBatch批量插入减少网络往返,ListByCountId使用mongo.DB(false)跳过缓存
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var InventoryCountDetail = new(inventoryCountDetail)
|
||||
|
||||
type inventoryCountDetail struct{}
|
||||
|
||||
func (d *inventoryCountDetail) Insert(ctx context.Context, req *dto.CreateInventoryCountDetailReq) (ids []interface{}, err error) {
|
||||
result := &entity.InventoryCountDetail{
|
||||
BookQuantity: req.BookQuantity,
|
||||
BookBatchInfo: req.BookBatchInfo,
|
||||
ActualQuantity: req.ActualQuantity,
|
||||
ActualBatchInfo: req.ActualBatchInfo,
|
||||
Remark: req.Remark,
|
||||
}
|
||||
// required string → *bson.ObjectID
|
||||
for _, item := range []struct {
|
||||
val string
|
||||
dest **bson.ObjectID
|
||||
name string
|
||||
}{
|
||||
{req.CountID, &result.CountID, "盘点单ID"},
|
||||
{req.AssetID, &result.AssetID, "资产ID"},
|
||||
{req.AssetSkuID, &result.AssetSkuID, "资产SKU ID"},
|
||||
{req.WarehouseID, &result.WarehouseID, "仓库ID"},
|
||||
} {
|
||||
id, e := bson.ObjectIDFromHex(item.val)
|
||||
if e != nil {
|
||||
return nil, fmt.Errorf("%s格式错误: %v", item.name, e)
|
||||
}
|
||||
*item.dest = &id
|
||||
}
|
||||
// optional string → *bson.ObjectID
|
||||
if !g.IsEmpty(req.ZoneID) {
|
||||
id, e := bson.ObjectIDFromHex(req.ZoneID)
|
||||
if e != nil {
|
||||
return nil, fmt.Errorf("库区ID格式错误: %v", e)
|
||||
}
|
||||
result.ZoneID = &id
|
||||
}
|
||||
if !g.IsEmpty(req.LocationID) {
|
||||
id, e := bson.ObjectIDFromHex(req.LocationID)
|
||||
if e != nil {
|
||||
return nil, fmt.Errorf("库位ID格式错误: %v", e)
|
||||
}
|
||||
result.LocationID = &id
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{result}, public.InventoryCountDetailCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// InsertBatch 批量插入盘点明细(性能优化:100条/批,减少网络往返)
|
||||
func (d *inventoryCountDetail) InsertBatch(ctx context.Context, details []*entity.InventoryCountDetail) (ids []interface{}, err error) {
|
||||
if len(details) == 0 {
|
||||
return
|
||||
}
|
||||
docs := make([]interface{}, len(details))
|
||||
for i, detail := range details {
|
||||
docs[i] = detail
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, docs, public.InventoryCountDetailCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryCountDetail) GetOne(ctx context.Context, req *dto.GetInventoryCountDetailReq) (res *entity.InventoryCountDetail, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.InventoryCountDetailCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryCountDetail) Update(ctx context.Context, req *dto.UpdateInventoryCountDetailReq) (err error) {
|
||||
buildFilter, err := mongo.BuildUpdateData(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{"$set": buildFilter}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.InventoryCountDetailCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryCountDetail) DeleteFake(ctx context.Context, req *dto.DeleteInventoryCountDetailReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.InventoryCountDetailCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteByCountId 按盘点任务ID真删除所有明细
|
||||
func (d *inventoryCountDetail) DeleteByCountId(ctx context.Context, countId *bson.ObjectID) (err error) {
|
||||
filter := bson.M{"countId": countId}
|
||||
_, err = mongo.DB().Delete(ctx, filter, public.InventoryCountDetailCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryCountDetail) List(ctx context.Context, req *dto.ListInventoryCountDetailReq) (res []entity.InventoryCountDetail, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.InventoryCountDetailCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryCountDetail) buildListFilter(ctx context.Context, req *dto.ListInventoryCountDetailReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
if !g.IsEmpty(req.CountID) {
|
||||
filter["countId"] = req.CountID
|
||||
}
|
||||
if !g.IsEmpty(req.AssetID) {
|
||||
filter["assetId"] = req.AssetID
|
||||
}
|
||||
if !g.IsEmpty(req.AssetSkuID) {
|
||||
filter["assetSkuId"] = req.AssetSkuID
|
||||
}
|
||||
if !g.IsEmpty(req.WarehouseID) {
|
||||
filter["warehouseId"] = req.WarehouseID
|
||||
}
|
||||
if !g.IsEmpty(req.ZoneID) {
|
||||
filter["zoneId"] = req.ZoneID
|
||||
}
|
||||
if !g.IsEmpty(req.LocationID) {
|
||||
filter["locationId"] = req.LocationID
|
||||
}
|
||||
if !g.IsEmpty(req.DiscrepancyType) {
|
||||
filter["discrepancyType"] = req.DiscrepancyType
|
||||
}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
filter["status"] = req.Status
|
||||
}
|
||||
if !g.IsEmpty(req.IsAdjusted) {
|
||||
filter["isAdjusted"] = req.IsAdjusted
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ListByCountId 按盘点ID查询所有明细
|
||||
func (d *inventoryCountDetail) ListByCountId(ctx context.Context, countId *bson.ObjectID) (res []entity.InventoryCountDetail, err error) {
|
||||
filter := bson.M{"countId": countId}
|
||||
_, err = mongo.DB(false).Find(ctx, filter, &res, public.InventoryCountDetailCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateAdjusted 更新调整状态
|
||||
func (d *inventoryCountDetail) UpdateAdjusted(ctx context.Context, id *bson.ObjectID, adjustedBy string) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"isAdjusted": true,
|
||||
"adjustedBy": adjustedBy,
|
||||
"adjustedAt": gtime.Now(),
|
||||
},
|
||||
}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.InventoryCountDetailCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateDiscrepancyReason 更新差异原因
|
||||
func (d *inventoryCountDetail) UpdateDiscrepancyReason(ctx context.Context, id *bson.ObjectID, reason string) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"discrepancyReason": reason,
|
||||
"updatedAt": gtime.Now(),
|
||||
},
|
||||
}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.InventoryCountDetailCollection)
|
||||
return
|
||||
}
|
||||
71
dao/stock/inventory_warning_dao.go
Normal file
71
dao/stock/inventory_warning_dao.go
Normal file
@@ -0,0 +1,71 @@
|
||||
// 库存预警DAO层
|
||||
// 职责:预警查询(无Insert/Update/Delete,由系统自动生成)
|
||||
// 紧密耦合:service.InventoryWarning
|
||||
// 注意:预警记录由定时任务或库存变动触发,非用户手动创建
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var InventoryWarning = new(inventoryWarning)
|
||||
|
||||
type inventoryWarning struct{}
|
||||
|
||||
func (d *inventoryWarning) GetOne(ctx context.Context, req *dto.GetInventoryWarningReq) (res *entity.InventoryWarning, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.InventoryWarningCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryWarning) List(ctx context.Context, req *dto.ListInventoryWarningReq) (res []entity.InventoryWarning, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.InventoryWarningCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryWarning) buildListFilter(ctx context.Context, req *dto.ListInventoryWarningReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
if !g.IsEmpty(req.WarningType) {
|
||||
filter["warningType"] = req.WarningType
|
||||
}
|
||||
// 兼容单值和数组参数(优先使用数组)
|
||||
if len(req.BatchIDs) > 0 {
|
||||
filter["batchId"] = bson.M{"$in": req.BatchIDs}
|
||||
} else if !g.IsEmpty(req.BatchID) {
|
||||
filter["batchId"] = req.BatchID
|
||||
}
|
||||
if len(req.AssetIDs) > 0 {
|
||||
filter["assetId"] = bson.M{"$in": req.AssetIDs}
|
||||
} else if !g.IsEmpty(req.AssetID) {
|
||||
filter["assetId"] = req.AssetID
|
||||
}
|
||||
if len(req.AssetSkuIDs) > 0 {
|
||||
filter["assetSkuId"] = bson.M{"$in": req.AssetSkuIDs}
|
||||
} else if !g.IsEmpty(req.AssetSkuID) {
|
||||
filter["assetSkuId"] = req.AssetSkuID
|
||||
}
|
||||
if len(req.SupplierIDs) > 0 {
|
||||
filter["supplierId"] = bson.M{"$in": req.SupplierIDs}
|
||||
} else if !g.IsEmpty(req.SupplierID) {
|
||||
filter["supplierId"] = req.SupplierID
|
||||
}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
filter["status"] = req.Status
|
||||
}
|
||||
if !g.IsEmpty(req.Keyword) {
|
||||
filter["batchNo"] = bson.M{"$regex": req.Keyword, "$options": "i"}
|
||||
}
|
||||
return
|
||||
}
|
||||
80
dao/stock/inventory_warning_history_dao.go
Normal file
80
dao/stock/inventory_warning_history_dao.go
Normal file
@@ -0,0 +1,80 @@
|
||||
// 库存预警历史DAO层
|
||||
// 职责:预警历史查询、删除(无Insert/Update,由预警状态变更时自动归档)
|
||||
// 紧密耦合:service.InventoryWarningHistory
|
||||
// 注意:历史记录由系统自动归档,非用户手动创建
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var InventoryWarningHistory = new(inventoryWarningHistory)
|
||||
|
||||
type inventoryWarningHistory struct{}
|
||||
|
||||
func (d *inventoryWarningHistory) GetOne(ctx context.Context, req *dto.GetInventoryWarningHistoryReq) (res *entity.InventoryWarningHistory, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.InventoryWarningHistoryCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryWarningHistory) List(ctx context.Context, req *dto.ListInventoryWarningHistoryReq) (res []entity.InventoryWarningHistory, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.InventoryWarningHistoryCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryWarningHistory) DeleteFake(ctx context.Context, req *dto.DeleteInventoryWarningHistoryReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.InventoryWarningHistoryCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *inventoryWarningHistory) buildListFilter(ctx context.Context, req *dto.ListInventoryWarningHistoryReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
if !g.IsEmpty(req.WarningType) {
|
||||
filter["warningType"] = req.WarningType
|
||||
}
|
||||
// 兼容单值和数组参数(优先使用数组)
|
||||
if len(req.BatchIDs) > 0 {
|
||||
filter["batchId"] = bson.M{"$in": req.BatchIDs}
|
||||
} else if !g.IsEmpty(req.BatchID) {
|
||||
filter["batchId"] = req.BatchID
|
||||
}
|
||||
if len(req.AssetIDs) > 0 {
|
||||
filter["assetId"] = bson.M{"$in": req.AssetIDs}
|
||||
} else if !g.IsEmpty(req.AssetID) {
|
||||
filter["assetId"] = req.AssetID
|
||||
}
|
||||
if len(req.AssetSkuIDs) > 0 {
|
||||
filter["assetSkuId"] = bson.M{"$in": req.AssetSkuIDs}
|
||||
} else if !g.IsEmpty(req.AssetSkuID) {
|
||||
filter["assetSkuId"] = req.AssetSkuID
|
||||
}
|
||||
if len(req.SupplierIDs) > 0 {
|
||||
filter["supplierId"] = bson.M{"$in": req.SupplierIDs}
|
||||
} else if !g.IsEmpty(req.SupplierID) {
|
||||
filter["supplierId"] = req.SupplierID
|
||||
}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
filter["status"] = req.Status
|
||||
}
|
||||
if !g.IsEmpty(req.ProcessMethod) {
|
||||
filter["processMethod"] = req.ProcessMethod
|
||||
}
|
||||
if !g.IsEmpty(req.Keyword) {
|
||||
filter["batchNo"] = bson.M{"$regex": req.Keyword, "$options": "i"}
|
||||
}
|
||||
return
|
||||
}
|
||||
191
dao/stock/location_dao.go
Normal file
191
dao/stock/location_dao.go
Normal file
@@ -0,0 +1,191 @@
|
||||
// 库位DAO层
|
||||
// 职责:库位CRUD、状态更新、批量状态更新、删除前检查(3个库存集合)、更新容量
|
||||
// 紧密耦合:service.Location(删除检查)、service.Capacity(容量计算入口)
|
||||
// 注意:DeleteFake前需检查StockDetails/StockBatch/PrivateStock三个集合
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
"assets/consts/stock"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var Location = new(location)
|
||||
|
||||
type location struct{}
|
||||
|
||||
func (d *location) Insert(ctx context.Context, req *dto.CreateLocationReq) (ids []interface{}, err error) {
|
||||
var result *entity.Location
|
||||
if err = utils.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
// 如果未传入状态,设置默认值为空闲
|
||||
if result.Status == "" {
|
||||
result.Status = stock.LocationStatusIdle
|
||||
}
|
||||
// 初始容量默认为0
|
||||
//if result.CurrentCapacity == 0 {
|
||||
// result.CurrentCapacity = 0
|
||||
//}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *location) GetOne(ctx context.Context, req *dto.GetLocationReq) (res *entity.Location, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *location) Update(ctx context.Context, req *dto.UpdateLocationReq) (err error) {
|
||||
buildFilter, err := mongo.BuildUpdateData(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{"$set": buildFilter}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *location) DeleteFake(ctx context.Context, req *dto.DeleteLocationReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus 更新库位状态
|
||||
func (d *location) UpdateStatus(ctx context.Context, req *dto.UpdateLocationStatusReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{"$set": bson.M{"status": req.Status}}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *location) List(ctx context.Context, req *dto.ListLocationReq) (res []entity.Location, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.LocationCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *location) buildListFilter(ctx context.Context, req *dto.ListLocationReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
// 兼容单值和数组参数(优先使用数组)
|
||||
if len(req.WarehouseIds) > 0 {
|
||||
filter["warehouseId"] = bson.M{"$in": req.WarehouseIds}
|
||||
} else if !g.IsEmpty(req.WarehouseId) {
|
||||
filter["warehouseId"] = req.WarehouseId
|
||||
}
|
||||
if len(req.ZoneIds) > 0 {
|
||||
filter["zoneId"] = bson.M{"$in": req.ZoneIds}
|
||||
} else if !g.IsEmpty(req.ZoneId) {
|
||||
filter["zoneId"] = req.ZoneId
|
||||
}
|
||||
if !g.IsEmpty(req.LocationType) {
|
||||
filter["locationType"] = req.LocationType
|
||||
}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
filter["status"] = req.Status
|
||||
}
|
||||
if !g.IsEmpty(req.Keyword) {
|
||||
filter["$or"] = bson.A{
|
||||
bson.M{"locationCode": bson.M{"$regex": req.Keyword, "$options": "i"}},
|
||||
bson.M{"locationName": bson.M{"$regex": req.Keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CountByZoneId 统计库区下的库位数量(用于删除前检查)
|
||||
func (d *location) CountByZoneId(ctx context.Context, zoneId string) (count int64, err error) {
|
||||
filter := bson.M{"zoneId": zoneId}
|
||||
count, err = mongo.DB().Count(ctx, filter, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// CountByWarehouseId 统计仓库下的库位数量(用于删除前检查)
|
||||
func (d *location) CountByWarehouseId(ctx context.Context, warehouseId string) (count int64, err error) {
|
||||
filter := bson.M{"warehouseId": warehouseId}
|
||||
count, err = mongo.DB().Count(ctx, filter, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchUpdateStatusByZoneId 批量更新库区下所有库位状态(用于状态联动)
|
||||
func (d *location) BatchUpdateStatusByZoneId(ctx context.Context, zoneId string, status stock.LocationStatus) (modifiedCount int64, err error) {
|
||||
filter := bson.M{"zoneId": zoneId}
|
||||
update := bson.M{"$set": bson.M{"status": status}}
|
||||
modifiedCount, err = mongo.DB().Update(ctx, filter, update, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchUpdateStatusByWarehouseId 批量更新仓库下所有库位状态(用于状态联动)
|
||||
func (d *location) BatchUpdateStatusByWarehouseId(ctx context.Context, warehouseId string, status stock.LocationStatus) (modifiedCount int64, err error) {
|
||||
filter := bson.M{"warehouseId": warehouseId}
|
||||
update := bson.M{"$set": bson.M{"status": status}}
|
||||
modifiedCount, err = mongo.DB().Update(ctx, filter, update, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteByZoneId 批量删除库区下所有库位(用于级联删除)
|
||||
func (d *location) DeleteByZoneId(ctx context.Context, zoneId string) (modifiedCount int64, err error) {
|
||||
filter := bson.M{"zoneId": zoneId}
|
||||
modifiedCount, err = mongo.DB().DeleteSoft(ctx, filter, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteByWarehouseId 批量删除仓库下所有库位(用于级联删除)
|
||||
func (d *location) DeleteByWarehouseId(ctx context.Context, warehouseId string) (modifiedCount int64, err error) {
|
||||
filter := bson.M{"warehouseId": warehouseId}
|
||||
modifiedCount, err = mongo.DB().DeleteSoft(ctx, filter, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// CountStockDetailsByLocationId 统计库位上的库存明细数量(用于删除前检查)
|
||||
func (d *location) CountStockDetailsByLocationId(ctx context.Context, locationId string) (count int64, err error) {
|
||||
filter := bson.M{"locationId": locationId}
|
||||
count, err = mongo.DB().Count(ctx, filter, public.StockDetailsCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// CountStockBatchByLocationId 统计库位上的批次库存数量(用于删除前检查)
|
||||
func (d *location) CountStockBatchByLocationId(ctx context.Context, locationId string) (count int64, err error) {
|
||||
filter := bson.M{"locationId": locationId}
|
||||
count, err = mongo.DB().Count(ctx, filter, public.StockBatchCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// CountPrivateStockByLocationId 统计库位上的私域库存数量(用于删除前检查)
|
||||
func (d *location) CountPrivateStockByLocationId(ctx context.Context, locationId string) (count int64, err error) {
|
||||
filter := bson.M{"locationId": locationId}
|
||||
count, err = mongo.DB().Count(ctx, filter, public.PrivateStockCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateCapacity 更新库位容量
|
||||
func (d *location) UpdateCapacity(ctx context.Context, locationId *bson.ObjectID, currentCapacity int) (err error) {
|
||||
filter := bson.M{"_id": locationId}
|
||||
update := bson.M{"$set": bson.M{"capacity.currentCapacity": currentCapacity}}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// ListByZoneAndUnitType 按库区和容量单位类型查询库位列表
|
||||
func (d *location) ListByZoneAndUnitType(ctx context.Context, zoneId *bson.ObjectID, unitType stock.CapacityUnitType) (res []entity.Location, err error) {
|
||||
filter := bson.M{
|
||||
"zoneId": zoneId,
|
||||
"capacityUnitType": unitType,
|
||||
}
|
||||
_, err = mongo.DB().Find(ctx, filter, &res, public.LocationCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
268
dao/stock/private_stock_dao.go
Normal file
268
dao/stock/private_stock_dao.go
Normal file
@@ -0,0 +1,268 @@
|
||||
// 实物库存批次DAO层
|
||||
// 职责:CRUD、IncrementAvailableQty原子操作(防并发超卖)、SumAvailableQtyByLocation聚合汇总
|
||||
// 紧密耦合:service.PrivateStock、service.Capacity(容量计算入口)
|
||||
// 注意:IncrementAvailableQty使用$inc+$gte条件,防止并发导致库存变负
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
"assets/consts/stock"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var PrivateStock = new(privateStock)
|
||||
|
||||
type privateStock struct {
|
||||
}
|
||||
|
||||
// Insert 插入私域库存
|
||||
func (d *privateStock) Insert(ctx context.Context, req *dto.CreatePrivateStockReq) (ids []interface{}, err error) {
|
||||
var result *entity.PrivateStock
|
||||
if err = utils.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 设置StockType(如果未指定,默认为PrivateStock类型)
|
||||
if !g.IsEmpty(req.StockType) {
|
||||
result.StockType = req.StockType
|
||||
} else {
|
||||
result.StockType = stock.StockLocationTypePrivateStock
|
||||
}
|
||||
|
||||
// 获取仓库信息(非必填)
|
||||
if req.WarehouseId != nil && !req.WarehouseId.IsZero() {
|
||||
warehouse, err := Warehouse.GetOne(ctx, &dto.GetWarehouseReq{Id: req.WarehouseId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.WarehouseID = req.WarehouseId
|
||||
result.WarehouseCode = warehouse.WarehouseCode
|
||||
result.WarehouseName = warehouse.WarehouseName
|
||||
}
|
||||
|
||||
// 如果有库区信息
|
||||
if req.ZoneId != nil && !req.ZoneId.IsZero() {
|
||||
zone, err := Zone.GetOne(ctx, &dto.GetZoneReq{Id: req.ZoneId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.ZoneID = req.ZoneId
|
||||
result.ZoneCode = zone.ZoneCode
|
||||
result.ZoneName = zone.ZoneName
|
||||
result.ZoneType = zone.ZoneType
|
||||
}
|
||||
|
||||
// 如果有库位信息
|
||||
if req.LocationId != nil && !req.LocationId.IsZero() {
|
||||
location, err := Location.GetOne(ctx, &dto.GetLocationReq{Id: req.LocationId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.LocationID = req.LocationId
|
||||
result.LocationCode = location.LocationCode
|
||||
result.LocationName = location.LocationName
|
||||
result.LocationType = location.LocationType
|
||||
}
|
||||
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.PrivateStockCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新私域库存
|
||||
func (d *privateStock) Update(ctx context.Context, req *dto.UpdatePrivateStockReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{"$set": bson.M{}}
|
||||
|
||||
if req.WarehouseId != nil && !req.WarehouseId.IsZero() {
|
||||
warehouse, err := Warehouse.GetOne(ctx, &dto.GetWarehouseReq{Id: req.WarehouseId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
update["$set"].(bson.M)["warehouseId"] = req.WarehouseId
|
||||
update["$set"].(bson.M)["warehouseCode"] = warehouse.WarehouseCode
|
||||
update["$set"].(bson.M)["warehouseName"] = warehouse.WarehouseName
|
||||
}
|
||||
|
||||
if req.ZoneId != nil && !req.ZoneId.IsZero() {
|
||||
zone, err := Zone.GetOne(ctx, &dto.GetZoneReq{Id: req.ZoneId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
update["$set"].(bson.M)["zoneId"] = req.ZoneId
|
||||
update["$set"].(bson.M)["zoneCode"] = zone.ZoneCode
|
||||
update["$set"].(bson.M)["zoneName"] = zone.ZoneName
|
||||
update["$set"].(bson.M)["zoneType"] = zone.ZoneType
|
||||
}
|
||||
|
||||
if req.LocationId != nil && !req.LocationId.IsZero() {
|
||||
location, err := Location.GetOne(ctx, &dto.GetLocationReq{Id: req.LocationId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
update["$set"].(bson.M)["locationId"] = req.LocationId
|
||||
update["$set"].(bson.M)["locationCode"] = location.LocationCode
|
||||
update["$set"].(bson.M)["locationName"] = location.LocationName
|
||||
update["$set"].(bson.M)["locationType"] = location.LocationType
|
||||
}
|
||||
|
||||
if req.PrivateSkuID != nil {
|
||||
update["$set"].(bson.M)["privateSkuId"] = req.PrivateSkuID
|
||||
}
|
||||
if !g.IsEmpty(req.BatchNo) {
|
||||
update["$set"].(bson.M)["batchNo"] = req.BatchNo
|
||||
}
|
||||
if req.BatchQty > 0 {
|
||||
update["$set"].(bson.M)["batchQty"] = req.BatchQty
|
||||
}
|
||||
// AvailableQty已移除全量覆盖,请使用IncrementAvailableQty方法进行增量更新
|
||||
if req.BatchStatus != nil {
|
||||
update["$set"].(bson.M)["batchStatus"] = req.BatchStatus
|
||||
}
|
||||
if req.StockStatus != nil {
|
||||
update["$set"].(bson.M)["stockStatus"] = req.StockStatus
|
||||
}
|
||||
if req.SupplierID != nil {
|
||||
update["$set"].(bson.M)["supplierId"] = req.SupplierID
|
||||
}
|
||||
if req.SupportsRecycle != nil {
|
||||
update["$set"].(bson.M)["supportsRecycle"] = *req.SupportsRecycle
|
||||
}
|
||||
if req.ProductionDate != nil {
|
||||
update["$set"].(bson.M)["productionDate"] = req.ProductionDate
|
||||
}
|
||||
if req.ExpiryDate != nil {
|
||||
update["$set"].(bson.M)["expiryDate"] = req.ExpiryDate
|
||||
}
|
||||
if req.ExpiryWarningDate != nil {
|
||||
update["$set"].(bson.M)["expiryWarningDate"] = req.ExpiryWarningDate
|
||||
}
|
||||
if !g.IsEmpty(req.PrivateCategoryPath) {
|
||||
update["$set"].(bson.M)["privateCategoryPath"] = req.PrivateCategoryPath
|
||||
}
|
||||
if !g.IsEmpty(req.StockType) {
|
||||
update["$set"].(bson.M)["stockType"] = req.StockType
|
||||
}
|
||||
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.PrivateStockCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 软删除私域库存
|
||||
func (d *privateStock) DeleteFake(ctx context.Context, req *dto.DeletePrivateStockReq) error {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
_, err := mongo.DB().DeleteSoft(ctx, filter, public.PrivateStockCollection)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetOne 根据ID查询私域库存
|
||||
func (d *privateStock) GetOne(ctx context.Context, req *dto.GetPrivateStockReq) (res *entity.PrivateStock, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.PrivateStockCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// IncrementAvailableQty 增量更新可用数量(并发安全)
|
||||
// deltaQty:正数表示增加(入库),负数表示减少(出库)
|
||||
// 减少时自动添加 availableQty >= |deltaQty| 条件,防止并发导致库存变负
|
||||
func (d *privateStock) IncrementAvailableQty(ctx context.Context, id *bson.ObjectID, deltaQty int) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
if deltaQty < 0 {
|
||||
filter["availableQty"] = bson.M{"$gte": -deltaQty}
|
||||
}
|
||||
update := bson.M{
|
||||
"$inc": bson.M{
|
||||
"availableQty": deltaQty,
|
||||
},
|
||||
}
|
||||
modifiedCount, err := mongo.DB().Update(ctx, filter, update, public.PrivateStockCollection)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if deltaQty < 0 && modifiedCount == 0 {
|
||||
err = gerror.Newf("库存不足,无法减少%d", -deltaQty)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// List 查询私域库存列表
|
||||
func (d *privateStock) List(ctx context.Context, req *dto.ListPrivateStockReq) (res []entity.PrivateStock, total int64, err error) {
|
||||
filter := bson.M{}
|
||||
if req.WarehouseId != nil && !req.WarehouseId.IsZero() {
|
||||
filter["warehouseId"] = req.WarehouseId
|
||||
}
|
||||
if req.ZoneId != nil && !req.ZoneId.IsZero() {
|
||||
filter["zoneId"] = req.ZoneId
|
||||
}
|
||||
if req.LocationId != nil && !req.LocationId.IsZero() {
|
||||
filter["locationId"] = req.LocationId
|
||||
}
|
||||
if req.PrivateSkuID != nil && !req.PrivateSkuID.IsZero() {
|
||||
filter["privateSkuId"] = req.PrivateSkuID
|
||||
}
|
||||
if req.BatchStatus != nil {
|
||||
filter["batchStatus"] = req.BatchStatus
|
||||
}
|
||||
if req.StockStatus != nil {
|
||||
filter["stockStatus"] = req.StockStatus
|
||||
}
|
||||
if req.SupplierID != nil && !req.SupplierID.IsZero() {
|
||||
filter["supplierId"] = req.SupplierID
|
||||
}
|
||||
if !g.IsEmpty(req.PrivateCategoryPath) {
|
||||
filter["privateCategoryPath"] = req.PrivateCategoryPath
|
||||
}
|
||||
if !g.IsEmpty(req.StockType) {
|
||||
filter["stockType"] = req.StockType
|
||||
}
|
||||
|
||||
// 默认排序
|
||||
if len(req.OrderBy) == 0 {
|
||||
req.OrderBy = []beans.OrderBy{
|
||||
{Field: "createdAt", Order: beans.Desc},
|
||||
}
|
||||
}
|
||||
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.PrivateStockCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
|
||||
// SumAvailableQtyByLocation 按库位ID汇总所有库存的可用数量(使用MongoDB聚合管道)
|
||||
func (d *privateStock) SumAvailableQtyByLocation(ctx context.Context, locationId *bson.ObjectID) (totalQty int, err error) {
|
||||
pipeline := bson.A{
|
||||
bson.M{"$match": bson.M{
|
||||
"locationId": locationId,
|
||||
"isDeleted": false,
|
||||
}},
|
||||
bson.M{"$group": bson.M{
|
||||
"_id": nil,
|
||||
"totalQty": bson.M{"$sum": "$availableQty"},
|
||||
}},
|
||||
}
|
||||
|
||||
coll := mongo.GetDB().Collection(public.PrivateStockCollection)
|
||||
cursor, err := coll.Aggregate(ctx, pipeline)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
var results []struct {
|
||||
TotalQty int `bson:"totalQty"`
|
||||
}
|
||||
if err = cursor.All(ctx, &results); err != nil {
|
||||
return
|
||||
}
|
||||
if len(results) > 0 {
|
||||
totalQty = results[0].TotalQty
|
||||
}
|
||||
return
|
||||
}
|
||||
78
dao/stock/stock_batch_dao.go
Normal file
78
dao/stock/stock_batch_dao.go
Normal file
@@ -0,0 +1,78 @@
|
||||
// 批次库存DAO层(逻辑库存)
|
||||
// 职责:批次CRUD、使用$inc原子操作更新数量
|
||||
// 紧密耦合:service.StockBatch、service.StockManage(入库出库)
|
||||
// 注意:Update使用$inc原子操作,GetOne使用NoCache()跳过缓存
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var StockBatch = new(stockBatch)
|
||||
|
||||
type stockBatch struct {
|
||||
}
|
||||
|
||||
// Insert 插入
|
||||
func (d *stockBatch) Insert(ctx context.Context, req *dto.CreateBatchReq) (ids []interface{}, err error) {
|
||||
var result *entity.StockBatch
|
||||
if err = utils.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.StockBatchCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新批次数量(使用$inc原子操作,并发安全)
|
||||
func (d *stockBatch) Update(ctx context.Context, req *dto.UpdateBatchReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{
|
||||
"$inc": bson.M{
|
||||
"batchQty": req.BatchQty,
|
||||
"availableQty": req.AvailableQty,
|
||||
},
|
||||
}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.StockBatchCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 根据批次号查询(使用NoCache跳过缓存,确保获取最新数据)
|
||||
func (d *stockBatch) GetOne(ctx context.Context, batchNo string) (res *entity.StockBatch, err error) {
|
||||
filter := bson.M{"batchNo": batchNo}
|
||||
err = mongo.DB().NoCache().FindOne(ctx, filter, &res, public.StockBatchCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetOneById 根据ID查询批次
|
||||
func (d *stockBatch) GetOneById(ctx context.Context, req *dto.GetBatchReq) (res *entity.StockBatch, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.StockBatchCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 软删除批次
|
||||
func (d *stockBatch) DeleteFake(ctx context.Context, req *dto.DeleteBatchReq) error {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
_, err := mongo.DB().DeleteSoft(ctx, filter, public.StockBatchCollection)
|
||||
return err
|
||||
}
|
||||
|
||||
// List 查询批次列表
|
||||
func (d *stockBatch) List(ctx context.Context, req *dto.ListBatchReq) (res []entity.StockBatch, total int64, err error) {
|
||||
filter := bson.M{}
|
||||
if req.AssetId != nil {
|
||||
filter["assetId"] = req.AssetId
|
||||
}
|
||||
if req.AssetSkuId != nil {
|
||||
filter["assetSkuId"] = req.AssetSkuId
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.StockBatchCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
80
dao/stock/stock_details_dao.go
Normal file
80
dao/stock/stock_details_dao.go
Normal file
@@ -0,0 +1,80 @@
|
||||
// 库存明细DAO层(逻辑库存)
|
||||
// 职责:批量插入/删除、按SKU统计数量、查询列表
|
||||
// 紧密耦合:service.StockDetails、service.StockManage(入库出库)
|
||||
// 注意:GetStockCountBySkuId使用NoCache()跳过缓存,BatchInsert用于批量入库
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
"assets/consts/stock"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var StockDetails = new(stockDetails)
|
||||
|
||||
type stockDetails struct {
|
||||
}
|
||||
|
||||
// BatchInsert 批量插入库存
|
||||
func (d *stockDetails) BatchInsert(ctx context.Context, stockInterfaces []interface{}) (ids []interface{}, err error) {
|
||||
ids, err = mongo.DB().Insert(ctx, stockInterfaces, public.StockDetailsCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteManyByIds 根据ID批量删除库存
|
||||
func (d *stockDetails) DeleteManyByIds(ctx context.Context, allStockIds []*bson.ObjectID) (count int64, err error) {
|
||||
if len(allStockIds) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
filter := bson.M{"_id": bson.M{"$in": allStockIds}}
|
||||
count, err = mongo.DB().Delete(ctx, filter, public.StockDetailsCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetStockCountBySkuId 获取库存数根据SKU ID
|
||||
func (d *stockDetails) GetStockCountBySkuId(ctx context.Context, assetSkuId *bson.ObjectID) (total int64, err error) {
|
||||
// 构建查询过滤条件
|
||||
filter := bson.M{}
|
||||
filter["assetSkuId"] = assetSkuId
|
||||
filter["status"] = stock.StockStatusAvailable
|
||||
// 检查总数
|
||||
total, err = mongo.DB().NoCache().Count(ctx, filter, public.StockDetailsCollection)
|
||||
|
||||
return total, err
|
||||
}
|
||||
|
||||
// GetOneById 根据ID查询库存明细
|
||||
func (d *stockDetails) GetOneById(ctx context.Context, req *dto.GetStockDetailsReq) (res *entity.StockDetails, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.StockDetailsCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取SKU列表
|
||||
func (d *stockDetails) List(ctx context.Context, req *dto.ListStockDetailsReq) (res []entity.StockDetails, total int64, err error) {
|
||||
// 构建查询过滤条件
|
||||
filter := bson.M{}
|
||||
if !g.IsEmpty(req.AssetId) {
|
||||
filter["assetId"] = req.AssetId
|
||||
}
|
||||
if !g.IsEmpty(req.AssetSkuId) {
|
||||
filter["assetSkuId"] = req.AssetSkuId
|
||||
}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
filter["status"] = req.Status
|
||||
}
|
||||
// 排序处理
|
||||
req.OrderBy = []beans.OrderBy{
|
||||
{Field: "sort", Order: beans.Asc},
|
||||
{Field: "createdAt", Order: beans.Desc},
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.StockDetailsCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
69
dao/stock/unit_conversion_dao.go
Normal file
69
dao/stock/unit_conversion_dao.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// 单位换算DAO层
|
||||
// 职责:换算规则CRUD、按单位类型和源目标单位查询
|
||||
// 紧密耦合:service.UnitConversion、service.Capacity(容量计算换算)
|
||||
// 注意:GetByUnits用于容量计算时获取换算系数
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
"assets/consts/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var UnitConversion = new(unitConversion)
|
||||
|
||||
type unitConversion struct{}
|
||||
|
||||
// GetByUnits 根据单位类型和源目标单位查询换算规则
|
||||
func (d *unitConversion) GetByUnits(ctx context.Context, unitType stock.CapacityUnitType, fromUnit, toUnit string) (res *entity.UnitConversion, err error) {
|
||||
filter := bson.M{
|
||||
"unitType": unitType,
|
||||
"fromUnit": fromUnit,
|
||||
"toUnit": toUnit,
|
||||
}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.UnitConversionCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// Insert 插入换算规则
|
||||
func (d *unitConversion) Insert(ctx context.Context, conversion *entity.UnitConversion) (ids []interface{}, err error) {
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{conversion}, public.UnitConversionCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新换算规则
|
||||
func (d *unitConversion) Update(ctx context.Context, id *bson.ObjectID, update bson.M) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
updateDoc := bson.M{"$set": update}
|
||||
_, err = mongo.DB().Update(ctx, filter, updateDoc, public.UnitConversionCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 软删除换算规则
|
||||
func (d *unitConversion) DeleteFake(ctx context.Context, id *bson.ObjectID) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.UnitConversionCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// List 查询换算规则列表
|
||||
func (d *unitConversion) List(ctx context.Context, unitType *stock.CapacityUnitType, fromUnit, toUnit string) (res []entity.UnitConversion, err error) {
|
||||
filter := bson.M{}
|
||||
|
||||
if unitType != nil {
|
||||
filter["unitType"] = *unitType
|
||||
}
|
||||
if fromUnit != "" {
|
||||
filter["fromUnit"] = fromUnit
|
||||
}
|
||||
if toUnit != "" {
|
||||
filter["toUnit"] = toUnit
|
||||
}
|
||||
|
||||
_, err = mongo.DB().Find(ctx, filter, &res, public.UnitConversionCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
141
dao/stock/warehouse_dao.go
Normal file
141
dao/stock/warehouse_dao.go
Normal file
@@ -0,0 +1,141 @@
|
||||
// 仓库DAO层
|
||||
// 职责:仓库CRUD、状态更新、批量更新库区/库位状态(状态联动)、更新容量
|
||||
// 紧密耦合:service.Warehouse(状态联动)、service.Capacity(容量汇总)
|
||||
// 注意:UpdateCapacityByUnitType使用嵌套路径更新map字段
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
"assets/consts/stock"
|
||||
"assets/model/config"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var Warehouse = new(warehouse)
|
||||
|
||||
type warehouse struct{}
|
||||
|
||||
func (d *warehouse) Insert(ctx context.Context, req *dto.CreateWarehouseReq) (ids []interface{}, err error) {
|
||||
var result *entity.Warehouse
|
||||
if err = utils.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
// 如果未传入状态,设置默认值为启用
|
||||
if result.Status == "" {
|
||||
result.Status = stock.WarehouseStatusEnabled
|
||||
}
|
||||
// 初始化Capacity为空map,避免后续UpdateCapacityByUnitType panic
|
||||
if result.Capacity == nil {
|
||||
emptyMap := make(map[stock.CapacityUnitType]config.Capacity)
|
||||
result.Capacity = &emptyMap
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.WarehouseCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *warehouse) GetOne(ctx context.Context, req *dto.GetWarehouseReq) (res *entity.Warehouse, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.WarehouseCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *warehouse) Update(ctx context.Context, req *dto.UpdateWarehouseReq) (err error) {
|
||||
buildFilter, err := mongo.BuildUpdateData(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{"$set": buildFilter}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.WarehouseCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *warehouse) DeleteFake(ctx context.Context, req *dto.DeleteWarehouseReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.WarehouseCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus 更新仓库状态
|
||||
func (d *warehouse) UpdateStatus(ctx context.Context, req *dto.UpdateWarehouseStatusReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{"$set": bson.M{"status": req.Status}}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.WarehouseCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *warehouse) List(ctx context.Context, req *dto.ListWarehouseReq) (res []entity.Warehouse, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.WarehouseCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *warehouse) buildListFilter(ctx context.Context, req *dto.ListWarehouseReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
filter["status"] = req.Status
|
||||
}
|
||||
if !g.IsEmpty(req.Keyword) {
|
||||
filter["$or"] = bson.A{
|
||||
bson.M{"warehouseCode": bson.M{"$regex": req.Keyword, "$options": "i"}},
|
||||
bson.M{"warehouseName": bson.M{"$regex": req.Keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CountZonesByWarehouseId 统计仓库下的库区数量(用于删除前检查)
|
||||
func (d *warehouse) CountZonesByWarehouseId(ctx context.Context, warehouseId string) (count int64, err error) {
|
||||
filter := bson.M{"warehouseId": warehouseId}
|
||||
count, err = mongo.DB().Count(ctx, filter, public.ZoneCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchUpdateZoneStatus 批量更新仓库下所有库区状态(用于状态联动)
|
||||
// fromStatus 可选:指定时只更新当前状态为 fromStatus 的记录,避免覆盖其他状态
|
||||
func (d *warehouse) BatchUpdateZoneStatus(ctx context.Context, warehouseId string, status stock.ZoneStatus, fromStatus ...stock.ZoneStatus) (modifiedCount int64, err error) {
|
||||
filter := bson.M{"warehouseId": warehouseId}
|
||||
if len(fromStatus) > 0 {
|
||||
filter["status"] = fromStatus[0]
|
||||
}
|
||||
update := bson.M{"$set": bson.M{"status": status}}
|
||||
modifiedCount, err = mongo.DB().Update(ctx, filter, update, public.ZoneCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateCapacityByUnitType 更新仓库指定容量单位类型的容量
|
||||
func (d *warehouse) UpdateCapacityByUnitType(ctx context.Context, warehouseId *bson.ObjectID, unitType stock.CapacityUnitType, currentCapacity int, maxCapacity int, capacityUnit string) (err error) {
|
||||
filter := bson.M{"_id": warehouseId}
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"capacity." + string(unitType) + ".currentCapacity": currentCapacity,
|
||||
"capacity." + string(unitType) + ".maxCapacity": maxCapacity,
|
||||
"capacity." + string(unitType) + ".capacityUnit": capacityUnit,
|
||||
},
|
||||
}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.WarehouseCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchUpdateLocationStatus 批量更新仓库下所有库位状态(用于状态联动)
|
||||
// fromStatus 可选:指定时只更新当前状态为 fromStatus 的记录,避免覆盖其他状态
|
||||
func (d *warehouse) BatchUpdateLocationStatus(ctx context.Context, warehouseId string, status stock.LocationStatus, fromStatus ...stock.LocationStatus) (modifiedCount int64, err error) {
|
||||
filter := bson.M{"warehouseId": warehouseId}
|
||||
if len(fromStatus) > 0 {
|
||||
filter["status"] = fromStatus[0]
|
||||
}
|
||||
update := bson.M{"$set": bson.M{"status": status}}
|
||||
modifiedCount, err = mongo.DB().Update(ctx, filter, update, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
162
dao/stock/zone_dao.go
Normal file
162
dao/stock/zone_dao.go
Normal file
@@ -0,0 +1,162 @@
|
||||
// 库区DAO层
|
||||
// 职责:库区CRUD、状态更新、批量更新库位状态(状态联动)、更新容量
|
||||
// 紧密耦合:service.Zone(状态联动)、service.Capacity(容量汇总)
|
||||
// 注意:UpdateCapacityByUnitType使用嵌套路径更新map字段
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
"assets/consts/stock"
|
||||
"assets/model/config"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var Zone = new(zone)
|
||||
|
||||
type zone struct{}
|
||||
|
||||
func (d *zone) Insert(ctx context.Context, req *dto.CreateZoneReq) (ids []interface{}, err error) {
|
||||
var result *entity.Zone
|
||||
if err = utils.Struct(req, &result); err != nil {
|
||||
return
|
||||
}
|
||||
// 如果未传入状态,设置默认值为启用
|
||||
if result.Status == "" {
|
||||
result.Status = stock.ZoneStatusEnabled
|
||||
}
|
||||
// 初始化Capacity为空map,避免后续UpdateCapacityByUnitType panic
|
||||
if result.Capacity == nil {
|
||||
emptyMap := make(map[stock.CapacityUnitType]config.Capacity)
|
||||
result.Capacity = &emptyMap
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.ZoneCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *zone) GetOne(ctx context.Context, req *dto.GetZoneReq) (res *entity.Zone, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.ZoneCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *zone) Update(ctx context.Context, req *dto.UpdateZoneReq) (err error) {
|
||||
buildFilter, err := mongo.BuildUpdateData(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{"$set": buildFilter}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.ZoneCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *zone) DeleteFake(ctx context.Context, req *dto.DeleteZoneReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
_, err = mongo.DB().DeleteSoft(ctx, filter, public.ZoneCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus 更新库区状态
|
||||
func (d *zone) UpdateStatus(ctx context.Context, req *dto.UpdateZoneStatusReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{"$set": bson.M{"status": req.Status}}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.ZoneCollection)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *zone) List(ctx context.Context, req *dto.ListZoneReq) (res []entity.Zone, total int64, err error) {
|
||||
filter, err := d.buildListFilter(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.ZoneCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
}
|
||||
|
||||
func (d *zone) buildListFilter(ctx context.Context, req *dto.ListZoneReq) (filter bson.M, err error) {
|
||||
_ = ctx
|
||||
filter = bson.M{}
|
||||
// 兼容单值和数组参数(优先使用数组)
|
||||
if len(req.WarehouseIds) > 0 {
|
||||
filter["warehouseId"] = bson.M{"$in": req.WarehouseIds}
|
||||
} else if !g.IsEmpty(req.WarehouseId) {
|
||||
filter["warehouseId"] = req.WarehouseId
|
||||
}
|
||||
if !g.IsEmpty(req.ZoneType) {
|
||||
filter["zoneType"] = req.ZoneType
|
||||
}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
filter["status"] = req.Status
|
||||
}
|
||||
if !g.IsEmpty(req.Keyword) {
|
||||
filter["$or"] = bson.A{
|
||||
bson.M{"zoneCode": bson.M{"$regex": req.Keyword, "$options": "i"}},
|
||||
bson.M{"zoneName": bson.M{"$regex": req.Keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CountLocationsByZoneId 统计库区下的库位数量(用于删除前检查)
|
||||
func (d *zone) CountLocationsByZoneId(ctx context.Context, zoneId string) (count int64, err error) {
|
||||
filter := bson.M{"zoneId": zoneId}
|
||||
count, err = mongo.DB().Count(ctx, filter, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// CountByWarehouseId 统计仓库下的库区数量(用于删除前检查)
|
||||
func (d *zone) CountByWarehouseId(ctx context.Context, warehouseId string) (count int64, err error) {
|
||||
filter := bson.M{"warehouseId": warehouseId}
|
||||
count, err = mongo.DB().Count(ctx, filter, public.ZoneCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchUpdateStatusByWarehouseId 批量更新仓库下所有库区状态(用于状态联动)
|
||||
func (d *zone) BatchUpdateStatusByWarehouseId(ctx context.Context, warehouseId string, status stock.ZoneStatus) (modifiedCount int64, err error) {
|
||||
filter := bson.M{"warehouseId": warehouseId}
|
||||
update := bson.M{"$set": bson.M{"status": status}}
|
||||
modifiedCount, err = mongo.DB().Update(ctx, filter, update, public.ZoneCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchUpdateLocationStatus 批量更新库区下所有库位状态(用于状态联动)
|
||||
// fromStatus 可选:指定时只更新当前状态为 fromStatus 的记录,避免覆盖其他状态
|
||||
func (d *zone) BatchUpdateLocationStatus(ctx context.Context, zoneId string, status stock.LocationStatus, fromStatus ...stock.LocationStatus) (modifiedCount int64, err error) {
|
||||
filter := bson.M{"zoneId": zoneId}
|
||||
if len(fromStatus) > 0 {
|
||||
filter["status"] = fromStatus[0]
|
||||
}
|
||||
update := bson.M{"$set": bson.M{"status": status}}
|
||||
modifiedCount, err = mongo.DB().Update(ctx, filter, update, public.LocationCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateCapacityByUnitType 更新库区指定容量单位类型的容量
|
||||
func (d *zone) UpdateCapacityByUnitType(ctx context.Context, zoneId *bson.ObjectID, unitType stock.CapacityUnitType, currentCapacity int, maxCapacity int, capacityUnit string) (err error) {
|
||||
filter := bson.M{"_id": zoneId}
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"capacity." + string(unitType) + ".currentCapacity": currentCapacity,
|
||||
"capacity." + string(unitType) + ".maxCapacity": maxCapacity,
|
||||
"capacity." + string(unitType) + ".capacityUnit": capacityUnit,
|
||||
},
|
||||
}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.ZoneCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// ListByWarehouseAndUnitType 按仓库ID查询所有库区(用于汇总仓库容量)
|
||||
func (d *zone) ListByWarehouseAndUnitType(ctx context.Context, warehouseId string) (res []entity.Zone, err error) {
|
||||
filter := bson.M{
|
||||
"warehouseId": warehouseId,
|
||||
}
|
||||
_, err = mongo.DB().Find(ctx, filter, &res, public.ZoneCollection, nil, nil)
|
||||
return
|
||||
}
|
||||
169
dao/sync/sync_dao.go
Normal file
169
dao/sync/sync_dao.go
Normal file
@@ -0,0 +1,169 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
dto "assets/model/dto/sync"
|
||||
entity "assets/model/entity/sync"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
var SyncTask = new(syncTask)
|
||||
|
||||
type syncTask struct{}
|
||||
|
||||
// Insert 插入同步任务
|
||||
func (d *syncTask) Insert(ctx context.Context, task *entity.SyncTask) (err error) {
|
||||
_, err = mongo.DB().Insert(ctx, []interface{}{task}, task.CollectionName())
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 获取单个同步任务
|
||||
func (d *syncTask) GetOne(ctx context.Context, id *bson.ObjectID) (task *entity.SyncTask, err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
|
||||
task = &entity.SyncTask{}
|
||||
err = mongo.DB().FindOne(ctx, filter, task, task.CollectionName())
|
||||
return task, err
|
||||
}
|
||||
|
||||
// List 获取同步任务列表
|
||||
func (d *syncTask) List(ctx context.Context, req *dto.ListSyncTaskReq) (list []*entity.SyncTask, total int64, err error) {
|
||||
// 构建查询过滤条件
|
||||
filter := d.buildListFilter(req)
|
||||
|
||||
// 调用 common/db/mongo 的 Find 方法,不使用排序
|
||||
total, err = mongo.DB().Find(ctx, filter, &list, "sync_task", &req.Page, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新同步任务
|
||||
func (d *syncTask) Update(ctx context.Context, id string, updateData *entity.SyncTask) (err error) {
|
||||
objectId, err := bson.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filter := bson.M{"_id": objectId}
|
||||
|
||||
if !g.IsEmpty(updateData) {
|
||||
// 直接使用 struct 转 map,不需要额外的转换
|
||||
update := bson.M{"$set": gconv.Map(updateData)}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, "sync_task")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateStatus 更新同步任务状态
|
||||
func (d *syncTask) UpdateStatus(ctx context.Context, id *bson.ObjectID, status public.SyncStatus, errorMessage string) (err error) {
|
||||
filter := bson.M{"_id": id}
|
||||
|
||||
updateData := bson.M{
|
||||
"status": status,
|
||||
"errorMessage": errorMessage,
|
||||
}
|
||||
|
||||
if status == public.SyncStatusSyncing {
|
||||
updateData["startedAt"] = gtime.Now()
|
||||
} else if status == public.SyncStatusSuccess || status == public.SyncStatusFailed {
|
||||
updateData["finishedAt"] = gtime.Now()
|
||||
}
|
||||
|
||||
update := bson.M{"$set": updateData}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, "sync_task")
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateErrorCount 更新错误计数
|
||||
func (d *syncTask) UpdateErrorCount(ctx context.Context, id string, increment int) (err error) {
|
||||
objectId, err := bson.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filter := bson.M{"_id": objectId}
|
||||
update := bson.M{"$inc": bson.M{"errorCount": increment}}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, "sync_task")
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete 删除同步任务
|
||||
func (d *syncTask) Delete(ctx context.Context, id string) (err error) {
|
||||
objectId, err := bson.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filter := bson.M{"_id": objectId}
|
||||
_, err = mongo.DB().Delete(ctx, filter, "sync_task")
|
||||
return err
|
||||
}
|
||||
|
||||
// GetPendingTasks 获取待处理的同步任务
|
||||
func (d *syncTask) GetPendingTasks(ctx context.Context, limit int) (tasks []*entity.SyncTask, err error) {
|
||||
filter := bson.M{"status": public.SyncStatusPending}
|
||||
|
||||
// 调用 common/db/mongo 的 Find 方法,不使用排序
|
||||
_, err = mongo.DB().Find(ctx, filter, &tasks, "sync_task", nil, nil)
|
||||
return tasks, err
|
||||
}
|
||||
|
||||
// buildListFilter 构建列表查询的过滤条件
|
||||
func (d *syncTask) buildListFilter(req *dto.ListSyncTaskReq) bson.M {
|
||||
filter := bson.M{}
|
||||
|
||||
if !g.IsEmpty(req.Platform) {
|
||||
filter["platform"] = req.Platform
|
||||
}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
filter["status"] = req.Status
|
||||
}
|
||||
if req.StartTime != nil {
|
||||
filter["createdAt"] = bson.M{"$gte": req.StartTime}
|
||||
}
|
||||
if req.EndTime != nil {
|
||||
if existingFilter, exists := filter["createdAt"]; exists {
|
||||
if existingTimeRange, ok := existingFilter.(bson.M); ok {
|
||||
existingTimeRange["$lte"] = req.EndTime
|
||||
filter["createdAt"] = existingTimeRange
|
||||
}
|
||||
} else {
|
||||
filter["createdAt"] = bson.M{"$lte": req.EndTime}
|
||||
}
|
||||
}
|
||||
|
||||
return filter
|
||||
}
|
||||
|
||||
// SyncConfigDao 同步配置DAO
|
||||
var SyncConfig = new(syncConfig)
|
||||
|
||||
type syncConfig struct{}
|
||||
|
||||
// GetByPlatform 根据平台获取同步配置
|
||||
func (d *syncConfig) GetByPlatform(ctx context.Context, platform public.SyncPlatform) (config *entity.ChannelConfig, err error) {
|
||||
filter := bson.M{"platform": platform}
|
||||
config = &entity.ChannelConfig{}
|
||||
err = mongo.DB().FindOne(ctx, filter, config, "sync_config")
|
||||
return config, err
|
||||
}
|
||||
|
||||
// List 获取同步配置列表
|
||||
func (d *syncConfig) List(ctx context.Context) (configs []*entity.ChannelConfig, err error) {
|
||||
_, err = mongo.DB().Find(ctx, bson.M{}, &configs, "sync_config", nil, nil)
|
||||
return configs, err
|
||||
}
|
||||
|
||||
// Update 更新同步配置
|
||||
func (d *syncConfig) Update(ctx context.Context, platform public.SyncPlatform, updateData *entity.ChannelConfig) (err error) {
|
||||
filter := bson.M{"platform": platform}
|
||||
|
||||
if !g.IsEmpty(updateData) {
|
||||
// 直接使用 struct 转 map
|
||||
update := bson.M{"$set": gconv.Map(updateData)}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, "sync_config")
|
||||
}
|
||||
return err
|
||||
}
|
||||
7
model/config/capacity.go
Normal file
7
model/config/capacity.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package config
|
||||
|
||||
type Capacity struct {
|
||||
CapacityUnit string `bson:"capacityUnit" json:"capacityUnit"` // 容量单位(具体单位值)
|
||||
MaxCapacity int `bson:"maxCapacity" json:"maxCapacity"` // 最大容量
|
||||
CurrentCapacity int `bson:"currentCapacity" json:"currentCapacity"` // 当前容量
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user