Compare commits
44 Commits
Author | SHA1 | Date | |
---|---|---|---|
58418effd3 | |||
51baf26dcc | |||
ca63f38c48 | |||
a9ab3b4d72 | |||
07544bcc1c | |||
2ff86339b1 | |||
d6472c05b4 | |||
2a4f28f9a8 | |||
d95814ad95 | |||
16e12f85cb | |||
75553fa63d | |||
606d1e513e | |||
315e22a488 | |||
502a67429e | |||
5d99ba9e64 | |||
c8cedfb72e | |||
8cda813a09 | |||
e45772ab7c | |||
2033896d43 | |||
4537477eff | |||
39589bfe0f | |||
c7216aa035 | |||
c7ab2b1957 | |||
0c3fc88c8d | |||
c64de0727b | |||
ce6708942a | |||
8efca2321e | |||
7d0a36dff1 | |||
e9ac976f48 | |||
16c6f1671c | |||
b50abd884b | |||
7e21a88722 | |||
8f1e1b15d0 | |||
499959fa41 | |||
b817b7fd40 | |||
5ed025bb22 | |||
596fd1dc44 | |||
1212d9dd1e | |||
6fb8697585 | |||
973b77d5e9 | |||
6c65d3940b | |||
b7472787c0 | |||
87c55b0cda | |||
6b747385a5 |
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
|||
.idea
|
||||
./logs/*
|
||||
./temp/*
|
||||
dev-go-admin
|
||||
main.exe
|
||||
main.exe
|
||||
|
|
|
@ -100,6 +100,7 @@ func CommodityCreate(c *gin.Context) {
|
|||
MemberDiscount: memberDiscountFloat,
|
||||
Origin: req.Origin,
|
||||
Remark: req.Remark,
|
||||
Img: req.Img,
|
||||
}
|
||||
err = commodity.SetErpCategory()
|
||||
if err != nil {
|
||||
|
@ -263,6 +264,7 @@ func CommodityEdit(c *gin.Context) {
|
|||
MemberDiscount: memberDiscountFloat,
|
||||
Origin: req.Origin,
|
||||
Remark: req.Remark,
|
||||
Img: req.Img,
|
||||
}
|
||||
commodity.ID = req.Id
|
||||
err = commodity.SetErpCategory()
|
||||
|
@ -328,7 +330,7 @@ func CommodityEdit(c *gin.Context) {
|
|||
}
|
||||
|
||||
begin := orm.Eloquent.Begin()
|
||||
err = begin.Save(commodity).Error
|
||||
err = begin.Omit("created_at").Save(commodity).Error
|
||||
if err != nil {
|
||||
logger.Error("create commodity err:", logger.Field("err", err))
|
||||
app.Error(c, http.StatusInternalServerError, err, "操作失败")
|
||||
|
|
|
@ -115,22 +115,32 @@ func SupplierUpdate(c *gin.Context) {
|
|||
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
var supplierInfo models.Supplier
|
||||
err := orm.Eloquent.Model(models.Supplier{}).Where("id", req.Id).Find(&supplierInfo).Error
|
||||
if err != nil || err == models.RecordNotFound {
|
||||
app.Error(c, http.StatusBadRequest, errors.New("para err"), "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
supplier := &models.Supplier{
|
||||
Name: req.Name,
|
||||
Contact: req.Contact,
|
||||
Tel: req.Tel,
|
||||
Address: req.Address,
|
||||
OpeningBank: req.OpeningBank,
|
||||
BankAccount: req.BankAccount,
|
||||
PaymentCycle: req.PaymentCycle,
|
||||
TaxNumber: req.TaxNumber,
|
||||
Landline: req.Landline,
|
||||
Email: req.Email,
|
||||
CompanyWebsite: req.CompanyWebsite,
|
||||
Province: req.Province,
|
||||
City: req.City,
|
||||
Area: req.Area,
|
||||
AccountHolder: req.AccountHolder,
|
||||
Number: supplierInfo.Number,
|
||||
Name: req.Name,
|
||||
Contact: req.Contact,
|
||||
Tel: req.Tel,
|
||||
Address: req.Address,
|
||||
OpeningBank: req.OpeningBank,
|
||||
BankAccount: req.BankAccount,
|
||||
PaymentCycle: req.PaymentCycle,
|
||||
TaxNumber: req.TaxNumber,
|
||||
Landline: req.Landline,
|
||||
Email: req.Email,
|
||||
CompanyWebsite: req.CompanyWebsite,
|
||||
Province: req.Province,
|
||||
City: req.City,
|
||||
Area: req.Area,
|
||||
AccountHolder: req.AccountHolder,
|
||||
CooperativeBusinessId: middleware.GetCooperativeBusinessId(c),
|
||||
}
|
||||
|
||||
if len(req.BankList) != 0 {
|
||||
|
@ -144,7 +154,7 @@ func SupplierUpdate(c *gin.Context) {
|
|||
supplier.BankData = ""
|
||||
}
|
||||
|
||||
err := orm.Eloquent.Where("id", req.Id).Updates(supplier).Error
|
||||
err = orm.Eloquent.Where("id", req.Id).Omit("created_at").Save(&supplier).Error
|
||||
if err != nil {
|
||||
logger.Error("update supplier err :", logger.Field("err", err), logger.Field("s", supplier))
|
||||
app.Error(c, http.StatusInternalServerError, err, "更新失败")
|
||||
|
|
|
@ -35,6 +35,13 @@ func ErpOrderCreate(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
tools.RoundFloatFields(req)
|
||||
|
||||
// 如果用户是会员,手机号不能为空
|
||||
if req.MemberType == model.ErpOrderMemberTypeMember && req.Tel == "" {
|
||||
app.Error(c, http.StatusBadRequest, errors.New("参数错误:缺少会员手机号"), "参数错误:缺少会员手机号")
|
||||
}
|
||||
|
||||
err = model.CreateErpOrder(req, c)
|
||||
if err != nil {
|
||||
logger.Error("CreateErpOrder err:", logger.Field("err", err))
|
||||
|
@ -68,6 +75,11 @@ func ErpOrderEdit(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
// 如果用户是会员,手机号不能为空
|
||||
if req.MemberType == model.ErpOrderMemberTypeMember && req.Tel == "" {
|
||||
app.Error(c, http.StatusBadRequest, errors.New("参数错误:缺少会员手机号"), "参数错误:缺少会员手机号")
|
||||
}
|
||||
|
||||
err = model.EditErpOrder(req, c)
|
||||
if err != nil {
|
||||
logger.Error("EditErpOrder err:", logger.Field("err", err))
|
||||
|
@ -195,6 +207,7 @@ func ErpOrderAudit(c *gin.Context) {
|
|||
}
|
||||
|
||||
var checkReq model.ErpOrderCreateReq
|
||||
checkReq.StoreId = erpOrder.StoreId
|
||||
checkReq.ErpOrderCommodities = commodity
|
||||
err = model.CheckOrderCommodityStock(&checkReq)
|
||||
if err != nil {
|
||||
|
@ -234,6 +247,7 @@ func ErpOrderAudit(c *gin.Context) {
|
|||
"audit_time": time.Now(),
|
||||
"auditor_name": sysUser.NickName,
|
||||
"auditor_id": sysUser.UserId,
|
||||
"updated_at": time.Now(),
|
||||
}).Error
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
|
|
|
@ -249,6 +249,14 @@ func ExpressNoList(c *gin.Context) {
|
|||
//app.OK(c, nil, "")
|
||||
}
|
||||
|
||||
// FundRecordList 查询财务统计列表
|
||||
// @Summary 查询财务统计列表
|
||||
// @Tags 财务管理
|
||||
// @Produce json
|
||||
// @Accept json
|
||||
// @Param request body models.FundRecordListReq true "查询财务统计列表模型"
|
||||
// @Success 200 {object} models.FundRecordListResp
|
||||
// @Router /api/v1/order/fund_record/list [post]
|
||||
func FundRecordList(c *gin.Context) {
|
||||
req := &models.FundRecordListReq{}
|
||||
if c.ShouldBindJSON(req) != nil {
|
||||
|
@ -257,18 +265,19 @@ func FundRecordList(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
list, count, err := req.List()
|
||||
list, count, exportUrl, err := req.List()
|
||||
if err != nil {
|
||||
logger.Errorf("err:", logger.Field("err", err))
|
||||
app.Error(c, http.StatusInternalServerError, err, "查询失败")
|
||||
return
|
||||
}
|
||||
|
||||
ret := map[string]interface{}{
|
||||
"total": count,
|
||||
"list": list,
|
||||
"pageIndex": req.Page,
|
||||
"pageSize": req.PageSize,
|
||||
ret := models.FundRecordListResp{
|
||||
Total: count,
|
||||
List: list,
|
||||
PageIndex: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
ExportUrl: exportUrl,
|
||||
}
|
||||
app.OK(c, ret, "")
|
||||
}
|
||||
|
|
|
@ -78,17 +78,39 @@ const (
|
|||
WxAppMchId = "1609877389"
|
||||
WxAppMchSecret = "DeovoMingHuiRengTianTang45675456"
|
||||
|
||||
UnifiedOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"
|
||||
HmPayApiUrl = "https://hmpay.sandpay.com.cn/gateway/api"
|
||||
PemBegin = "-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
PemEnd = "\n-----END RSA PRIVATE KEY-----"
|
||||
HmPubKey = `MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDzGVH0Fxpb2M48U1BWr6lpNs2W3VHqtjO8X5RqWjtTwpQVKo8dqaiAGxVbsdnefPpsbI5l9rKquRAOJhWFU07hxSUgXZOk55QQmll03MBgRDXLgxyKfycLLQwhsCJAzDIWC7IWgok/RHV9m9AV2GbQxWBl+7iDE4prcbpgG8Z0HwIDAQAB`
|
||||
HmPayMerchantId = "664403000030115"
|
||||
TimeFormat = "2006-01-02 15:04:05"
|
||||
clientIp = "39.108.188.218" // 小程序服务器
|
||||
clientIpDev = "112.33.14.191" // 移动云服务器
|
||||
HmPayMerchantIdDeovo = "664403000021193"
|
||||
HmPubKeyDeovo = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDA4g8VFWIxEbOzxYC8ZIOgaOsLWK4Y5k9D8GwJ1Gige79LbTxbe3PH12KMc59DpCR1PnIDwlYWjIE7mZZAHgImXs0pSFihvlNS9srWk2uPlEXXQjjIZ3mnPoXtNhU0x5cYdkB8jtijcYMSGwKmdrIvpvPX3MrDKOX6dJ1T4ll+QIDAQAB"
|
||||
UnifiedOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"
|
||||
HmPayApiUrl = "https://hmpay.sandpay.com.cn/gateway/api"
|
||||
PemBegin = "-----BEGIN RSA PRIVATE KEY-----\n"
|
||||
PemEnd = "\n-----END RSA PRIVATE KEY-----"
|
||||
HmPubKey = `MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDzGVH0Fxpb2M48U1BWr6lpNs2W3VHqtjO8X5RqWjtTwpQVKo8dqaiAGxVbsdnefPpsbI5l9rKquRAOJhWFU07hxSUgXZOk55QQmll03MBgRDXLgxyKfycLLQwhsCJAzDIWC7IWgok/RHV9m9AV2GbQxWBl+7iDE4prcbpgG8Z0HwIDAQAB`
|
||||
HmPayMerchantId = "664403000030115"
|
||||
TimeFormat = "2006-01-02 15:04:05"
|
||||
clientIp = "39.108.188.218" // 小程序服务器
|
||||
clientIpDev = "112.33.14.191" // 移动云服务器
|
||||
|
||||
// HmPayMerchantIdSwitch 任天堂项目-对私账户(密钥20240701203620)
|
||||
HmPayMerchantIdSwitch = "664403000021193"
|
||||
HmPubKeySwitch = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDA4g8VFWIxEbOzxYC8ZIOgaOsLWK4Y5k9D8GwJ1Gige79LbTxbe3PH12KMc59DpCR1PnIDwlYWjIE7mZZAHgImXs0pSFihvlNS9srWk2uPlEXXQjjIZ3mnPoXtNhU0x5cYdkB8jtijcYMSGwKmdrIvpvPX3MrDKOX6dJ1T4ll+QIDAQAB"
|
||||
HmPubKeySwitchFp = "./config/hm_pay/switch_private_key.pem"
|
||||
TestHmPubKeySwitchFp = "/Users/max/Documents/code/deovo/mh_goadmin_server/config/hm_pay/switch_private_key.pem"
|
||||
|
||||
// HmPayMerchantIdSwitchPub 任天堂项目-对公账户(密钥20240819161949)
|
||||
HmPayMerchantIdSwitchPub = "664403000021225"
|
||||
HmPubKeySwitchPub = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBsfp+BrCGD39noWjW4z0VvvsFCWzU8vhAWlwGo/dkPxgQLXBNaTApUpavbQ6m/S0x5hQjcKwQ3UrJLDV70SAqPuO3QP0iagMKo2M6ROCO69L06In4gbqTTtTOb/1xpkbsVHd/9Wy/fyxreg1LY+MLzysH+OHAjjjiAYVL4e765QIDAQAB"
|
||||
HmPubKeySwitchPubFp = "./config/hm_pay/switch_pub_private_key.pem"
|
||||
TestHmPubKeySwitchPubFp = "/Users/max/Documents/code/deovo/mh_goadmin_server/config/hm_pay/switch_pub_private_key.pem"
|
||||
|
||||
// HmPayMerchantIdJBL 哈曼项目-对私账户(密钥20240820145322)
|
||||
HmPayMerchantIdJBL = "664403000021330"
|
||||
HmPubKeyJBL = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBhzboiNtCxDF3QXdPGx5aS2UjXSqq1p2JsIe+PhCWLdaNHoQxzTS0s41KuWbSDpSmtUhutBJZ1QBy+84iLmLKJ5E7UfUIGbrI309hJLQxQey655wWYBtkOVpq6aozjjnnjQjDbYG1WuFmLA03mzQ51VLr4555ioo70hredjLaVQIDAQAB"
|
||||
HmPubKeyJBLFp = "./config/hm_pay/jbl_private_key.pem"
|
||||
TestHmPubKeyJBLFp = "/Users/max/Documents/code/deovo/mh_goadmin_server/config/hm_pay/jbl_private_key.pem"
|
||||
|
||||
// HmPayMerchantIdJBLPub 哈曼项目-对公账户
|
||||
HmPayMerchantIdJBLPub = "664403000021340"
|
||||
HmPubKeyJBLPub = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIjqYgPO1kj3NI0WEfOCnKYUHu4EkARnbiJ2FKosajpP8eceaL1u4JOelNG+RN7cldvmWEtefZCPNOHAHddQLfEnRZ3xyzdRdV0A3vXykyY6UMWgRlPnHOslAm8OUpOWubDzQTmfr88R38EUrHG4HYvRVmQb/s/LQjsuS863vSbwIDAQAB"
|
||||
HmPubKeyJBLPubFp = "./config/hm_pay/jbl_pub_private_key.pem"
|
||||
TestHmPubKeyJBLPubFp = "/Users/max/Documents/code/deovo/mh_goadmin_server/config/hm_pay/jbl_pub_private_key.pem"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -698,10 +720,9 @@ type HmPayUnifiedOrderRsp struct {
|
|||
Sign string `json:"sign"`
|
||||
}
|
||||
|
||||
func ParsePrivateKeyDeovo() (*rsa.PrivateKey, error) {
|
||||
//fp := "/Users/max/Documents/code/deovo/mh_goadmin_server/config/hm_pay/deovo_private_key.pem"
|
||||
fp := "./config/hm_pay/deovo_private_key.pem"
|
||||
privateKey, err := os.ReadFile(fp)
|
||||
func ParsePrivateKeyDeovo(storeId uint32) (*rsa.PrivateKey, error) {
|
||||
storeKey := getStoreKeyConfig(storeId)
|
||||
privateKey, err := os.ReadFile(storeKey.FP)
|
||||
if err != nil {
|
||||
logger.Errorf("read file err:", err)
|
||||
return nil, err
|
||||
|
@ -722,12 +743,12 @@ func ParsePrivateKeyDeovo() (*rsa.PrivateKey, error) {
|
|||
return priKey.(*rsa.PrivateKey), nil
|
||||
}
|
||||
|
||||
func Sha1withRsaDeovo(signContent string) (string, error) {
|
||||
func Sha1withRsaDeovo(storeId uint32, signContent string) (string, error) {
|
||||
hash := crypto.SHA1
|
||||
shaNew := hash.New()
|
||||
shaNew.Write([]byte(signContent))
|
||||
hashed := shaNew.Sum(nil)
|
||||
priKey, err := ParsePrivateKeyDeovo()
|
||||
priKey, err := ParsePrivateKeyDeovo(storeId)
|
||||
if err != nil {
|
||||
logger.Errorf("parse err:", err)
|
||||
return "", err
|
||||
|
@ -741,7 +762,7 @@ func Sha1withRsaDeovo(signContent string) (string, error) {
|
|||
return b64.StdEncoding.EncodeToString(signature), nil
|
||||
}
|
||||
|
||||
func GenHmPaySignDeovo(m map[string]string) (string, error) {
|
||||
func GenHmPaySignDeovo(storeId uint32, m map[string]string) (string, error) {
|
||||
delete(m, "sign")
|
||||
var signData []string
|
||||
for k, v := range m {
|
||||
|
@ -765,7 +786,7 @@ func GenHmPaySignDeovo(m map[string]string) (string, error) {
|
|||
//logger.Info("签字符串1:", logger.Field("signStr", signStr))
|
||||
fmt.Println("签字符串1:", signStr)
|
||||
|
||||
signature, err := Sha1withRsaDeovo(signStr)
|
||||
signature, err := Sha1withRsaDeovo(storeId, signStr)
|
||||
if err != nil {
|
||||
logger.Errorf("signature err:", err)
|
||||
return "", err
|
||||
|
@ -905,7 +926,7 @@ func HmPayUnifiedOrder(r HmJsPayUnifiedOrderReq) (HmPayUnifiedOrderRsp, error) {
|
|||
return hmPayUnifiedOrderRsp, nil
|
||||
}
|
||||
|
||||
func HmVerifySha1RsaDeovo(signContent, signBase string) error {
|
||||
func HmVerifySha1RsaDeovo(storeId uint32, signContent, signBase string) error {
|
||||
//fp := "/Users/li/mh/mh_server/pack/configs/hm_pay/public_key.pme"
|
||||
//publicKeyString, err := ioutil.ReadFile(fp)
|
||||
//if err != nil {
|
||||
|
@ -913,7 +934,8 @@ func HmVerifySha1RsaDeovo(signContent, signBase string) error {
|
|||
// return err
|
||||
//}
|
||||
|
||||
block, _ := pem.Decode([]byte(FormatPrivateKey(HmPubKeyDeovo)))
|
||||
storeKey := getStoreKeyConfig(storeId)
|
||||
block, _ := pem.Decode([]byte(FormatPrivateKey(storeKey.PubKey)))
|
||||
if block == nil {
|
||||
fmt.Println("decode block is nil")
|
||||
return errors.New("decode block is nil")
|
||||
|
@ -1021,6 +1043,50 @@ func ToSignContent(s interface{}) (string, error) {
|
|||
return signStr, nil
|
||||
}
|
||||
|
||||
type StoreKeyConfig struct {
|
||||
AppID string
|
||||
FP string
|
||||
PubKey string
|
||||
}
|
||||
|
||||
func getStoreKeyConfig(storeId uint32) StoreKeyConfig {
|
||||
var config StoreKeyConfig
|
||||
|
||||
switch storeId {
|
||||
case 19, 23, 27, 28: // 汕头万象城, 海雅缤纷城, 布吉万象汇, 大运天地
|
||||
config = StoreKeyConfig{
|
||||
AppID: HmPayMerchantIdSwitchPub,
|
||||
FP: HmPubKeySwitchPubFp,
|
||||
PubKey: HmPubKeySwitchPub,
|
||||
}
|
||||
case 13: // 万象天地
|
||||
config = StoreKeyConfig{
|
||||
AppID: HmPayMerchantIdSwitch,
|
||||
FP: HmPubKeySwitchFp,
|
||||
PubKey: HmPubKeySwitch,
|
||||
}
|
||||
case 29: // JBL哈曼店
|
||||
now := time.Now()
|
||||
start := time.Date(now.Year(), now.Month(), now.Day(), 16, 30, 0, 0, now.Location())
|
||||
end := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())
|
||||
if now.After(start) && now.Before(end) {
|
||||
config = StoreKeyConfig{
|
||||
AppID: HmPayMerchantIdJBLPub,
|
||||
FP: HmPubKeyJBLPubFp,
|
||||
PubKey: HmPubKeyJBLPub,
|
||||
}
|
||||
} else {
|
||||
config = StoreKeyConfig{
|
||||
AppID: HmPayMerchantIdJBL,
|
||||
FP: HmPubKeyJBLFp,
|
||||
PubKey: HmPubKeyJBL,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// HmJsPayBToCOrder 河马刷卡支付(B扫C)
|
||||
func HmJsPayBToCOrder(storeId uint32, orderId string, totalFee float64, authCode, notifyUrl string) (*HmPayBToCOrderDetail, error) {
|
||||
now := time.Now().Local()
|
||||
|
@ -1033,9 +1099,11 @@ func HmJsPayBToCOrder(storeId uint32, orderId string, totalFee float64, authCode
|
|||
// return nil, errors.New("NotifyUrl is null")
|
||||
//}
|
||||
|
||||
storeKey := getStoreKeyConfig(storeId)
|
||||
|
||||
unifiedOrderReq := HmJsPayUnifiedOrderReq{}
|
||||
publicPara := HmPayPublicPara{
|
||||
AppId: HmPayMerchantIdDeovo,
|
||||
AppId: storeKey.AppID,
|
||||
//SubAppId: HmWxSubMerchantId,
|
||||
Method: "trade.pay",
|
||||
//Charset: "UTF-8",
|
||||
|
@ -1080,7 +1148,7 @@ func HmJsPayBToCOrder(storeId uint32, orderId string, totalFee float64, authCode
|
|||
return nil, err
|
||||
}
|
||||
|
||||
sign, err := GenHmPaySignDeovo(m)
|
||||
sign, err := GenHmPaySignDeovo(storeId, m)
|
||||
if err != nil {
|
||||
logger.Error("HmJsPayUnifiedOrder GenHmPaySign err:", logger.Field("err", err))
|
||||
return nil, err
|
||||
|
@ -1099,7 +1167,7 @@ func HmJsPayBToCOrder(storeId uint32, orderId string, totalFee float64, authCode
|
|||
return nil, err
|
||||
}
|
||||
|
||||
err = HmVerifySha1RsaDeovo(signContent, unifiedOrderResp.Sign)
|
||||
err = HmVerifySha1RsaDeovo(storeId, signContent, unifiedOrderResp.Sign)
|
||||
if err != nil {
|
||||
logger.Errorf("HmVerifySha1Rsa err:", err)
|
||||
return nil, err
|
||||
|
@ -1118,13 +1186,14 @@ func HmJsPayBToCOrder(storeId uint32, orderId string, totalFee float64, authCode
|
|||
}
|
||||
|
||||
// HmQueryOrder 订单查询
|
||||
func HmQueryOrder(orderId string) (*HmPayTradeQueryResp, error) {
|
||||
func HmQueryOrder(orderId string, storeId uint32) (*HmPayTradeQueryResp, error) {
|
||||
now := time.Now().Local()
|
||||
nonce := GenRandStr(NonceStringLength)
|
||||
|
||||
storeKey := getStoreKeyConfig(storeId)
|
||||
unifiedOrderReq := HmJsPayUnifiedOrderReq{}
|
||||
publicPara := HmPayPublicPara{
|
||||
AppId: HmPayMerchantIdDeovo,
|
||||
AppId: storeKey.AppID,
|
||||
Method: "trade.query",
|
||||
SignType: "RSA",
|
||||
Sign: "",
|
||||
|
@ -1149,7 +1218,7 @@ func HmQueryOrder(orderId string) (*HmPayTradeQueryResp, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
sign, err := GenHmPaySignDeovo(m)
|
||||
sign, err := GenHmPaySignDeovo(storeId, m)
|
||||
if err != nil {
|
||||
logger.Error("HmJsPayUnifiedOrder GenHmPaySign err:", logger.Field("err", err))
|
||||
return nil, err
|
||||
|
@ -1167,7 +1236,7 @@ func HmQueryOrder(orderId string) (*HmPayTradeQueryResp, error) {
|
|||
logger.Errorf("ToSignContent err:", err)
|
||||
return nil, err
|
||||
}
|
||||
err = HmVerifySha1RsaDeovo(signContent, unifiedOrderResp.Sign)
|
||||
err = HmVerifySha1RsaDeovo(storeId, signContent, unifiedOrderResp.Sign)
|
||||
if err != nil {
|
||||
logger.Errorf("HmVerifySha1Rsa err:", err)
|
||||
return nil, err
|
||||
|
@ -1187,13 +1256,13 @@ func HmQueryOrder(orderId string) (*HmPayTradeQueryResp, error) {
|
|||
}
|
||||
|
||||
// HmCancelOrder 订单撤销
|
||||
func HmCancelOrder(orderId string) (*HmPayTradeCancelResp, error) {
|
||||
func HmCancelOrder(orderId string, storeId uint32) (*HmPayTradeCancelResp, error) {
|
||||
now := time.Now().Local()
|
||||
nonce := GenRandStr(NonceStringLength)
|
||||
|
||||
unifiedOrderReq := HmJsPayUnifiedOrderReq{}
|
||||
publicPara := HmPayPublicPara{
|
||||
AppId: HmPayMerchantIdDeovo,
|
||||
AppId: HmPayMerchantIdSwitch,
|
||||
Method: "trade.cancel",
|
||||
SignType: "RSA",
|
||||
Sign: "",
|
||||
|
@ -1218,7 +1287,7 @@ func HmCancelOrder(orderId string) (*HmPayTradeCancelResp, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
sign, err := GenHmPaySignDeovo(m)
|
||||
sign, err := GenHmPaySignDeovo(storeId, m)
|
||||
if err != nil {
|
||||
logger.Error("HmJsPayUnifiedOrder GenHmPaySign err:", logger.Field("err", err))
|
||||
return nil, err
|
||||
|
@ -1236,7 +1305,7 @@ func HmCancelOrder(orderId string) (*HmPayTradeCancelResp, error) {
|
|||
logger.Errorf("ToSignContent err:", err)
|
||||
return nil, err
|
||||
}
|
||||
err = HmVerifySha1RsaDeovo(signContent, unifiedOrderResp.Sign)
|
||||
err = HmVerifySha1RsaDeovo(storeId, signContent, unifiedOrderResp.Sign)
|
||||
if err != nil {
|
||||
logger.Errorf("HmVerifySha1Rsa err:", err)
|
||||
return nil, err
|
||||
|
|
|
@ -43,7 +43,7 @@ func TestHmJsPayBToCOrder(t *testing.T) {
|
|||
func TestHmQueryOrder(t *testing.T) {
|
||||
orderId := "sale2024070569804727"
|
||||
|
||||
order, err := HmQueryOrder(orderId)
|
||||
order, err := HmQueryOrder(orderId, 13)
|
||||
if err != nil {
|
||||
fmt.Println("err:", err)
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ func TestHmQueryOrder(t *testing.T) {
|
|||
func TestHmCancelOrder(t *testing.T) {
|
||||
orderId := "sale2023122225067733"
|
||||
|
||||
order, err := HmCancelOrder(orderId)
|
||||
order, err := HmCancelOrder(orderId, 13)
|
||||
if err != nil {
|
||||
fmt.Println("err:", err)
|
||||
}
|
||||
|
|
|
@ -814,7 +814,7 @@ func ErpPurchaseReportByCommodity(c *gin.Context) {
|
|||
app.Error(c, http.StatusInternalServerError, err, "查询失败:"+err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Println(resp)
|
||||
//fmt.Println(resp)
|
||||
|
||||
app.OK(c, resp, "查询成功")
|
||||
return
|
||||
|
|
|
@ -2,6 +2,7 @@ package system
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"github.com/google/uuid"
|
||||
|
@ -25,6 +26,8 @@ import (
|
|||
// @Param roleId query string false "角色id"
|
||||
// @Param nickName query string false "昵称"
|
||||
// @Param storeId query string false "门店id"
|
||||
// @Param shopper_code query string false "店员兑换码"
|
||||
// @Param is_export query string false "是否导出:1-导出"
|
||||
// @Success 200 {object} models.SysUserListResp
|
||||
// @Router /api/v1/sysUserList [get]
|
||||
// @Security Bearer
|
||||
|
@ -43,17 +46,20 @@ func GetSysUserList(c *gin.Context) {
|
|||
if index != "" {
|
||||
pageIndex, err = tools.StringToInt(index)
|
||||
}
|
||||
data.Username = c.Request.FormValue("username") // 用户名称
|
||||
data.Status = c.Request.FormValue("status") // 状态
|
||||
data.Phone = c.Request.FormValue("phone") // 手机号
|
||||
strRoleId := c.Request.FormValue("roleId") // 用户角色
|
||||
data.NickName = c.Request.FormValue("nickName") // 用户昵称
|
||||
strStoreId := c.Request.FormValue("storeId") // 门店id
|
||||
data.ShopperCode = c.Request.FormValue("shopper_code") // 店员兑换码
|
||||
exportFlag := c.Request.FormValue("is_export") // 是否导出excel
|
||||
export := 0
|
||||
if exportFlag != "" {
|
||||
export, _ = tools.StringToInt(exportFlag)
|
||||
}
|
||||
|
||||
data.Username = c.Request.FormValue("username") // 用户名称
|
||||
data.Status = c.Request.FormValue("status") // 状态
|
||||
data.Phone = c.Request.FormValue("phone") // 手机号
|
||||
|
||||
strRoleId := c.Request.FormValue("roleId") // 用户角色
|
||||
data.RoleId, _ = tools.StringToInt(strRoleId)
|
||||
|
||||
data.NickName = c.Request.FormValue("nickName") // 用户昵称
|
||||
|
||||
strStoreId := c.Request.FormValue("storeId") // 门店id
|
||||
nStoreId, _ := tools.StringToInt(strStoreId)
|
||||
data.StoreId = uint32(nStoreId)
|
||||
|
||||
|
@ -64,10 +70,17 @@ func GetSysUserList(c *gin.Context) {
|
|||
data.DeptId, _ = tools.StringToInt(deptId)
|
||||
|
||||
data.DataScope = tools.GetUserIdStr(c)
|
||||
result, count, err := data.GetPage(pageSize, pageIndex)
|
||||
result, count, exportUrl, err := data.GetPage(pageSize, pageIndex, export)
|
||||
tools.HasError(err, "", -1)
|
||||
var resp models.SysUserListResp
|
||||
resp.List = result
|
||||
resp.ExportUrl = exportUrl
|
||||
resp.Total = count
|
||||
resp.PageSize = pageSize
|
||||
resp.PageIndex = pageIndex
|
||||
|
||||
app.PageOK(c, result, count, pageIndex, pageSize, "")
|
||||
app.OK(c, resp, "查询成功")
|
||||
return
|
||||
}
|
||||
|
||||
// GetSysUser
|
||||
|
@ -182,6 +195,27 @@ func InsertSysUser(c *gin.Context) {
|
|||
tools.HasError(err, "数据解析失败", 500)
|
||||
}
|
||||
|
||||
if req.ShopperCode != "" {
|
||||
if len(req.ShopperCode) != 6 {
|
||||
logger.Error("兑换码不是6位")
|
||||
app.Error(c, http.StatusInternalServerError, err, "兑换码长度不符合要求[6位]")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Uid == 0 {
|
||||
logger.Error("uid为0")
|
||||
app.Error(c, http.StatusInternalServerError, err, "配置店员兑换码需填写小程序账号ID")
|
||||
return
|
||||
}
|
||||
|
||||
// 判断店员兑换码是否重复
|
||||
if models.IsShopperCodeExists(req.ShopperCode) {
|
||||
logger.Error("兑换码重复")
|
||||
app.Error(c, http.StatusInternalServerError, err, fmt.Sprintf("兑换码[%s]重复,请更换", req.ShopperCode))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 判断小程序账号ID是否正常
|
||||
if req.Uid != 0 {
|
||||
userInfo, err := models.GetUserInfoByUid(req.Uid)
|
||||
|
@ -259,6 +293,16 @@ func InsertSysUser(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
if req.ShopperCode != "" {
|
||||
err = models.AddShopperCode(req, begin)
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Error("AddShopperCode err:", logger.Field("err", err))
|
||||
app.Error(c, http.StatusInternalServerError, err, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = begin.Commit().Error
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
|
@ -286,13 +330,37 @@ func UpdateSysUser(c *gin.Context) {
|
|||
err := c.BindWith(&req, binding.JSON)
|
||||
tools.HasError(err, "非法数据格式", 500)
|
||||
|
||||
if req.ShopperCode != "" {
|
||||
if len(req.ShopperCode) != 6 {
|
||||
logger.Error("兑换码不是6位")
|
||||
app.Error(c, http.StatusInternalServerError, err, "店员识别码长度不符合要求[6位]")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Uid == 0 {
|
||||
logger.Error("uid为0")
|
||||
app.Error(c, http.StatusInternalServerError, err, "配置店员识别码需填写小程序账号ID")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
SalesCommRateFloat, err := models.StringToFloat(req.SalesCommRate)
|
||||
if err != nil {
|
||||
//logger.Error("brokerage1 err:", err)
|
||||
tools.HasError(err, "数据解析失败", 500)
|
||||
}
|
||||
|
||||
sysInfo := models.GetUserById(uint32(req.UserId))
|
||||
sysInfo := models.GetSysUserById(uint32(req.UserId))
|
||||
if sysInfo.Uid != 0 {
|
||||
// 添加店员兑换码
|
||||
var shopperCode models.ShopperPromotionCode
|
||||
err = orm.Eloquent.Table("shopper_promotion_code").Where("uid = ?", sysInfo.Uid).Find(&shopperCode).Error
|
||||
if err != nil {
|
||||
logger.Error("query shopper_promotion_code err:", logger.Field("err", err))
|
||||
}
|
||||
sysInfo.ShopperCode = shopperCode.Code
|
||||
}
|
||||
|
||||
// 判断小程序账号ID是否正常
|
||||
if req.Uid != 0 && sysInfo.Uid != req.Uid {
|
||||
userInfo, err := models.GetUserInfoByUid(req.Uid)
|
||||
|
@ -336,6 +404,11 @@ func UpdateSysUser(c *gin.Context) {
|
|||
},
|
||||
}
|
||||
|
||||
// 重置密码时uid赋值为原有的uid
|
||||
if req.Phone == "" && req.LoginM.PassWord.Password != "" && req.Uid == 0 {
|
||||
data.Uid = sysInfo.Uid
|
||||
}
|
||||
|
||||
if len(req.StoreList) != 0 {
|
||||
// 将 StoreData 转换为 JSON 字符串
|
||||
storeDataJSON, err := json.Marshal(req.StoreList)
|
||||
|
@ -350,35 +423,45 @@ func UpdateSysUser(c *gin.Context) {
|
|||
begin := orm.Eloquent.Begin()
|
||||
data.UpdateBy = tools.GetUserIdStr(c)
|
||||
result, err := data.Update(begin, data.UserId)
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
}
|
||||
tools.HasError(err, "修改失败", 500)
|
||||
|
||||
// 判断是否修改了uid
|
||||
if sysInfo.Uid == 0 && req.Uid != 0 { // 新增uid,直接更新为2即可
|
||||
err = models.UpdateUserType(begin, req.Uid, models.UserTypeShopAssistant, uint32(req.RoleId))
|
||||
} else if sysInfo.Uid != 0 {
|
||||
if sysInfo.Uid != req.Uid {
|
||||
// 原uid的状态更新为1
|
||||
err = models.UpdateUserType(begin, sysInfo.Uid, models.UserTypeConsumer, 0)
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Error("UpdateUserType err:", logger.Field("err", err))
|
||||
app.Error(c, http.StatusInternalServerError, err, "修改失败")
|
||||
return
|
||||
if req.Phone != "" { // 手机号目前是必填项,不能为空,否则可能是重置密码
|
||||
if sysInfo.Uid == 0 && req.Uid != 0 { // 新增uid,直接更新为2即可
|
||||
err = models.UpdateUserType(begin, req.Uid, models.UserTypeShopAssistant, uint32(req.RoleId))
|
||||
} else if sysInfo.Uid != 0 {
|
||||
if sysInfo.Uid != req.Uid {
|
||||
// 原uid的状态更新为1
|
||||
err = models.UpdateUserType(begin, sysInfo.Uid, models.UserTypeConsumer, 0)
|
||||
if err == nil {
|
||||
if req.Uid != 0 {
|
||||
// 新uid状态更新为2
|
||||
err = models.UpdateUserType(begin, req.Uid, models.UserTypeShopAssistant, uint32(req.RoleId))
|
||||
}
|
||||
}
|
||||
} else if sysInfo.Uid == req.Uid && sysInfo.RoleId != req.RoleId { // 更改了用户角色
|
||||
err = models.UpdateUserType(begin, sysInfo.Uid, models.UserTypeShopAssistant, uint32(req.RoleId))
|
||||
}
|
||||
|
||||
if req.Uid != 0 {
|
||||
// 新uid状态更新为2
|
||||
err = models.UpdateUserType(begin, req.Uid, models.UserTypeShopAssistant, uint32(req.RoleId))
|
||||
}
|
||||
} else if sysInfo.Uid == req.Uid && sysInfo.RoleId != req.RoleId { // 更改了用户角色
|
||||
err = models.UpdateUserType(begin, sysInfo.Uid, models.UserTypeShopAssistant, uint32(req.RoleId))
|
||||
}
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Error("UpdateUserType err:", logger.Field("err", err))
|
||||
app.Error(c, http.StatusInternalServerError, err, "修改失败")
|
||||
return
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Error("UpdateUserType err:", logger.Field("err", err))
|
||||
app.Error(c, http.StatusInternalServerError, err, "修改失败")
|
||||
return
|
||||
|
||||
if req.ShopperCode != "" { // 添加店员兑换码:删除原兑换码,添加新兑换码
|
||||
err = models.UpdateShopperCode(req, begin, sysInfo)
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Error("UpdateShopperCode err:", logger.Field("err", err))
|
||||
app.Error(c, http.StatusInternalServerError, err, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = begin.Commit().Error
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"go-admin/tools/config"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"gorm.io/gorm"
|
||||
"math"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
@ -35,9 +36,6 @@ const (
|
|||
SystemOut = 5 // 系统出库
|
||||
CheckOut = 6 // 盘点出库
|
||||
OnSale = 7 // 销售锁定中
|
||||
|
||||
PurchasePrice = "erp:stock:stockDetails:list:purchasePrice" // 入库采购价
|
||||
EmployeeCostPrice = "erp:stock:stockDetails:list:employeeCostPrice" // 入库员工成本价
|
||||
)
|
||||
|
||||
// ErpStock 库存列表
|
||||
|
@ -56,7 +54,8 @@ type ErpStock struct {
|
|||
MinRetailPrice float64 `json:"min_retail_price"` // 最低零售价
|
||||
Count uint32 `json:"count"` // 数量
|
||||
DispatchCount uint32 `json:"dispatch_count"` // 调拨中数量(调拨中调入)
|
||||
Commodities []ErpStockCommodity `json:"commodities" gorm:"-"`
|
||||
Commodities []ErpStockCommodity `json:"commodities" gorm:"-"` //
|
||||
DecisionStoreId []uint32 `json:"decision_store_id" gorm:"-"` // 门店编号列表(查询进销存的时候使用)
|
||||
}
|
||||
|
||||
// ErpStockCommodity 库存详情
|
||||
|
@ -122,6 +121,7 @@ type ErpCommodity struct {
|
|||
Origin string `json:"origin"` // 产地
|
||||
Remark string `json:"remark" gorm:"type:varchar(512)"` // 备注
|
||||
StockCount uint32 `json:"stock_count" gorm:"-"` // 库存数量
|
||||
Img string `json:"img"` // 图片
|
||||
|
||||
ErpCategory *ErpCategory `json:"erp_category" gorm:"-"`
|
||||
}
|
||||
|
@ -509,6 +509,10 @@ func (m *ErpCommodityListReq) List() (*ErpCommodityListResp, error) {
|
|||
|
||||
// 计算分页所需的切片索引
|
||||
startIndex := page * m.PageSize
|
||||
if (len(commodities)/m.PageSize + 1) < startIndex {
|
||||
startIndex = 0
|
||||
page = 0
|
||||
}
|
||||
endIndex := (page + 1) * m.PageSize
|
||||
if endIndex > len(commodities) {
|
||||
endIndex = len(commodities)
|
||||
|
@ -523,6 +527,44 @@ func (m *ErpCommodityListReq) List() (*ErpCommodityListResp, error) {
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
// SortByErpSupplierId 对商品数组进行排序,先按供应商ID排序,如果相同则按商品编号排序(升序)
|
||||
func SortByErpSupplierId(commodities []ErpCommodity, supplierIDDesc bool) {
|
||||
// 定义排序函数
|
||||
less := func(i, j int) bool {
|
||||
// 按照供应商ID排序
|
||||
if commodities[i].ErpSupplierId != commodities[j].ErpSupplierId {
|
||||
if supplierIDDesc { // 降序 DESC
|
||||
return commodities[i].ErpSupplierId > commodities[j].ErpSupplierId
|
||||
}
|
||||
return commodities[i].ErpSupplierId < commodities[j].ErpSupplierId // 升序 ASC
|
||||
}
|
||||
|
||||
// 解析商品编号,提取分类编号和商品编号的数字部分
|
||||
catNumI, subCatNumI, threeSubCatNumI, itemNumI := parseSerialNumber(commodities[i].SerialNumber)
|
||||
catNumJ, subCatNumJ, threeSubCatNumJ, itemNumJ := parseSerialNumber(commodities[j].SerialNumber)
|
||||
|
||||
// 按照分类编号从小到大排序
|
||||
if catNumI != catNumJ {
|
||||
return catNumI < catNumJ
|
||||
}
|
||||
|
||||
// 如果分类编号相同,按照具体分类下的商品编号递增排序
|
||||
if subCatNumI != subCatNumJ {
|
||||
return subCatNumI < subCatNumJ
|
||||
}
|
||||
|
||||
if threeSubCatNumI != threeSubCatNumJ {
|
||||
return threeSubCatNumI < threeSubCatNumJ
|
||||
}
|
||||
|
||||
// 如果具体分类编号也相同,按照商品编号递增排序
|
||||
return itemNumI < itemNumJ
|
||||
}
|
||||
|
||||
// 调用排序函数进行排序
|
||||
sort.SliceStable(commodities, less)
|
||||
}
|
||||
|
||||
// SortStockCommodities 对库存商品数组进行排序
|
||||
func SortStockCommodities(commodities []ErpStock) {
|
||||
// 定义排序函数
|
||||
|
@ -1191,13 +1233,13 @@ func (m *StockImporter) processErpStocks(erpStocks []ErpStockCommodity) error {
|
|||
})
|
||||
}
|
||||
|
||||
err := m.ErpStockCountUpdate(begin) //更新or插入库存表
|
||||
err := errGroup.Wait()
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
err = errGroup.Wait()
|
||||
err = m.ErpStockCountUpdate(begin) //更新or插入库存表
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
return err
|
||||
|
@ -1221,8 +1263,26 @@ func createStockList(begin *gorm.DB, stockList []ErpStockCommodity) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// 合并导入数据的辅助函数
|
||||
func mergeCensusMap(censusMap map[uint32]map[uint32]uint32) map[uint32]map[uint32]uint32 {
|
||||
mergedMap := make(map[uint32]map[uint32]uint32)
|
||||
for storeId, commodities := range censusMap {
|
||||
if mergedMap[storeId] == nil {
|
||||
mergedMap[storeId] = make(map[uint32]uint32)
|
||||
}
|
||||
for commodityId, count := range commodities {
|
||||
mergedMap[storeId][commodityId] += count
|
||||
}
|
||||
}
|
||||
return mergedMap
|
||||
}
|
||||
|
||||
func (m *StockImporter) ErpStockCountUpdate(gdb *gorm.DB) error {
|
||||
for k1, v1 := range m.CensusMap {
|
||||
// 合并导入数据,避免同一商品多次重复处理
|
||||
mergedCensusMap := mergeCensusMap(m.CensusMap)
|
||||
|
||||
//for k1, v1 := range m.CensusMap {
|
||||
for k1, v1 := range mergedCensusMap {
|
||||
for k2, v2 := range v1 {
|
||||
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock WHERE store_id=%d AND erp_commodity_id=%d", k1, k2))
|
||||
if err != nil {
|
||||
|
@ -1408,44 +1468,85 @@ func ErpStockCommodityToInventory(inventoryStockIdMap map[string]uint32, list []
|
|||
// ErpCommodityListExport 导出商品列表
|
||||
func ErpCommodityListExport(list []ErpCommodity) (string, error) {
|
||||
file := excelize.NewFile()
|
||||
streamWriter, err := file.NewStreamWriter("Sheet1")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fSheet := "Sheet1"
|
||||
|
||||
url := ExportUrl
|
||||
fileName := time.Now().Format(TimeFormat) + "商品" + ".xlsx"
|
||||
fileName := time.Now().Format(TimeFormat) + "商品资料" + ".xlsx"
|
||||
|
||||
//title := []interface{}{"供应商编号", "供应商名称", "联系人", "手机号", "地址", "开户银行", "银行账号", "付款周期/天"}
|
||||
title := []interface{}{"商品编号", "商品名称", "商品分类", "是否串码", "主供应商", "零售价", "最低零售价", "员工成本价",
|
||||
"采购价", "提成等级1", "提成等级2", "产地", "备注", "会员折扣(零售价的百分比)"}
|
||||
cell, _ := excelize.CoordinatesToCellName(1, 1)
|
||||
if err = streamWriter.SetRow(cell, title); err != nil {
|
||||
fmt.Println(err)
|
||||
title := []interface{}{"商品编号", "商品名称", "商品分类", "商品条码", "是否串码", "系统生成串码", "主供应商", "指导零售价",
|
||||
"最低零售价", "员工成本价加价", "指导采购价", "销售毛利提成", "员工毛利提成", "会员优惠", "产地", "备注"}
|
||||
for i, _ := range title {
|
||||
cell, _ := excelize.CoordinatesToCellName(1+i, 1)
|
||||
err := file.SetCellValue(fSheet, cell, title[i])
|
||||
if err != nil {
|
||||
logger.Errorf("file set value err:", err)
|
||||
}
|
||||
}
|
||||
|
||||
var row []interface{}
|
||||
nExcelStartRow := 0
|
||||
for rowId := 0; rowId < len(list); rowId++ {
|
||||
isIMEI := "否"
|
||||
if list[rowId].IMEIType == 2 {
|
||||
systemIMEI := "否"
|
||||
if list[rowId].IMEIType != 1 { // 非串码
|
||||
isIMEI = "是"
|
||||
if list[rowId].IMEIType == 2 { //2-串码(系统生成)
|
||||
systemIMEI = "是"
|
||||
}
|
||||
}
|
||||
|
||||
row = []interface{}{list[rowId].SerialNumber, list[rowId].Name, list[rowId].ErpCategoryName,
|
||||
isIMEI, list[rowId].ErpSupplierName, list[rowId].RetailPrice,
|
||||
list[rowId].MinRetailPrice, list[rowId].StaffCostPrice, list[rowId].WholesalePrice, list[rowId].Brokerage1,
|
||||
list[rowId].Brokerage2, list[rowId].Origin, list[rowId].Remark, list[rowId].MemberDiscount}
|
||||
cell, _ := excelize.CoordinatesToCellName(1, rowId+2)
|
||||
if err := streamWriter.SetRow(cell, row); err != nil {
|
||||
fmt.Println(err)
|
||||
row = []interface{}{
|
||||
list[rowId].SerialNumber,
|
||||
list[rowId].Name,
|
||||
list[rowId].ErpCategoryName,
|
||||
list[rowId].ErpBarcode,
|
||||
isIMEI,
|
||||
systemIMEI,
|
||||
list[rowId].ErpSupplierName,
|
||||
list[rowId].RetailPrice,
|
||||
list[rowId].MinRetailPrice,
|
||||
list[rowId].StaffCostPrice,
|
||||
list[rowId].WholesalePrice,
|
||||
list[rowId].Brokerage1,
|
||||
list[rowId].Brokerage2,
|
||||
list[rowId].MemberDiscount,
|
||||
list[rowId].Origin,
|
||||
list[rowId].Remark}
|
||||
|
||||
for j, _ := range row {
|
||||
cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2)
|
||||
err := file.SetCellValue(fSheet, cell, row[j])
|
||||
if err != nil {
|
||||
logger.Error("file set value err:", logger.Field("err", err))
|
||||
}
|
||||
}
|
||||
nExcelStartRow++
|
||||
}
|
||||
if err := streamWriter.Flush(); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err := file.SaveAs("/www/server/images/export/" + fileName); err != nil {
|
||||
//if err := file.SaveAs("./" + fileName); err != nil {
|
||||
// 设置所有单元格的样式: 居中、加边框
|
||||
style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"},
|
||||
"border":[{"type":"left","color":"000000","style":1},
|
||||
{"type":"top","color":"000000","style":1},
|
||||
{"type":"right","color":"000000","style":1},
|
||||
{"type":"bottom","color":"000000","style":1}]}`)
|
||||
|
||||
//设置单元格高度
|
||||
file.SetRowHeight("Sheet1", 1, 20)
|
||||
|
||||
// 设置单元格大小
|
||||
file.SetColWidth("Sheet1", "A", "A", 15)
|
||||
file.SetColWidth("Sheet1", "B", "B", 30)
|
||||
file.SetColWidth("Sheet1", "D", "D", 18)
|
||||
|
||||
endRow := fmt.Sprintf("P"+"%d", nExcelStartRow+2)
|
||||
|
||||
// 应用样式到整个表格
|
||||
_ = file.SetCellStyle("Sheet1", "A1", endRow, style)
|
||||
|
||||
fmt.Println("save fileName:", config.ExportConfig.Path+fileName)
|
||||
if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
return url + fileName, nil
|
||||
}
|
||||
|
||||
|
@ -1474,7 +1575,7 @@ func checkRoleMenu(c *gin.Context, menuName string) (bool, error) {
|
|||
}
|
||||
|
||||
// InventoryDetailListExport 导出库存商品列表
|
||||
func InventoryDetailListExport(list []ErpStockCommodity, exportPurchasePrice bool, exportStaffCostPrice bool) (string, error) {
|
||||
func InventoryDetailListExport(list []ErpStockCommodity, c *gin.Context) (string, error) {
|
||||
file := excelize.NewFile()
|
||||
streamWriter, err := file.NewStreamWriter("Sheet1")
|
||||
if err != nil {
|
||||
|
@ -1483,12 +1584,20 @@ func InventoryDetailListExport(list []ErpStockCommodity, exportPurchasePrice boo
|
|||
}
|
||||
|
||||
url := ExportUrl
|
||||
fileName := time.Now().Format(TimeFormat) + "商品" + ".xlsx"
|
||||
fileName := time.Now().Format(TimeFormat) + "库存详情" + ".xlsx"
|
||||
fmt.Println("url fileName:", url+fileName)
|
||||
|
||||
// 判断是否有入库采购价、入库员工成本价的权限
|
||||
exportPurchasePrice, _ := checkRoleMenu(c, PurchasePrice)
|
||||
exportStaffCostPrice, _ := checkRoleMenu(c, EmployeeCostPrice)
|
||||
fmt.Println("exportPurchasePrice is:", exportPurchasePrice)
|
||||
fmt.Println("exportStaffCostPrice is:", exportStaffCostPrice)
|
||||
logger.Info("exportPurchasePrice is:", logger.Field("exportPurchasePrice", exportPurchasePrice))
|
||||
logger.Info("exportStaffCostPrice is:", logger.Field("exportStaffCostPrice", exportStaffCostPrice))
|
||||
|
||||
// 设置标题行
|
||||
title := []interface{}{"商品编号", "商品名称", "商品分类", "是否串码", "商品串码", "所属门店", "供应商", "首次入库时间", "首次入库方式",
|
||||
"首次入库订单编号", "最近入库时间"}
|
||||
title := []interface{}{"商品编号", "商品名称", "商品分类", "是否串码", "商品串码", "所属门店", "供应商", "库存数量",
|
||||
"首次入库时间", "首次入库方式", "首次入库订单编号", "最近入库时间"}
|
||||
|
||||
if exportPurchasePrice {
|
||||
title = append(title, "入库采购价")
|
||||
|
@ -1540,6 +1649,7 @@ func InventoryDetailListExport(list []ErpStockCommodity, exportPurchasePrice boo
|
|||
list[rowId].IMEI,
|
||||
list[rowId].StoreName,
|
||||
list[rowId].ErpSupplierName,
|
||||
1,
|
||||
list[rowId].FirstStockTime,
|
||||
storageType,
|
||||
list[rowId].OriginalSn,
|
||||
|
@ -1559,19 +1669,19 @@ func InventoryDetailListExport(list []ErpStockCommodity, exportPurchasePrice boo
|
|||
row = append(row, state)
|
||||
row = append(row, list[rowId].Remark)
|
||||
|
||||
cell, _ := excelize.CoordinatesToCellName(1, rowId+2)
|
||||
if err := streamWriter.SetRow(cell, row); err != nil {
|
||||
cell, _ = excelize.CoordinatesToCellName(1, rowId+2)
|
||||
if err = streamWriter.SetRow(cell, row); err != nil {
|
||||
fmt.Println(err)
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
if err := streamWriter.Flush(); err != nil {
|
||||
if err = streamWriter.Flush(); err != nil {
|
||||
fmt.Println(err)
|
||||
return "", err
|
||||
}
|
||||
fmt.Println("save fileName:", config.ExportConfig.Path+fileName)
|
||||
if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil {
|
||||
if err = file.SaveAs(config.ExportConfig.Path + fileName); err != nil {
|
||||
fmt.Println(err)
|
||||
return "", err
|
||||
}
|
||||
|
@ -2349,8 +2459,8 @@ type ErpStockCommodityListResp struct {
|
|||
Total int `json:"total"` // 数据总条数
|
||||
PageIndex int `json:"pageIndex"` // 页码
|
||||
PageSize int `json:"pageSize"` // 每页展示条数
|
||||
TotalWholesalePrice int `json:"total_wholesale_price"` // 入库采购价之和
|
||||
TotalStaffPrice int `json:"total_staff_price"` // 入库员工成本价之和
|
||||
TotalWholesalePrice float64 `json:"total_wholesale_price"` // 入库采购价之和
|
||||
TotalStaffPrice float64 `json:"total_staff_price"` // 入库员工成本价之和
|
||||
ExportUrl string `json:"export_url"`
|
||||
}
|
||||
|
||||
|
@ -2431,14 +2541,8 @@ func (m *ErpStockCommodityListReq) GetDetailList(c *gin.Context, nType uint32) (
|
|||
return resp, err
|
||||
}
|
||||
ErpStockCommodityListSetAge(commodities)
|
||||
// 判断是否有入库采购价、入库员工成本价的权限
|
||||
purchasePriceFlag, _ := checkRoleMenu(c, PurchasePrice)
|
||||
employeeCostPriceFlag, _ := checkRoleMenu(c, EmployeeCostPrice)
|
||||
fmt.Println("purchasePriceFlag is:", purchasePriceFlag)
|
||||
fmt.Println("employeeCostPriceFlag is:", employeeCostPriceFlag)
|
||||
logger.Info("purchasePriceFlag is:", logger.Field("purchasePriceFlag", purchasePriceFlag))
|
||||
logger.Info("employeeCostPriceFlag is:", logger.Field("employeeCostPriceFlag", purchasePriceFlag))
|
||||
listExport, err := InventoryDetailListExport(commodities, purchasePriceFlag, employeeCostPriceFlag)
|
||||
|
||||
listExport, err := InventoryDetailListExport(commodities, c)
|
||||
if err != nil {
|
||||
//logger.Error("list export err:", err)
|
||||
}
|
||||
|
@ -2465,8 +2569,8 @@ func (m *ErpStockCommodityListReq) GetDetailList(c *gin.Context, nType uint32) (
|
|||
resp.Total = int(count)
|
||||
resp.PageIndex = page + 1
|
||||
resp.PageSize = m.PageSize
|
||||
resp.TotalWholesalePrice = int(nTotalCount.TotalWholesalePrice)
|
||||
resp.TotalStaffPrice = int(nTotalCount.TotalStaffCostPrice + nTotalCount.TotalWholesalePrice)
|
||||
resp.TotalWholesalePrice = math.Round(nTotalCount.TotalWholesalePrice*100) / 100
|
||||
resp.TotalStaffPrice = math.Round((nTotalCount.TotalStaffCostPrice+nTotalCount.TotalWholesalePrice)*100) / 100
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
@ -2714,7 +2818,9 @@ func SetStockCommodityState(c *gin.Context, id uint32) error { //更新库存状
|
|||
|
||||
// 更新商品库存详情表状态为:系统出库
|
||||
if err := begin.Model(&ErpStockCommodity{}).Where("id=?", id).Updates(map[string]interface{}{
|
||||
"state": SystemOut}).Error; err != nil {
|
||||
"state": SystemOut,
|
||||
"updated_at": time.Now(),
|
||||
}).Error; err != nil {
|
||||
return fmt.Errorf("[update err]:%v", err)
|
||||
}
|
||||
|
||||
|
@ -3066,7 +3172,8 @@ type CommodityCreateRequest struct {
|
|||
Brokerage2 float64 `json:"brokerage_2"` // 员工毛利提成
|
||||
MemberDiscount float64 `json:"member_discount"` // 会员优惠
|
||||
Origin string `json:"origin"` // 产地
|
||||
Remark string `json:"remark" gorm:"type:varchar(512)"` // 备注
|
||||
Remark string `json:"remark"` // 备注
|
||||
Img string `json:"img"` // 图片
|
||||
}
|
||||
|
||||
type CommodityEditRequest struct {
|
||||
|
@ -3085,7 +3192,8 @@ type CommodityEditRequest struct {
|
|||
Brokerage2 float64 `json:"brokerage_2"` // 员工毛利提成
|
||||
MemberDiscount float64 `json:"member_discount"` // 会员优惠
|
||||
Origin string `json:"origin"` // 产地
|
||||
Remark string `json:"remark" gorm:"type:varchar(512)"` // 备注
|
||||
Remark string `json:"remark"` // 备注
|
||||
Img string `json:"img"` // 图片
|
||||
}
|
||||
|
||||
type CommodityDetailRequest struct {
|
||||
|
|
|
@ -12,18 +12,19 @@ const (
|
|||
type Coupon struct {
|
||||
Model
|
||||
|
||||
Name string `json:"name"`
|
||||
Describe string `json:"describe" gorm:"type:text;"` // 描述
|
||||
CouponType string `json:"coupon_type"`
|
||||
ActivityType uint32 `json:"activity_type"` // 活动类型 1-会员续费
|
||||
ActivityId uint32 `json:"activity_id" gorm:"index"`
|
||||
Value uint32 `json:"value"`
|
||||
OutCount uint32 `json:"out_count"` // 用户已领取数量
|
||||
UsedCount uint32 `json:"used_count"` // 用户已使用数量
|
||||
ActiveStart time.Time `json:"active_start"` // 有效期开始
|
||||
ActiveEnd time.Time `json:"active_end"` // 有效期结束 零值永不结束
|
||||
MemberLevel uint32 `json:"member_level"` // 会员等级 1-用户 2-会员
|
||||
IsDraw bool `json:"is_draw" gorm:"-"`
|
||||
Name string `json:"name"` // 优惠券名称
|
||||
Describe string `json:"describe" gorm:"type:text"` // 优惠券简介
|
||||
Rule string `json:"rule" gorm:"type:text"` // 优惠券使用规则
|
||||
CouponType string `json:"coupon_type"` //
|
||||
ActivityType uint32 `json:"activity_type"` // 活动类型 1-会员续费
|
||||
ActivityId uint32 `json:"activity_id" gorm:"index"` //
|
||||
Value uint32 `json:"value"` //
|
||||
OutCount uint32 `json:"out_count"` // 用户已领取数量
|
||||
UsedCount uint32 `json:"used_count"` // 用户已使用数量
|
||||
ActiveStart time.Time `json:"active_start"` // 有效期开始
|
||||
ActiveEnd time.Time `json:"active_end"` // 有效期结束 零值永不结束
|
||||
MemberLevel uint32 `json:"member_level"` // 会员等级 1-用户 2-会员
|
||||
IsDraw bool `json:"is_draw" gorm:"-"` //
|
||||
}
|
||||
|
||||
// gen:qs
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1557,7 +1557,7 @@ func ExpireMemberSMSSendDay(day uint32, nowTime time.Time) {
|
|||
//err := orm.Eloquent.Table("user").Where("member_expire > ?", start).Where("member_expire < ?", end).
|
||||
// Where("member_level in (?)", []uint32{2, 3, 4, 5}).Find(&users).Error
|
||||
err := orm.Eloquent.Table("user").Where("member_expire > ?", start).Where("member_expire < ?", end).
|
||||
Where("member_level = ?", MemberLevelUser).Find(&users).Error
|
||||
Where("member_level = ?", MemberLevelUser).Find(&users).Error
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
return
|
||||
|
|
|
@ -142,12 +142,12 @@ func checkAllotInventoryParam(req *InventoryAllotAddReq, editFlag bool) error {
|
|||
}
|
||||
}
|
||||
|
||||
// 校验编辑订单时是否有传商品ID
|
||||
if editFlag {
|
||||
if item.ID == 0 {
|
||||
return fmt.Errorf("商品[%s]ID为空", item.CommodityName)
|
||||
}
|
||||
}
|
||||
//// 校验编辑订单时是否有传商品ID
|
||||
//if editFlag {
|
||||
// if item.ID == 0 {
|
||||
// return fmt.Errorf("商品[%s]ID为空", item.CommodityName)
|
||||
// }
|
||||
//}
|
||||
|
||||
// 校验串码类型
|
||||
switch item.IMEIType {
|
||||
|
@ -351,7 +351,7 @@ func EditAllotInventory(req *InventoryAllotEditReq) (*ErpInventoryAllotOrder, er
|
|||
inventoryAllotOrder.TotalCount = nTotalCount
|
||||
|
||||
err = begin.Model(&ErpInventoryAllotOrder{}).Where("id = ?", inventoryAllotOrder.ID).
|
||||
Updates(inventoryAllotOrder).Error
|
||||
Omit("created_at").Save(inventoryAllotOrder).Error
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Error("update allot order err:", logger.Field("err", err))
|
||||
|
@ -786,6 +786,33 @@ func MergeCommodities(commodities []ErpInventoryAllotCommodity) []ErpInventoryAl
|
|||
return mergedCommodities
|
||||
}
|
||||
|
||||
// MergeAllCommodities 遍历库存调拨商品信息,将商品id相同的所有商品进行合并,数量累加即可
|
||||
func MergeAllCommodities(commodities []ErpInventoryAllotCommodity) []ErpInventoryAllotCommodity {
|
||||
// 用于存储合并后的商品信息
|
||||
mergedCommodities := make([]ErpInventoryAllotCommodity, 0)
|
||||
// 用于记录无串码商品的合并信息
|
||||
commodityMap := make(map[uint32]*ErpInventoryAllotCommodity)
|
||||
|
||||
for _, commodity := range commodities {
|
||||
if existing, found := commodityMap[commodity.CommodityId]; found {
|
||||
// 如果相同商品 ID 的无串码商品已存在,则数量累加
|
||||
existing.Count += commodity.Count
|
||||
commodityMap[commodity.CommodityId] = existing
|
||||
} else {
|
||||
// 否则,加入到 commodityMap 中
|
||||
newCommodity := commodity
|
||||
commodityMap[commodity.CommodityId] = &newCommodity
|
||||
}
|
||||
}
|
||||
|
||||
// 将合并后的无串码商品加入到合并后的列表中
|
||||
for _, commodity := range commodityMap {
|
||||
mergedCommodities = append(mergedCommodities, *commodity)
|
||||
}
|
||||
|
||||
return mergedCommodities
|
||||
}
|
||||
|
||||
// MergeChangeCommodities 遍历库存变动商品信息,将商品id相同的非串码商品进行合并,数量累加即可
|
||||
func MergeChangeCommodities(commodities []ErpInventoryChangeCommodity) []ErpInventoryChangeCommodity {
|
||||
// 用于存储合并后的商品信息
|
||||
|
@ -843,7 +870,7 @@ func cancelAllotAuditAndUpdateStock(gdb *gorm.DB, allotOrder ErpInventoryAllotOr
|
|||
for _, v := range trimCommodities {
|
||||
var stockCommodity []ErpStockCommodity
|
||||
err := orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
|
||||
"AND state = ? AND imei = ?", v.CommodityId, allotOrder.ReceiveStoreId, InAllot, v.IMEI).
|
||||
"AND state = ? AND imei = ?", v.CommodityId, allotOrder.DeliverStoreId, InAllot, v.IMEI).
|
||||
Find(&stockCommodity).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("查询商品库存失败:[%s]", err.Error())
|
||||
|
@ -1043,13 +1070,15 @@ func ReceiveAllotInventory(req *InventoryAllotReceiveReq, c *gin.Context) error
|
|||
// 遍历库存调拨商品信息
|
||||
for _, v := range trimCommodities {
|
||||
var stockCommodity []ErpStockCommodity
|
||||
err := orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
|
||||
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
|
||||
"AND state = ? AND imei = ?", v.CommodityId, inventoryAllotOrder.DeliverStoreId, InAllot, v.IMEI).
|
||||
Find(&stockCommodity).Error
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
return fmt.Errorf("查询商品库存失败:[%s]", err.Error())
|
||||
}
|
||||
if len(stockCommodity) == 0 {
|
||||
begin.Rollback()
|
||||
return fmt.Errorf("未找到商品库存信息")
|
||||
}
|
||||
|
||||
|
@ -1059,29 +1088,89 @@ func ReceiveAllotInventory(req *InventoryAllotReceiveReq, c *gin.Context) error
|
|||
stockCommodity[i].StoreName = inventoryAllotOrder.ReceiveStoreName
|
||||
stockCommodity[i].State = InStock
|
||||
stockCommodity[i].StockTime = time.Now()
|
||||
err = begin.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
|
||||
Updates(stockCommodity[i]).Error
|
||||
err = begin.Where("id", stockCommodity[i].ID).Omit("created_at").Save(&stockCommodity[i]).Error
|
||||
//err = begin.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
|
||||
// Updates(stockCommodity[i]).Error
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
return fmt.Errorf("更新商品库存失败:%s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新库存商品数量
|
||||
err = begin.Exec(fmt.Sprintf(
|
||||
"UPDATE erp_stock SET count=count+%d WHERE store_id=%d AND erp_commodity_id=%d",
|
||||
v.Count, inventoryAllotOrder.ReceiveStoreId, v.CommodityId)).Error
|
||||
// 遍历库存调拨商品信息,将商品id相同的非串码商品进行合并,数量累加即可
|
||||
trimAllCommodities := MergeAllCommodities(trimCommodities)
|
||||
for _, v := range trimAllCommodities {
|
||||
var stockCommodity []ErpStockCommodity
|
||||
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
|
||||
"AND state = ? AND imei = ?", v.CommodityId, inventoryAllotOrder.DeliverStoreId, InAllot, v.IMEI).
|
||||
Find(&stockCommodity).Error
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Errorf("update stock err:", err)
|
||||
return err
|
||||
return fmt.Errorf("查询商品库存失败:[%s]", err.Error())
|
||||
}
|
||||
if len(stockCommodity) == 0 {
|
||||
begin.Rollback()
|
||||
return fmt.Errorf("未找到商品库存信息")
|
||||
}
|
||||
|
||||
// 更新库存商品调拨数量
|
||||
// 更新调入门店的库存数量
|
||||
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock WHERE store_id=%d AND erp_commodity_id=%d",
|
||||
inventoryAllotOrder.ReceiveStoreId, v.CommodityId))
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Errorf("exist err:", err)
|
||||
return err
|
||||
}
|
||||
if exist {
|
||||
// 更新调入门店库存商品数量
|
||||
err = begin.Exec(fmt.Sprintf(
|
||||
"UPDATE erp_stock SET count=count+%d WHERE store_id=%d AND erp_commodity_id=%d",
|
||||
v.Count, inventoryAllotOrder.ReceiveStoreId, v.CommodityId)).Error
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Errorf("update stock err:", err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
stock := &ErpStock{
|
||||
StoreId: inventoryAllotOrder.ReceiveStoreId,
|
||||
StoreName: inventoryAllotOrder.ReceiveStoreName,
|
||||
ErpCommodityId: v.CommodityId,
|
||||
ErpCommodityName: v.CommodityName,
|
||||
ErpCategoryId: stockCommodity[0].ErpCategoryId,
|
||||
ErpCategoryName: stockCommodity[0].ErpCategoryName,
|
||||
CommoditySerialNumber: stockCommodity[0].CommoditySerialNumber,
|
||||
IMEIType: v.IMEIType,
|
||||
RetailPrice: stockCommodity[0].RetailPrice,
|
||||
MinRetailPrice: stockCommodity[0].MinRetailPrice,
|
||||
Count: v.Count,
|
||||
DispatchCount: 0,
|
||||
}
|
||||
err = begin.Create(stock).Error
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Errorf("create stock err:", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
//// 更新库存商品数量
|
||||
//err = begin.Exec(fmt.Sprintf(
|
||||
// "UPDATE erp_stock SET count=count+%d WHERE store_id=%d AND erp_commodity_id=%d",
|
||||
// v.Count, inventoryAllotOrder.ReceiveStoreId, v.CommodityId)).Error
|
||||
//if err != nil {
|
||||
// begin.Rollback()
|
||||
// logger.Errorf("update stock err:", err)
|
||||
// return err
|
||||
//}
|
||||
|
||||
// 更新调出门店库存商品调拨数量
|
||||
err = begin.Exec(fmt.Sprintf(
|
||||
"UPDATE erp_stock SET dispatch_count = dispatch_count-%d WHERE store_id=%d AND erp_commodity_id=%d",
|
||||
v.Count, inventoryAllotOrder.DeliverStoreId, v.CommodityId)).Error
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Errorf("update stock err:", err)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -215,6 +215,17 @@ func checkChangeInventoryParam(req *InventoryChangeAddReq, editFlag bool) error
|
|||
if stockCount < int64(item.Count) {
|
||||
return fmt.Errorf("商品[%s]库存数量[%d]少于库存减少数量[%d]", item.CommodityName, stockCount, item.Count)
|
||||
}
|
||||
} else { // 库存增加
|
||||
// 如果该商品是串码商品,判断其串码是否会重复
|
||||
if item.IMEI != "" {
|
||||
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock_commodity WHERE FIND_IN_SET('%s', imei) > 0", item.IMEI))
|
||||
if err != nil {
|
||||
logger.Error("exist sn err")
|
||||
}
|
||||
if exist {
|
||||
return fmt.Errorf("串码有重复项请修改[%s]", item.IMEI)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,7 +356,7 @@ func EditChangeInventory(req *InventoryChangeEditReq) (*ErpInventoryChangeOrder,
|
|||
inventoryChangeOrder.TotalAmount = nTotalAmount
|
||||
|
||||
err = begin.Model(&ErpInventoryChangeOrder{}).Where("id = ?", inventoryChangeOrder.ID).
|
||||
Updates(inventoryChangeOrder).Error
|
||||
Omit("created_at").Save(inventoryChangeOrder).Error
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Error("update change order err:", logger.Field("err", err))
|
||||
|
@ -749,7 +760,7 @@ func handleInventoryReduce(gdb *gorm.DB, changeOrder ErpInventoryChangeOrder) er
|
|||
usedStockCommodityIdList := make(map[uint32][]uint32) // 记录非串码商品已使用的商品库存表主键id
|
||||
// 更新库存数量
|
||||
for i, _ := range trimCommodities {
|
||||
if trimCommodities[i].IMEIType == 2 { // 串码商品
|
||||
if trimCommodities[i].IMEIType == 2 || trimCommodities[i].IMEIType == 3 { // 串码商品
|
||||
if trimCommodities[i].IMEI == "" {
|
||||
return errors.New("串码为空")
|
||||
}
|
||||
|
@ -772,7 +783,10 @@ func handleInventoryReduce(gdb *gorm.DB, changeOrder ErpInventoryChangeOrder) er
|
|||
|
||||
// 更新库存商品状态为:盘点出库
|
||||
err = gdb.Table("erp_stock_commodity").Where("imei = ?", trimCommodities[i].IMEI).
|
||||
Updates(map[string]interface{}{"state": CheckOut}).Error
|
||||
Updates(map[string]interface{}{
|
||||
"state": CheckOut,
|
||||
"updated_at": time.Now(),
|
||||
}).Error
|
||||
if err != nil {
|
||||
logger.Error("handleInventoryReduce update erp_stock_commodity err:",
|
||||
logger.Field("err", err))
|
||||
|
@ -825,13 +839,16 @@ func handleInventoryReduce(gdb *gorm.DB, changeOrder ErpInventoryChangeOrder) er
|
|||
}
|
||||
|
||||
err = gdb.Table("erp_stock_commodity").Where("id = ?", rightId).
|
||||
Updates(map[string]interface{}{"state": CheckOut}).Error // 状态更新为:盘点出库
|
||||
Updates(map[string]interface{}{
|
||||
"state": CheckOut,
|
||||
"updated_at": time.Now(),
|
||||
}).Error // 状态更新为:盘点出库
|
||||
if err != nil {
|
||||
logger.Error("handleInventoryReduce update erp_stock_commodity err:",
|
||||
logger.Field("err", err))
|
||||
return err
|
||||
}
|
||||
usedStockCommodityIdList[trimCommodities[i].ID] = append(usedStockCommodityIdList[trimCommodities[i].ID], rightId)
|
||||
usedStockCommodityIdList[trimCommodities[i].CommodityId] = append(usedStockCommodityIdList[trimCommodities[i].CommodityId], rightId)
|
||||
}
|
||||
|
||||
// 更新库存数量:库存数量-count
|
||||
|
@ -868,7 +885,7 @@ func handleCancelInventoryAdd(gdb *gorm.DB, changeOrder ErpInventoryChangeOrder)
|
|||
|
||||
// 更新库存数量
|
||||
for i, _ := range trimCommodities {
|
||||
if trimCommodities[i].IMEIType == 2 { // 串码商品
|
||||
if trimCommodities[i].IMEIType == 2 || trimCommodities[i].IMEIType == 3 { // 串码商品
|
||||
if trimCommodities[i].IMEI == "" {
|
||||
return errors.New("串码为空")
|
||||
}
|
||||
|
@ -953,7 +970,7 @@ func handleCancelInventoryReduce(gdb *gorm.DB, changeOrder ErpInventoryChangeOrd
|
|||
usedStockCommodityIdList := make(map[uint32][]uint32) // 记录非串码商品已使用的商品库存表主键id
|
||||
// 更新库存数量
|
||||
for i, _ := range trimCommodities {
|
||||
if trimCommodities[i].IMEIType == 2 { // 串码商品
|
||||
if trimCommodities[i].IMEIType == 2 || trimCommodities[i].IMEIType == 3 { // 串码商品
|
||||
if trimCommodities[i].IMEI == "" {
|
||||
return errors.New("串码为空")
|
||||
}
|
||||
|
@ -1022,7 +1039,7 @@ func handleCancelInventoryReduce(gdb *gorm.DB, changeOrder ErpInventoryChangeOrd
|
|||
return err
|
||||
}
|
||||
|
||||
usedStockCommodityIdList[trimCommodities[i].ID] = append(usedStockCommodityIdList[trimCommodities[i].ID], rightId)
|
||||
usedStockCommodityIdList[trimCommodities[i].CommodityId] = append(usedStockCommodityIdList[trimCommodities[i].CommodityId], rightId)
|
||||
}
|
||||
|
||||
// 更新库存数量:库存数量+count
|
||||
|
|
|
@ -213,6 +213,16 @@ func CheckProductInventoryParam(req *ProductInventoryAddReq, editFlag bool) erro
|
|||
} else {
|
||||
_, ok := IMEICommodityMap[item.IMEI]
|
||||
if !ok {
|
||||
// 如果该商品是串码商品,判断其串码是否会重复
|
||||
if item.IMEI != "" {
|
||||
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock_commodity WHERE FIND_IN_SET('%s', imei) > 0", item.IMEI))
|
||||
if err != nil {
|
||||
logger.Error("exist sn err")
|
||||
}
|
||||
if exist {
|
||||
return fmt.Errorf("串码有重复项请修改[%s]", item.IMEI)
|
||||
}
|
||||
}
|
||||
IMEICommodityMap[item.IMEI] = true
|
||||
} else {
|
||||
return fmt.Errorf("串码[%s]有重复项", item.IMEI)
|
||||
|
@ -329,7 +339,7 @@ func EditProductInventory(req *ProductInventoryEditReq) (*ErpInventoryProductOrd
|
|||
inventoryProductOrder.TotalAmount = nTotalAmount
|
||||
|
||||
err = begin.Model(&ErpInventoryProductOrder{}).Where("id = ?", inventoryProductOrder.ID).
|
||||
Updates(inventoryProductOrder).Error
|
||||
Omit("created_at").Save(inventoryProductOrder).Error
|
||||
if err != nil {
|
||||
begin.Rollback()
|
||||
logger.Error("update erp_order err:", logger.Field("err", err))
|
||||
|
@ -526,7 +536,7 @@ func cancelProductAuditAndUpdateStock(gdb *gorm.DB, productOrder ErpInventoryPro
|
|||
|
||||
// 更新库存数量
|
||||
for i, _ := range commodities {
|
||||
if commodities[i].IMEIType == 2 { // 串码商品
|
||||
if commodities[i].IMEIType == 2 || commodities[i].IMEIType == 3 { // 串码商品
|
||||
if commodities[i].IMEI == "" {
|
||||
return errors.New("串码为空")
|
||||
}
|
||||
|
|
|
@ -388,6 +388,7 @@ func (m *InventoryReportByProductReq) ReportByProductList(c *gin.Context) (*Inve
|
|||
resp.TotalEffectiveAmount = sumData.TotalEffectiveAmount
|
||||
resp.TotalTransferAmount = sumData.TotalTransferAmount
|
||||
resp.TotalAmount = resp.TotalEffectiveAmount + resp.TotalTransferAmount
|
||||
resp.TotalAmount = math.Round(resp.TotalAmount*100) / 100
|
||||
resp.Total = uint32(len(reportList))
|
||||
resp.List = reportList
|
||||
|
||||
|
|
|
@ -7,6 +7,36 @@ import (
|
|||
"go-admin/tools"
|
||||
)
|
||||
|
||||
const (
|
||||
PurchasePrice = "erp:stock:stockDetails:list:purchasePrice" // 库存详情-入库采购价
|
||||
EmployeeCostPrice = "erp:stock:stockDetails:list:employeeCostPrice" // 库存详情-入库员工成本价
|
||||
|
||||
PriceMenu = "erp:purchase:purchaseDetails:list:price" // 采购/退货价
|
||||
EmployeePriceMenu = "erp:purchase:purchaseDetails:list:employee_price" // 员工成本价
|
||||
DifferencePriceMenu = "erp:purchase:purchaseDetails:list:difference_price" // 差额
|
||||
|
||||
SalesProfitMenu = "erp:retail:storeMangement:salesProfit" // 门店经营-销售毛利
|
||||
StaffProfitMenu = "erp:retail:storeMangement:staffProfit" // 门店经营-员工毛利
|
||||
|
||||
SalesCostMenu = "erp:retail:retailRemittance:salesCost" // 商品零售毛利汇总-销售成本
|
||||
EmployeeCostMenu = "erp:retail:retailRemittance:staffCost" // 商品零售毛利汇总-员工成本
|
||||
SalesMarginMenu = "erp:retail:retailRemittance:salesMargin" // 商品零售毛利汇总-销售毛利
|
||||
EmployeeMarginMenu = "erp:retail:retailRemittance:employeeMargin" // 商品零售毛利汇总-员工毛利
|
||||
GrossMarginsMenu = "erp:retail:retailRemittance:grossMargins" // 商品零售毛利汇总-销售毛利率
|
||||
EmployeeGrossMarginsMenu = "erp:retail:retailRemittance:employeeGrossMargins" // 商品零售毛利汇总-员工毛利率
|
||||
|
||||
DetailWholesalePriceMenu = "erp:retail:reportForm:retailDetails:wholesalePrice" // 零售明细-采购单价
|
||||
DetailEmployeeCostMenu = "erp:retail:reportForm:retailDetails:staffPrice" // 零售明细-员工成本价
|
||||
DetailSalesProfitMenu = "erp:retail:reportForm:retailDetails:salesProfit" // 零售明细-销售毛利
|
||||
DetailStaffProfitMenu = "erp:retail:reportForm:retailDetails:staffProfit" // 零售明细-员工毛利
|
||||
DetailTotalSalesProfitMenu = "erp:retail:reportForm:retailDetails:totalSales" // 零售明细-订单总销售毛利
|
||||
DetailTotalStaffProfitMenu = "erp:retail:reportForm:retailDetails:totalStaff" // 零售明细-订单总员工毛利
|
||||
DetailSalesProfitPerMenu = "erp:retail:reportForm:retailDetails:salesProfitPer" // 零售明细-销售毛利提成
|
||||
DetailStaffProfitPerMenu = "erp:retail:reportForm:retailDetails:staffProfitPer" // 零售明细-员工毛利提成
|
||||
DetailSalesmanPerMenu = "erp:retail:reportForm:retailDetails:salesmanPer" // 零售明细-销售员提成
|
||||
DetailStorePerMenu = "erp:retail:reportForm:retailDetails:storePer" // 零售明细-门店提成
|
||||
)
|
||||
|
||||
type Menu struct {
|
||||
MenuId int `json:"menuId" gorm:"primary_key;AUTO_INCREMENT"`
|
||||
MenuName string `json:"menuName" gorm:"size:128;"`
|
||||
|
@ -262,6 +292,7 @@ func (e *Menu) Get() (Menus []Menu, err error) {
|
|||
}
|
||||
|
||||
if err = table.Order("sort").Find(&Menus).Error; err != nil {
|
||||
//if err = table.Where("visible = 0").Order("sort").Find(&Menus).Error; err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"go-admin/tools"
|
||||
"go-admin/tools/config"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -1553,9 +1554,10 @@ func (m *ExpressNoInfo) SetStore() {
|
|||
}
|
||||
}
|
||||
|
||||
// FundRecordListReq 财务统计入参
|
||||
type FundRecordListReq struct {
|
||||
Uid uint64 `json:"uid" `
|
||||
FundType string `json:"fund_type"` // -member_gold -member_platinum -member_black_gold
|
||||
FundType string `json:"fund_type"`
|
||||
TransactionId string `json:"transaction_id"` // 支付单号
|
||||
OutTradeNo string `json:"out_trade_no"`
|
||||
RefundId string `json:"refund_id"`
|
||||
|
@ -1564,9 +1566,18 @@ type FundRecordListReq struct {
|
|||
EndTime time.Time `json:"end_time"` // 结束时间
|
||||
Page int `json:"pageIndex"`
|
||||
PageSize int `json:"pageSize"`
|
||||
IsExport uint32 `json:"is_export"` // 1-导出
|
||||
}
|
||||
|
||||
func (m *FundRecordListReq) List() ([]FundRecord, int64, error) {
|
||||
type FundRecordListResp struct {
|
||||
List []FundRecord `json:"list"`
|
||||
Total int64 `json:"total"` // 总条数
|
||||
PageIndex int `json:"pageIndex"` // 页码
|
||||
PageSize int `json:"pageSize"` // 每页展示条数
|
||||
ExportUrl string `json:"export_url"`
|
||||
}
|
||||
|
||||
func (m *FundRecordListReq) List() ([]FundRecord, int64, string, error) {
|
||||
var fundRecords []FundRecord
|
||||
qs := orm.Eloquent.Table("fund_record")
|
||||
|
||||
|
@ -1602,7 +1613,7 @@ func (m *FundRecordListReq) List() ([]FundRecord, int64, error) {
|
|||
err := qs.Count(&count).Error
|
||||
if err != nil {
|
||||
logger.Errorf("err:", logger.Field("err", err))
|
||||
return fundRecords, 0, err
|
||||
return fundRecords, 0, "", err
|
||||
}
|
||||
if m.PageSize == 0 {
|
||||
m.PageSize = 10
|
||||
|
@ -1613,13 +1624,146 @@ func (m *FundRecordListReq) List() ([]FundRecord, int64, error) {
|
|||
if page < 0 {
|
||||
page = 0
|
||||
}
|
||||
err = qs.Order("created_at DESC").Offset(page * pageSize).Limit(pageSize).Find(&fundRecords).Error
|
||||
if err != nil {
|
||||
logger.Errorf("err:", logger.Field("err", err))
|
||||
return fundRecords, 0, err
|
||||
|
||||
if m.IsExport == 1 { // 导出excel
|
||||
err = qs.Order("created_at DESC").Find(&fundRecords).Error
|
||||
if err != nil {
|
||||
logger.Errorf("err:", logger.Field("err", err))
|
||||
return fundRecords, 0, "", err
|
||||
}
|
||||
|
||||
exportUrl, err := fundRecordListExport(fundRecords)
|
||||
if err != nil {
|
||||
logger.Errorf("err:", logger.Field("err", err))
|
||||
return fundRecords, 0, "", err
|
||||
}
|
||||
|
||||
return nil, 0, exportUrl, nil
|
||||
} else {
|
||||
err = qs.Order("created_at DESC").Offset(page * pageSize).Limit(pageSize).Find(&fundRecords).Error
|
||||
if err != nil {
|
||||
logger.Errorf("err:", logger.Field("err", err))
|
||||
return fundRecords, 0, "", err
|
||||
}
|
||||
}
|
||||
|
||||
return fundRecords, count, nil
|
||||
return fundRecords, count, "", nil
|
||||
}
|
||||
|
||||
// TranslateFundType 将fund_type转换为对应的字符
|
||||
func TranslateFundType(fundType string) string {
|
||||
fundTypeMap := map[string]string{
|
||||
"member_fee": "会员费",
|
||||
"buy_goods_refund": "商品退货",
|
||||
"buy_goods": "商品购买",
|
||||
"buy_goods_cancel": "商品取消",
|
||||
"recycle_card": "回收卡带",
|
||||
"postage_package_fee": "购买运费包",
|
||||
"member_deposit": "押金",
|
||||
"upgrade_member": "升级会员",
|
||||
"member_expire_delay": "滞纳金",
|
||||
"express_fee": "邮费",
|
||||
"deposit_refund": "退押金",
|
||||
"express_fee_refund": "退邮费",
|
||||
"downgrade_renewal": "降级续费",
|
||||
}
|
||||
|
||||
if val, ok := fundTypeMap[fundType]; ok {
|
||||
return val
|
||||
}
|
||||
return "未知类型"
|
||||
}
|
||||
|
||||
// ConvertAmount 将Amount转换为格式化字符串
|
||||
func ConvertAmount(amount int64) string {
|
||||
// 转换为以分为单位的小数,保留两位小数
|
||||
convertedAmount := float64(amount) / 100.0
|
||||
sign := "+"
|
||||
if convertedAmount < 0 {
|
||||
sign = "-"
|
||||
convertedAmount = -convertedAmount
|
||||
}
|
||||
return sign + strconv.FormatFloat(convertedAmount, 'f', 2, 64)
|
||||
}
|
||||
|
||||
// fundRecordListExport 导出财务统计数据
|
||||
func fundRecordListExport(list []FundRecord) (string, error) {
|
||||
file := excelize.NewFile()
|
||||
fSheet := "Sheet1"
|
||||
|
||||
url := ExportUrl
|
||||
fileName := time.Now().Format(TimeFormat) + "财务统计" + ".xlsx"
|
||||
fmt.Println("url fileName:", url+fileName)
|
||||
|
||||
title := []interface{}{"用户ID", "类型", "金额", "商户单号", "交易单号", "退款单号", "付款单号", "创建时间", "备注"}
|
||||
|
||||
for i, _ := range title {
|
||||
cell, _ := excelize.CoordinatesToCellName(1+i, 1)
|
||||
err := file.SetCellValue(fSheet, cell, title[i])
|
||||
if err != nil {
|
||||
logger.Errorf("file set value err:", err)
|
||||
}
|
||||
}
|
||||
|
||||
var row []interface{}
|
||||
nExcelStartRow := 0
|
||||
for rowId := 0; rowId < len(list); rowId++ {
|
||||
formattedTime := list[rowId].CreatedAt.Format(QueryTimeFormat)
|
||||
row = []interface{}{
|
||||
list[rowId].Uid,
|
||||
TranslateFundType(list[rowId].FundType),
|
||||
ConvertAmount(list[rowId].Amount),
|
||||
list[rowId].OutTradeNo,
|
||||
list[rowId].TransactionId,
|
||||
list[rowId].RefundId,
|
||||
list[rowId].PaymentNo,
|
||||
formattedTime,
|
||||
list[rowId].Remark,
|
||||
}
|
||||
|
||||
for j, _ := range row {
|
||||
cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2)
|
||||
err := file.SetCellValue(fSheet, cell, row[j])
|
||||
if err != nil {
|
||||
logger.Error("file set value err:", logger.Field("err", err))
|
||||
}
|
||||
}
|
||||
nExcelStartRow++
|
||||
}
|
||||
|
||||
// 设置所有单元格的样式: 居中、加边框
|
||||
style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"},
|
||||
"border":[{"type":"left","color":"000000","style":1},
|
||||
{"type":"top","color":"000000","style":1},
|
||||
{"type":"right","color":"000000","style":1},
|
||||
{"type":"bottom","color":"000000","style":1}]}`)
|
||||
|
||||
//设置单元格高度
|
||||
file.SetRowHeight("Sheet1", 1, 20)
|
||||
|
||||
// 设置单元格大小
|
||||
file.SetColWidth("Sheet1", "A", "A", 10)
|
||||
file.SetColWidth("Sheet1", "B", "B", 13)
|
||||
file.SetColWidth("Sheet1", "C", "C", 10)
|
||||
file.SetColWidth("Sheet1", "D", "D", 16)
|
||||
file.SetColWidth("Sheet1", "E", "E", 30)
|
||||
file.SetColWidth("Sheet1", "F", "F", 30)
|
||||
file.SetColWidth("Sheet1", "G", "G", 30)
|
||||
file.SetColWidth("Sheet1", "H", "H", 25)
|
||||
file.SetColWidth("Sheet1", "I", "I", 13)
|
||||
|
||||
var endRow string
|
||||
endRow = fmt.Sprintf("I"+"%d", nExcelStartRow+1)
|
||||
|
||||
// 应用样式到整个表格
|
||||
_ = file.SetCellStyle("Sheet1", "A1", endRow, style)
|
||||
|
||||
fmt.Println("save fileName:", config.ExportConfig.Path+fileName)
|
||||
if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
return url + fileName, nil
|
||||
}
|
||||
|
||||
type CooperativeOrderReq struct {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
orm "go-admin/common/global"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
|
@ -23,13 +23,16 @@ func GetSmsNumberRemaining() int {
|
|||
now := time.Now()
|
||||
year, month, _ := now.Date()
|
||||
|
||||
var totalUsed sql.NullInt64
|
||||
nTotalUsed := struct {
|
||||
TotalUsed int `json:"total_used"`
|
||||
}{}
|
||||
|
||||
// 查询当前年份和月份的短信发送总数
|
||||
if err := orm.Eloquent.Debug().Model(&SmsSummary{}).
|
||||
Where("year = ? AND month = ?", year, int(month)).
|
||||
Select("SUM(used)").
|
||||
Scan(&totalUsed).Error; err != nil {
|
||||
Select("SUM(used) as total_used").
|
||||
Scan(&nTotalUsed).Error; err != nil {
|
||||
fmt.Println("SQL Error:", err) // 打印 SQL 错误信息
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@ -39,7 +42,7 @@ func GetSmsNumberRemaining() int {
|
|||
nMonthlyLimit = monthlyLimit
|
||||
}
|
||||
|
||||
remaining := nMonthlyLimit - int(totalUsed.Int64)
|
||||
remaining := nMonthlyLimit - nTotalUsed.TotalUsed
|
||||
|
||||
return remaining
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/xuri/excelize/v2"
|
||||
"go-admin/logger"
|
||||
"go-admin/tools/config"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
||||
"sort"
|
||||
|
@ -68,6 +71,8 @@ type SysUserB struct {
|
|||
StoreList []StoreInfo `json:"store_list" gorm:"-" ` // 有效门店列表
|
||||
SalesCommRate float64 `json:"sales_comm_rate"` // 销售提成比例
|
||||
Uid uint32 `json:"uid" gorm:"column:uid;unique_index"` // 用户uid todo 待添加
|
||||
ShopperCode string `json:"shopper_code" gorm:"-"` // 店员兑换码
|
||||
|
||||
BaseModel
|
||||
|
||||
DataScope string `gorm:"-" json:"dataScope"`
|
||||
|
@ -108,6 +113,7 @@ type InsertSysUserReq struct {
|
|||
SalesCommRate string `json:"sales_comm_rate"` // 销售提成比例
|
||||
StoreList []StoreInfo `json:"store_list"` // 有效门店
|
||||
Uid uint32 `json:"uid"` // 用户uid
|
||||
ShopperCode string `json:"shopper_code"` // 店员兑换码
|
||||
}
|
||||
|
||||
func (SysUser) TableName() string {
|
||||
|
@ -257,17 +263,35 @@ func (e *SysUser) GetList() (SysUserView []SysUserView, err error) {
|
|||
}
|
||||
|
||||
type SysUserListResp struct {
|
||||
Total int `json:"count"` // 总条数
|
||||
PageIndex int `json:"pageIndex"` // 页码
|
||||
PageSize int `json:"pageSize"` // 页面条数
|
||||
List []SysUserPage `json:"list"` // 采购报表信息
|
||||
Total int `json:"count"` // 总条数
|
||||
PageIndex int `json:"pageIndex"` // 页码
|
||||
PageSize int `json:"pageSize"` // 页面条数
|
||||
ExportUrl string `json:"export_url"` // 导出excel路径
|
||||
List []SysUserPage `json:"list"` // 采购报表信息
|
||||
}
|
||||
|
||||
func (e *SysUser) GetPage(pageSize int, pageIndex int) ([]SysUserPage, int, error) {
|
||||
func (e *SysUser) GetPage(pageSize int, pageIndex int, exportFlag int) ([]SysUserPage, int, string, error) {
|
||||
if e.ShopperCode != "" {
|
||||
var shopperCode ShopperPromotionCode
|
||||
err := orm.Eloquent.Table("shopper_promotion_code").Where("code = ?", e.ShopperCode).Find(&shopperCode).Error
|
||||
if err != nil {
|
||||
logger.Error("query shopper_promotion_code err:", logger.Field("err", err))
|
||||
return nil, 0, "", err
|
||||
}
|
||||
if shopperCode.ID == 0 {
|
||||
return nil, 0, "", nil
|
||||
} else {
|
||||
e.Uid = shopperCode.Uid
|
||||
}
|
||||
}
|
||||
|
||||
var doc []SysUserPage
|
||||
table := orm.Eloquent.Select("sys_user.*,sys_dept.dept_name").Table(e.TableName())
|
||||
table = table.Joins("left join sys_dept on sys_dept.dept_id = sys_user.dept_id") //es := orm.Eloquent.Select("sys_user.*,sys_dept.dept_name").Table(e.TableName()) //es = table.Joins("left join sys_dept on sys_dept.dept_id = sys_user.dept_id")
|
||||
|
||||
if e.Uid != 0 {
|
||||
table = table.Where("uid = ?", e.Uid)
|
||||
}
|
||||
if e.Username != "" {
|
||||
table = table.Where("username = ?", e.Username)
|
||||
}
|
||||
|
@ -300,7 +324,7 @@ func (e *SysUser) GetPage(pageSize int, pageIndex int) ([]SysUserPage, int, erro
|
|||
dataPermission.UserId, _ = tools.StringToInt(e.DataScope)
|
||||
table, err := dataPermission.GetDataScope(e.TableName(), table)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, 0, "", err
|
||||
}
|
||||
|
||||
es := table
|
||||
|
@ -308,18 +332,25 @@ func (e *SysUser) GetPage(pageSize int, pageIndex int) ([]SysUserPage, int, erro
|
|||
err = es.Count(&count).Error
|
||||
if err != nil {
|
||||
//logger.Error("count err:", err)
|
||||
return nil, 0, err
|
||||
return nil, 0, "", err
|
||||
}
|
||||
|
||||
//if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Order("sys_user.created_at DESC").Offset(-1).Limit(-1).Total(&count).Error; err != nil {
|
||||
// return nil, 0, err
|
||||
//}
|
||||
|
||||
if err = table.Order("sys_user.user_id DESC").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil {
|
||||
return nil, 0, err
|
||||
if exportFlag == 1 { // 导出excel
|
||||
if err = table.Order("sys_user.user_id DESC").Find(&doc).Error; err != nil {
|
||||
return nil, 0, "", err
|
||||
}
|
||||
} else {
|
||||
if err = table.Order("sys_user.user_id DESC").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil {
|
||||
return nil, 0, "", err
|
||||
}
|
||||
}
|
||||
|
||||
var resp []SysUserPage
|
||||
var exportUrl string
|
||||
// 反序列化 StoreData
|
||||
for i, v := range doc {
|
||||
if doc[i].StoreData != "" {
|
||||
|
@ -340,10 +371,148 @@ func (e *SysUser) GetPage(pageSize int, pageIndex int) ([]SysUserPage, int, erro
|
|||
}
|
||||
}
|
||||
|
||||
if doc[i].Uid != 0 {
|
||||
// 添加店员兑换码
|
||||
var shopperCode ShopperPromotionCode
|
||||
err = orm.Eloquent.Table("shopper_promotion_code").Where("uid = ?", doc[i].Uid).Find(&shopperCode).Error
|
||||
if err != nil {
|
||||
logger.Error("query shopper_promotion_code err:", logger.Field("err", err))
|
||||
}
|
||||
doc[i].ShopperCode = shopperCode.Code
|
||||
}
|
||||
|
||||
resp = append(resp, doc[i])
|
||||
}
|
||||
|
||||
return resp, int(count), nil
|
||||
if exportFlag == 1 { // 导出excel
|
||||
exportUrl, err = sysUserExport(resp)
|
||||
if err != nil {
|
||||
return nil, 0, "", err
|
||||
}
|
||||
resp = nil
|
||||
}
|
||||
|
||||
return resp, int(count), exportUrl, nil
|
||||
}
|
||||
|
||||
func getValidStoreNames(storeList []StoreInfo) (string, error) {
|
||||
var validStoreNames []string
|
||||
currentTime := time.Now()
|
||||
|
||||
for _, store := range storeList {
|
||||
expireTime, err := time.Parse(StoreDateTimeFormat, store.ExpireTime)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid expire time format for store ID %d: %v", store.StoreID, err)
|
||||
}
|
||||
if expireTime.After(currentTime) {
|
||||
validStoreNames = append(validStoreNames, store.StoreName)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(validStoreNames, ","), nil
|
||||
}
|
||||
|
||||
// 导出系统用户列表
|
||||
func sysUserExport(req []SysUserPage) (string, error) {
|
||||
file := excelize.NewFile()
|
||||
fSheet := "Sheet1"
|
||||
|
||||
url := ExportUrl
|
||||
fileName := time.Now().Format(TimeFormat) + "系统用户" + ".xlsx"
|
||||
fmt.Println("url fileName:", url+fileName)
|
||||
|
||||
// 组合标题栏数据
|
||||
title := []interface{}{"用户名称", "用户昵称", "角色", "合作商", "门店", "手机号", "店员识别码", "状态"}
|
||||
for i, _ := range title {
|
||||
cell, _ := excelize.CoordinatesToCellName(1+i, 1)
|
||||
err := file.SetCellValue(fSheet, cell, title[i])
|
||||
if err != nil {
|
||||
logger.Errorf("file set value err:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 查询系统角色
|
||||
var doc []SysRole
|
||||
err := orm.Eloquent.Table("sys_role").Find(&doc).Error
|
||||
if err != nil {
|
||||
logger.Errorf("query sys_role error:", err)
|
||||
}
|
||||
roleMap := make(map[int]string)
|
||||
for _, item := range doc {
|
||||
roleMap[item.RoleId] = item.RoleName
|
||||
}
|
||||
|
||||
var row []interface{}
|
||||
nExcelStartRow := 0
|
||||
for _, userData := range req {
|
||||
// 门店
|
||||
storeName, _ := getValidStoreNames(userData.StoreList)
|
||||
|
||||
var status string
|
||||
if userData.Status == "0" {
|
||||
status = "正常"
|
||||
} else {
|
||||
status = "停用"
|
||||
}
|
||||
|
||||
row = []interface{}{
|
||||
userData.UserName.Username, // 用户名称
|
||||
userData.NickName, // 用户昵称
|
||||
roleMap[userData.RoleId], // 角色
|
||||
userData.CooperativeName, // 合作商
|
||||
storeName, // 门店
|
||||
userData.Phone, // 手机号
|
||||
userData.ShopperCode, // 店员识别码
|
||||
status, // 状态
|
||||
}
|
||||
|
||||
for j, _ := range row {
|
||||
cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2)
|
||||
err := file.SetCellValue(fSheet, cell, row[j])
|
||||
if err != nil {
|
||||
logger.Error("file set value err:", logger.Field("err", err))
|
||||
}
|
||||
}
|
||||
nExcelStartRow++
|
||||
}
|
||||
|
||||
// 设置所有单元格的样式: 居中、加边框
|
||||
style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"},
|
||||
"border":[{"type":"left","color":"000000","style":1},
|
||||
{"type":"top","color":"000000","style":1},
|
||||
{"type":"right","color":"000000","style":1},
|
||||
{"type":"bottom","color":"000000","style":1}]}`)
|
||||
|
||||
// 设置单元格的样式: 居中、加边框、自动换行
|
||||
style1, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center","wrap_text":true},
|
||||
"border":[{"type":"left","color":"000000","style":1},
|
||||
{"type":"top","color":"000000","style":1},
|
||||
{"type":"right","color":"000000","style":1},
|
||||
{"type":"bottom","color":"000000","style":1}]}`)
|
||||
|
||||
//设置单元格高度
|
||||
file.SetRowHeight("Sheet1", 1, 20)
|
||||
|
||||
// 设置单元格大小
|
||||
file.SetColWidth("Sheet1", "B", "B", 15)
|
||||
file.SetColWidth("Sheet1", "C", "C", 15)
|
||||
file.SetColWidth("Sheet1", "D", "D", 15)
|
||||
file.SetColWidth("Sheet1", "E", "E", 30)
|
||||
file.SetColWidth("Sheet1", "F", "F", 15)
|
||||
file.SetColWidth("Sheet1", "G", "G", 15)
|
||||
|
||||
endRow := fmt.Sprintf("H"+"%d", nExcelStartRow+2)
|
||||
// 应用样式到整个表格
|
||||
_ = file.SetCellStyle("Sheet1", "A1", endRow, style)
|
||||
|
||||
endRow1 := fmt.Sprintf("E%d", nExcelStartRow+2)
|
||||
_ = file.SetCellStyle("Sheet1", "E2", endRow1, style1)
|
||||
|
||||
fmt.Println("save fileName:", config.ExportConfig.Path+fileName)
|
||||
if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
return url + fileName, nil
|
||||
}
|
||||
|
||||
// 反序列化 StoreData
|
||||
|
@ -435,6 +604,13 @@ func (e *SysUser) Update(begin *gorm.DB, id int) (update SysUser, err error) {
|
|||
if err = begin.Table(e.TableName()).Model(&update).Updates(&e).Error; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if e.Uid == 0 {
|
||||
if err = begin.Table(e.TableName()).Model(&update).UpdateColumn("uid", 0).Error; err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -472,6 +648,13 @@ func GetUserById(id uint32) *SysUserB {
|
|||
return u
|
||||
}
|
||||
|
||||
func GetSysUserById(id uint32) *SysUser {
|
||||
var u = new(SysUser)
|
||||
orm.Eloquent.Table("sys_user").Where("user_id", id).First(u)
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateUserType 更新uid的user_type为2
|
||||
func UpdateUserType(begin *gorm.DB, uid, nType, roleId uint32) error {
|
||||
// 更新库存表
|
||||
|
@ -596,3 +779,137 @@ func GetUserEffectiveStoreById(id uint32) ([]StoreInfo, error) {
|
|||
|
||||
return validStores, nil
|
||||
}
|
||||
|
||||
// AddShopperCode 添加店员兑换码
|
||||
func AddShopperCode(req InsertSysUserReq, begin *gorm.DB) error {
|
||||
// 获取有效门店id
|
||||
now := time.Now()
|
||||
// 过滤掉过期的门店
|
||||
validStores := make([]StoreInfo, 0)
|
||||
for _, store := range req.StoreList {
|
||||
expireTime, err := time.Parse(StoreDateTimeFormat, store.ExpireTime)
|
||||
if err != nil {
|
||||
log.Println("Error parsing time:", err, "ExpireTime:", store.ExpireTime)
|
||||
continue
|
||||
}
|
||||
|
||||
// 包含当天有效时间
|
||||
expireTime = expireTime.Add(24*time.Hour - time.Second)
|
||||
if expireTime.After(now) {
|
||||
validStores = append(validStores, store)
|
||||
}
|
||||
}
|
||||
|
||||
if len(validStores) == 0 {
|
||||
return errors.New("设置兑换码失败,无有效门店")
|
||||
}
|
||||
|
||||
// 按有效时间和 store_id 排序
|
||||
sort.Slice(validStores, func(i, j int) bool {
|
||||
timeI, _ := time.Parse(StoreDateTimeFormat, validStores[i].ExpireTime)
|
||||
timeJ, _ := time.Parse(StoreDateTimeFormat, validStores[j].ExpireTime)
|
||||
|
||||
if timeI.Equal(timeJ) {
|
||||
return validStores[i].StoreID < validStores[j].StoreID
|
||||
}
|
||||
return timeI.Before(timeJ)
|
||||
})
|
||||
|
||||
var shopperCode ShopperPromotionCode
|
||||
shopperCode.Code = req.ShopperCode
|
||||
shopperCode.Uid = req.Uid
|
||||
shopperCode.State = 2
|
||||
shopperCode.StoreId = uint32(validStores[0].StoreID)
|
||||
if err := begin.Table("shopper_promotion_code").Create(&shopperCode).Error; err != nil {
|
||||
logger.Error("create shopper_promotion_code err:", logger.Field("err", err))
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateShopperCode 更新店员兑换码
|
||||
func UpdateShopperCode(req InsertSysUserReq, begin *gorm.DB, sysInfo *SysUser) error {
|
||||
if req.Uid == sysInfo.Uid && req.ShopperCode == sysInfo.ShopperCode { // 兑换码没变化
|
||||
return nil
|
||||
}
|
||||
|
||||
var oldShopperCode ShopperPromotionCode
|
||||
orm.Eloquent.Debug().Model(&ShopperPromotionCode{}).
|
||||
Where("code = ? and state = ?", req.ShopperCode, 2).Find(&oldShopperCode)
|
||||
if oldShopperCode.ID != 0 && oldShopperCode.Uid != sysInfo.Uid {
|
||||
return errors.New(fmt.Sprintf("[%s]与已有店员识别码重复", req.ShopperCode))
|
||||
}
|
||||
|
||||
// 获取有效门店id
|
||||
now := time.Now()
|
||||
// 过滤掉过期的门店
|
||||
validStores := make([]StoreInfo, 0)
|
||||
for _, store := range req.StoreList {
|
||||
expireTime, err := time.Parse(StoreDateTimeFormat, store.ExpireTime)
|
||||
if err != nil {
|
||||
log.Println("Error parsing time:", err, "ExpireTime:", store.ExpireTime)
|
||||
continue
|
||||
}
|
||||
|
||||
// 包含当天有效时间
|
||||
expireTime = expireTime.Add(24*time.Hour - time.Second)
|
||||
if expireTime.After(now) {
|
||||
validStores = append(validStores, store)
|
||||
}
|
||||
}
|
||||
|
||||
if len(validStores) == 0 {
|
||||
return errors.New("设置兑换码失败,无有效门店")
|
||||
}
|
||||
|
||||
// 按有效时间和 store_id 排序
|
||||
sort.Slice(validStores, func(i, j int) bool {
|
||||
timeI, _ := time.Parse(StoreDateTimeFormat, validStores[i].ExpireTime)
|
||||
timeJ, _ := time.Parse(StoreDateTimeFormat, validStores[j].ExpireTime)
|
||||
|
||||
if timeI.Equal(timeJ) {
|
||||
return validStores[i].StoreID < validStores[j].StoreID
|
||||
}
|
||||
return timeI.Before(timeJ)
|
||||
})
|
||||
|
||||
// 删除原有的兑换码
|
||||
if sysInfo.Uid != 0 && sysInfo.ShopperCode != "" {
|
||||
err := orm.Eloquent.Table("shopper_promotion_code").Where("uid = ?", sysInfo.Uid).Delete(&ShopperPromotionCode{}).Error
|
||||
if err != nil {
|
||||
logger.Error("delete shopper_promotion_code err:", logger.Field("err", err))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 删除新配置的uid的兑换码
|
||||
err := orm.Eloquent.Table("shopper_promotion_code").Where("uid = ?", req.Uid).Delete(&ShopperPromotionCode{}).Error
|
||||
if err != nil {
|
||||
logger.Error("delete shopper_promotion_code err:", logger.Field("err", err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 添加新的兑换码
|
||||
var shopperCode ShopperPromotionCode
|
||||
shopperCode.Code = req.ShopperCode
|
||||
shopperCode.Uid = req.Uid
|
||||
shopperCode.State = 2
|
||||
shopperCode.StoreId = uint32(validStores[0].StoreID)
|
||||
if err := begin.Table("shopper_promotion_code").Create(&shopperCode).Error; err != nil {
|
||||
logger.Error("create shopper_promotion_code err:", logger.Field("err", err))
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsShopperCodeExists 查询兑换码是否重复
|
||||
func IsShopperCodeExists(code string) bool {
|
||||
var count int64
|
||||
orm.Eloquent.Debug().Model(&ShopperPromotionCode{}).
|
||||
Where("code = ? and state = ?", code, 2).
|
||||
Count(&count)
|
||||
|
||||
return count > 0
|
||||
}
|
||||
|
|
|
@ -133,6 +133,8 @@ const StoreDateTimeFormat = "2006.01.02"
|
|||
|
||||
const (
|
||||
ExportUrl = "https://admin.deovo.com/load/export/"
|
||||
//ExportUrl = "https://dev.admin.deovo.com/load/export/" // dev环境
|
||||
//ExportUrl = "/Users/max/Documents/" // 本地环境
|
||||
)
|
||||
|
||||
type UserInvite struct {
|
||||
|
|
|
@ -26,7 +26,7 @@ func registerUserManageUnAuthRouter(v1 *gin.RouterGroup) {
|
|||
userInfo.POST("/add_assistant", usermanage.UserAddAssistant)
|
||||
userInfo.POST("/assistant_del", usermanage.UserAssistantDel)
|
||||
userInfo.POST("/invite_list", usermanage.UserInviteList)
|
||||
userInfo.POST("/cancel_members", usermanage.CancelMembers)
|
||||
userInfo.POST("/cancel_members", usermanage.CancelMembers) // 取消租卡会员
|
||||
|
||||
userInfo.POST("/user_derive", usermanage.ExportDataUserMember)
|
||||
userInfo.POST("/deposit_refund/list", usermanage.UserDepositRefundRecordList) // 保证金审核列表
|
||||
|
|
|
@ -290,7 +290,7 @@ func _1599190683670Test(db *gorm.DB, version string) error {
|
|||
}
|
||||
|
||||
list8 := []models.SysUser{
|
||||
{SysUserId: models.SysUserId{1}, LoginM: models.LoginM{models.UserName{"admin"}, models.PassWord{"$2a$10$cKFFTCzGOvaIHHJY2K45Zuwt8TD6oPzYi4s5MzYIBAWCLL6ZhouP2"}}, SysUserB: models.SysUserB{"zhangwj", "13818888888", 1, "", "", "0", "1@qq.com", 1, 1, "1", "1", "", "0", 1, "总店", 1, "迪为", 1, "", []models.StoreInfo{{1, "", ""}}, 0, 0, models.BaseModel{CreatedAt: time.Now(), UpdatedAt: time.Now()}, "", ""}},
|
||||
{SysUserId: models.SysUserId{1}, LoginM: models.LoginM{models.UserName{"admin"}, models.PassWord{"$2a$10$cKFFTCzGOvaIHHJY2K45Zuwt8TD6oPzYi4s5MzYIBAWCLL6ZhouP2"}}, SysUserB: models.SysUserB{"zhangwj", "13818888888", 1, "", "", "0", "1@qq.com", 1, 1, "1", "1", "", "0", 1, "总店", 1, "迪为", 1, "", []models.StoreInfo{{1, "", ""}}, 0, 0, "", models.BaseModel{CreatedAt: time.Now(), UpdatedAt: time.Now()}, "", ""}},
|
||||
}
|
||||
|
||||
list9 := []models.DictData{
|
||||
|
|
3
config/hm_pay/jbl_private_key.pem
Normal file
3
config/hm_pay/jbl_private_key.pem
Normal file
|
@ -0,0 +1,3 @@
|
|||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCZqJtyqYd4HcYPNQnR2/IDDgcUFXjWs0kDMIre7AF6zNAcFD/vTOCcEzmb0scLhduoy6sEXj6lxdAuNYXKhVJIh2XRdORVMLqtdgeGN3W5rohQSC/8kWt6VmcXJZQw5YDdbSpacSa0djLxX8+lJuQwrkkNQKb41/uGifCwvnpF9sR8DqF9iDQn3LNoV2AkkCmXfXCPh2GJD1DOXes81dxzqWAc1kCSyGIPNgWgspV7rU4Zm5VpnomptxvMnIr3F+HXxM4zVk48JHwA6+FwQaw/G/XdqiZTwFtm65VbEEYrmsj8UYlxzeNOa6xv20AsmhwYJIMAi3Q+ziH1pVDGN1+3AgMBAAECggEAReUnSKIK6D2K4VH79IT68h7IY39c5zTIanYDRWHPTn+pzov7hSvQI86u7s2TEw/BmmeClEsWbiusBcj84eGBS1KjowJr9sBiuhKtW4UQvPTCNtqPUXEIla6F2EaUwSU0WASXNmqv83istZUii/pD5EzzF98n1JvSYyGN5afPUNE3liMI+xsM1WdVuzB+hewLBS/98cFBDcrHbakxjFiBYiyuo3vwvu4JpmtoLlMB/J9cDNFi2Xu12kk2x1wEFvpErDd8fZrQny/Qvj9tt8O+GZSPQqHFHxooRRubCkI6UWz3Qlx0GW3H5mRFYz1bqi4SD7BfTiS/LnmIU0UwSjrwsQKBgQDmhT6MPBUfNCREBvYyDu1qaRwRpXH78PvZKPgeaTzZqf8f9+2B97/xEQ1BZoDgjK3RG6CIrHmqjW1+uAFtsU/DvfSq49HlPV2Fdqt16vAeYIU2dnWCkNyl5eWlfxOLwWVqclsiHwHY9RZbmrg7/yW3oUqCF+9Gmd49Oogg4cDQLwKBgQCqpH820p6uRtqcphpYQPrws/L+zlX8Ddh2EiBcPZvu1VOCr9CEdhDguoP6Igk9d+eMnqXW6fczXtS88YuRNiqrg7hynWKtP4XPj6bTUMA9IK5Aum9NdWt7UmT9b+3iV0Dp28/TLIy0jOht0cFpkJTpNfypmIO+h5INPVIkFva++QKBgQClbkoM6bFey1SbXUOheQT4sKXsJAdA/xg+KCCn8m4w5saocoyIEPw2TD5vCNjETTEQN/tlGiHWO9iwb+zWg8DygIfte8FN+lP7S8aQwSHBKxNummSKZttyUyITOrcUPJ5DXf345re0s25wHwDITbsLpTyLUBHvYM0Us8StlFWDEQKBgAxJgfuBmPl1kqI696SpMSiJ3JJqaxiWKqL91SSvLv44kCXV4Q7YrYhxBbXKI54wdxTSC6D5AdrKFklwnxsaqmHlPy/Jk2RkMY9riZintN/x7XotsnwCW3XqzejN2XQ10i/EqydKiuspRkc6FlIynfZY89OGbt4WRvb7FmIQ4T2JAoGBAIVfna3AOKOngLHyjsBMRtpXsipV3rYKatuW5jMPP2WsJRAdn/I5VNxYDB4Su5/ieHjKE49cESeMsZbBB5myO4nUiLiZj3Pmvz7rmlTlGXtOS9anT6vYvWnKk8QSQJAWowE8AIHfN5m4pmZqRo4Es4gQvQt+vNavYEHt/+qWgn4m
|
||||
-----END RSA PUBLIC KEY-----
|
3
config/hm_pay/jbl_pub_private_key.pem
Normal file
3
config/hm_pay/jbl_pub_private_key.pem
Normal file
|
@ -0,0 +1,3 @@
|
|||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCZqJtyqYd4HcYPNQnR2/IDDgcUFXjWs0kDMIre7AF6zNAcFD/vTOCcEzmb0scLhduoy6sEXj6lxdAuNYXKhVJIh2XRdORVMLqtdgeGN3W5rohQSC/8kWt6VmcXJZQw5YDdbSpacSa0djLxX8+lJuQwrkkNQKb41/uGifCwvnpF9sR8DqF9iDQn3LNoV2AkkCmXfXCPh2GJD1DOXes81dxzqWAc1kCSyGIPNgWgspV7rU4Zm5VpnomptxvMnIr3F+HXxM4zVk48JHwA6+FwQaw/G/XdqiZTwFtm65VbEEYrmsj8UYlxzeNOa6xv20AsmhwYJIMAi3Q+ziH1pVDGN1+3AgMBAAECggEAReUnSKIK6D2K4VH79IT68h7IY39c5zTIanYDRWHPTn+pzov7hSvQI86u7s2TEw/BmmeClEsWbiusBcj84eGBS1KjowJr9sBiuhKtW4UQvPTCNtqPUXEIla6F2EaUwSU0WASXNmqv83istZUii/pD5EzzF98n1JvSYyGN5afPUNE3liMI+xsM1WdVuzB+hewLBS/98cFBDcrHbakxjFiBYiyuo3vwvu4JpmtoLlMB/J9cDNFi2Xu12kk2x1wEFvpErDd8fZrQny/Qvj9tt8O+GZSPQqHFHxooRRubCkI6UWz3Qlx0GW3H5mRFYz1bqi4SD7BfTiS/LnmIU0UwSjrwsQKBgQDmhT6MPBUfNCREBvYyDu1qaRwRpXH78PvZKPgeaTzZqf8f9+2B97/xEQ1BZoDgjK3RG6CIrHmqjW1+uAFtsU/DvfSq49HlPV2Fdqt16vAeYIU2dnWCkNyl5eWlfxOLwWVqclsiHwHY9RZbmrg7/yW3oUqCF+9Gmd49Oogg4cDQLwKBgQCqpH820p6uRtqcphpYQPrws/L+zlX8Ddh2EiBcPZvu1VOCr9CEdhDguoP6Igk9d+eMnqXW6fczXtS88YuRNiqrg7hynWKtP4XPj6bTUMA9IK5Aum9NdWt7UmT9b+3iV0Dp28/TLIy0jOht0cFpkJTpNfypmIO+h5INPVIkFva++QKBgQClbkoM6bFey1SbXUOheQT4sKXsJAdA/xg+KCCn8m4w5saocoyIEPw2TD5vCNjETTEQN/tlGiHWO9iwb+zWg8DygIfte8FN+lP7S8aQwSHBKxNummSKZttyUyITOrcUPJ5DXf345re0s25wHwDITbsLpTyLUBHvYM0Us8StlFWDEQKBgAxJgfuBmPl1kqI696SpMSiJ3JJqaxiWKqL91SSvLv44kCXV4Q7YrYhxBbXKI54wdxTSC6D5AdrKFklwnxsaqmHlPy/Jk2RkMY9riZintN/x7XotsnwCW3XqzejN2XQ10i/EqydKiuspRkc6FlIynfZY89OGbt4WRvb7FmIQ4T2JAoGBAIVfna3AOKOngLHyjsBMRtpXsipV3rYKatuW5jMPP2WsJRAdn/I5VNxYDB4Su5/ieHjKE49cESeMsZbBB5myO4nUiLiZj3Pmvz7rmlTlGXtOS9anT6vYvWnKk8QSQJAWowE8AIHfN5m4pmZqRo4Es4gQvQt+vNavYEHt/+qWgn4m
|
||||
-----END RSA PUBLIC KEY-----
|
3
config/hm_pay/jbl_pub_public_key.pem
Normal file
3
config/hm_pay/jbl_pub_public_key.pem
Normal file
|
@ -0,0 +1,3 @@
|
|||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmaibcqmHeB3GDzUJ0dvyAw4HFBV41rNJAzCK3uwBeszQHBQ/70zgnBM5m9LHC4XbqMurBF4+pcXQLjWFyoVSSIdl0XTkVTC6rXYHhjd1ua6IUEgv/JFrelZnFyWUMOWA3W0qWnEmtHYy8V/PpSbkMK5JDUCm+Nf7honwsL56RfbEfA6hfYg0J9yzaFdgJJApl31wj4dhiQ9Qzl3rPNXcc6lgHNZAkshiDzYFoLKVe61OGZuVaZ6JqbcbzJyK9xfh18TOM1ZOPCR8AOvhcEGsPxv13aomU8BbZuuVWxBGK5rI/FGJcc3jTmusb9tALJocGCSDAIt0Ps4h9aVQxjdftwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----
|
3
config/hm_pay/jbl_public_key.pem
Normal file
3
config/hm_pay/jbl_public_key.pem
Normal file
|
@ -0,0 +1,3 @@
|
|||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmaibcqmHeB3GDzUJ0dvyAw4HFBV41rNJAzCK3uwBeszQHBQ/70zgnBM5m9LHC4XbqMurBF4+pcXQLjWFyoVSSIdl0XTkVTC6rXYHhjd1ua6IUEgv/JFrelZnFyWUMOWA3W0qWnEmtHYy8V/PpSbkMK5JDUCm+Nf7honwsL56RfbEfA6hfYg0J9yzaFdgJJApl31wj4dhiQ9Qzl3rPNXcc6lgHNZAkshiDzYFoLKVe61OGZuVaZ6JqbcbzJyK9xfh18TOM1ZOPCR8AOvhcEGsPxv13aomU8BbZuuVWxBGK5rI/FGJcc3jTmusb9tALJocGCSDAIt0Ps4h9aVQxjdftwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----
|
3
config/hm_pay/switch_private_key.pem
Normal file
3
config/hm_pay/switch_private_key.pem
Normal file
|
@ -0,0 +1,3 @@
|
|||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDR19P9/7pIrtzsctlnFo9J5Yn1uucbMi+xRvaoM0tx2dwKBYS7AqdcibCHHlioqOV+xl6bU2T2LfyRcXr+cZJIl4U6UpCUfyPbBdaizlimPZwnWNEZVWQVszy2MPmGsV4f6anDakKHz80f6RZNGY1a9YEpeMea/XFQ/colQeb9mIfsfGx/sz14mL8zBwJSapngvCe0qsJf+xxtpftFUnMOKtMTF66fs8DuWQUeL3zZ0SRkNw3G/Sw1J8JUQm4Y92vMHWqDYSZnM1ExlQsf66vlRSh/BAoKZ3ezXAEppWI61Gerx6NxrONpzRyRUbtTUJIHdWbk6py9Soa8iETn6e5zAgMBAAECggEAEzvcI4DoGzdj6oxQXwGTWquebJaYDkcYVgByJVKmTKYyY/zDgLyqiHHaa1gduj/Y4TjffQ80xtfKOa6UHnRceyjgPktJE0NgDvhHBx8wwvQMtxKN/+tyxAZsvypYBL+HKBerxsybkoU6gP1FXQXFjhvInfuDGDK4yzqn56hVutKwxwbOtHzCCJQnfbV+NXKFHYA6OBIZ5LvplgeUlN0luN/b9wARSpdJSiNG9+GP8L2n7QIgFcPtLrQlhZYEnN1+USjqG4km1jdYIzSMYXuym3LCDlD4CFZgRxP8/2U2rq2kXiJRlH2l+ydNAL8dysvtgvQBLpFJJ1O+oOKWe3MyYQKBgQDv+GPvpDXwpk6alHbYRqOZVCH+XB1CBWWOsV5r84OaSRBWbgr2QE2I3V11dg8dOzd7izHpFjzItzXqjT0nTceOVDevvCco2LnDWtkC6M6o0j8NNpI4WukbzLWzOOLssAxNMVBFTqKYOJJnN6wx/s6x0RTlglCMW+d2FSOcErU1gwKBgQDf3D9zeBZF0WL8WinjF2F28C7y/yD1IZ0VTWz+fP2SlDJxyIxYdNqGl19Sqkb9+J/abPD7RXvys19Q8uSfnMXIpLh1gaokczwgwjTeaB6VwXB/5f+XPqBiO0aKe5i73VwGX2r6dsXUrtohuRp/O80qtj+ZcHmaDLYgm7/jANwAUQKBgE1jTl9HFrof9/Nz84u15CabckcET88tzF2jJ68qngNQkrs8y740aIy9ztkFlMQ5h6AI+LSRnlKgevvERrd5JuTolfjPddV/ZxDwKFH+4D6jZwAM3ETeVJTJhMNikhQAhkcSoy9mt5rdi6FL2/VXljLUGagWSYGqVc/H6272vYefAoGBAIFIuNhd/Tb7M1icVd6SDTbchbDOyWDotcisu4rJ8sQplGyELxGTAvWCDIo4TuG0KdXC3vWu7mN/VkfwzzqjFtLG1sT+Sp3cc1hT8KaVqTxByFAFK7RUddnlc9rcgJvWvqPrjWPzHlOzW8ToGzZp+hZ1xItAGupt9u0kJhDa2TPRAoGBAM2e+cEMYJc0KCHOJ/vptt7Dum/duAXrsnucREehNyZ5z3U0xaU7vFEMz5H9SI8e18kM4bgBDFkxB+enEZ6r0q9paSeZgz3hT5EtggSRa8u4MgpbVGcIQk9dbg1sT6SVUPROoL9giGL9WoRY1gDU6brHbs+EClDJUN56j28QT5xO
|
||||
-----END RSA PUBLIC KEY-----
|
3
config/hm_pay/switch_pub_private_key.pem
Normal file
3
config/hm_pay/switch_pub_private_key.pem
Normal file
|
@ -0,0 +1,3 @@
|
|||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCVdPz3OdVbN/XDm0zRzGiQ3vw1eB387D2ePMP2wGcbo7zZypLvsQwa7qzz6b0+THy697VEmMOoCM7SXUv5vsqDK5dmOQK66RLhUfv/DYK5yxcZlGYwYjmnT79W0Yppu9BmtQzMeggp2+LHHCfcc39krZJvlLagLEVS1AikD9p9RcjaGFfagNNetFOjxzQP6Zdi3SsBqokAW2zcu6LH02ERaZl3fSk5F4bjrIpkFipkprJoZzXfunui0hCKO6jQrCZ56YRpFY1XlPohALS5tP4VI8cjJXrOysdIX9y88mLtD5Ts1ZYJHudkbu4/xkQzbzxyLnQtajQnaXnIFu+ML6ZJAgMBAAECggEASH/Sgl7kl3ZC2ptIHXFpu/TfJVTaPymeDldtvBHDMo4v+vogYvNgauQis8NL0J+r1cp5fQgZyTZUlYk6ZLDfbdfEforjPyX2yaRKeIPmSRgyYW8yTwAm9Xli2MuWuAmqY1gqGDqOITgP/wQydeb1AjKMmWHrYTF4g2BlvKgQFbn4JaEGScslm1CIgGWt+rt9wJ3q9A+3U2irsZGjvsFFJ/0WP00w10QQ9Faq3yfMQTQ/bF+6E63pCOm1MZbGzHzpEbvEpp/G8mMjxp+Hs+3HCra4XWdZysp5+1DUxOWFRqQ8WqyNf83OAZAph8YTHKghKt0ncX8NKF40Ws5f7UJV/QKBgQDdXTevUWF2cQpra95ab66Ba77uIn2MmwrYOdILwh2eSvjeR9H1mJPBZ2+NKMBNuYA7Tz0E8qBGborX5TuwvrWmtrWigKEU2bDFLqIATecs56MW2kB4wbCIWyQj975NrHE1NN3ip5nYQSmS2Wy/QhzSgBjJrun/udJUGW0ArjIPuwKBgQCs14QkjArHAGB1/CArG1XGuAdZBAj82o+AtEuag5JpIbC9RtlA2H9CnH3ugUhrPV192XOULd6WtujR4gv9CVdFSZXtgCeB52dj62C5LS7iH98e6QfduYvxNGljKEe87iXd62qV7gLLOi/vtoZEu8Mejqw7HQ1o6VkKLr4TI5Q3ywKBgQCJNXSEmN7eeWbJ+sySJdN2qQBpvrsvYhKwv/YwD5woN7RWoxHDN1WudZyxVGcORkLzgEQEQxeRUIeDFrWO8kbKFUo0daJiuCRXtHX51k/Kh7GRQqrfrr7rZgLawH8WyiJJpoE6MkSrxIguW9KKIkKXP4sdx+uG9Pkn47Kqz058bQKBgAk+aXnO55CnC4Gj31CO4LKFCxeOqLBlPAGFIvn7iWwH+jzVOi9GpN+6IN4NmgLqQELHy2+kWGA1HhSDg2KgCkPRYKxYC0TeTGBCqWSd7wD29WbgzaPlFX/r7qr374ZCMlJBEe080nduADxQxbONWy0aMknjDuGKgVGTGGVLpNSrAoGARHsbxf/8th/Cs/TYD8mvZgPkgFMyKZuZM4Qe6VEwZazHplWXQ0BibYxloyb/nVYABxVJ0c4noP0I7pQ2H2Y68tvNWnOmVN3NaC5t1tPhE1eAA3Nfo3S3+Ma+X1bmprSQ0nyr3UeFvR2Pl3qKj5diTo4QU8RdSi4K6SwbqaK0+Ys=
|
||||
-----END RSA PUBLIC KEY-----
|
3
config/hm_pay/switch_pub_public_key.pem
Normal file
3
config/hm_pay/switch_pub_public_key.pem
Normal file
|
@ -0,0 +1,3 @@
|
|||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlXT89znVWzf1w5tM0cxokN78NXgd/Ow9njzD9sBnG6O82cqS77EMGu6s8+m9Pkx8uve1RJjDqAjO0l1L+b7KgyuXZjkCuukS4VH7/w2CucsXGZRmMGI5p0+/VtGKabvQZrUMzHoIKdvixxwn3HN/ZK2Sb5S2oCxFUtQIpA/afUXI2hhX2oDTXrRTo8c0D+mXYt0rAaqJAFts3Luix9NhEWmZd30pOReG46yKZBYqZKayaGc137p7otIQijuo0KwmeemEaRWNV5T6IQC0ubT+FSPHIyV6zsrHSF/cvPJi7Q+U7NWWCR7nZG7uP8ZEM288ci50LWo0J2l5yBbvjC+mSQIDAQAB
|
||||
-----END RSA PUBLIC KEY-----
|
3
config/hm_pay/switch_public_key.pem
Normal file
3
config/hm_pay/switch_public_key.pem
Normal file
|
@ -0,0 +1,3 @@
|
|||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0dfT/f+6SK7c7HLZZxaPSeWJ9brnGzIvsUb2qDNLcdncCgWEuwKnXImwhx5YqKjlfsZem1Nk9i38kXF6/nGSSJeFOlKQlH8j2wXWos5Ypj2cJ1jRGVVkFbM8tjD5hrFeH+mpw2pCh8/NH+kWTRmNWvWBKXjHmv1xUP3KJUHm/ZiH7Hxsf7M9eJi/MwcCUmqZ4LwntKrCX/scbaX7RVJzDirTExeun7PA7lkFHi982dEkZDcNxv0sNSfCVEJuGPdrzB1qg2EmZzNRMZULH+ur5UUofwQKCmd3s1wBKaViOtRnq8ejcazjac0ckVG7U1CSB3Vm5OqcvUqGvIhE5+nucwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----
|
215
docs/docs.go
215
docs/docs.go
|
@ -4589,6 +4589,39 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/order/fund_record/list": {
|
||||
"post": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"财务管理"
|
||||
],
|
||||
"summary": "查询财务统计列表",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "查询财务统计列表模型",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.FundRecordListReq"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.FundRecordListResp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/order/list": {
|
||||
"post": {
|
||||
"consumes": [
|
||||
|
@ -5725,6 +5758,18 @@ const docTemplate = `{
|
|||
"description": "门店id",
|
||||
"name": "storeId",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "店员兑换码",
|
||||
"name": "shopper_code",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "是否导出:1-导出",
|
||||
"name": "is_export",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
@ -6848,6 +6893,10 @@ const docTemplate = `{
|
|||
"description": "系统生成串码:2-是(系统生成) 3-否(手动添加)",
|
||||
"type": "integer"
|
||||
},
|
||||
"img": {
|
||||
"description": "图片",
|
||||
"type": "string"
|
||||
},
|
||||
"is_imei": {
|
||||
"description": "是否串码:1-串码类 2-非串码",
|
||||
"type": "integer"
|
||||
|
@ -6950,6 +6999,10 @@ const docTemplate = `{
|
|||
"description": "1-无串码 2-串码(系统生成) 3-串码(手动添加)",
|
||||
"type": "integer"
|
||||
},
|
||||
"img": {
|
||||
"description": "图片",
|
||||
"type": "string"
|
||||
},
|
||||
"is_imei": {
|
||||
"description": "是否串码:1-串码类 2-非串码",
|
||||
"type": "integer"
|
||||
|
@ -8018,6 +8071,10 @@ const docTemplate = `{
|
|||
"description": "1-无串码 2-串码(系统生成) 3-串码(手动添加)",
|
||||
"type": "integer"
|
||||
},
|
||||
"img": {
|
||||
"description": "图片",
|
||||
"type": "string"
|
||||
},
|
||||
"is_imei": {
|
||||
"description": "是否串码:1-串码类 2-非串码",
|
||||
"type": "integer"
|
||||
|
@ -9627,6 +9684,14 @@ const docTemplate = `{
|
|||
"description": "总员工成本:商品员工成本价之和",
|
||||
"type": "number"
|
||||
},
|
||||
"total_employee_gross_margins": {
|
||||
"description": "总员工毛利率: 员工毛利/销售/退货金额",
|
||||
"type": "string"
|
||||
},
|
||||
"total_employee_margin": {
|
||||
"description": "总员工毛利:销售金额/实际退货金额-员工成本",
|
||||
"type": "number"
|
||||
},
|
||||
"total_gross_margins": {
|
||||
"description": "销售毛利率:销售毛利/销售/退货金额",
|
||||
"type": "string"
|
||||
|
@ -10731,7 +10796,7 @@ const docTemplate = `{
|
|||
"description": "入/出库,开始时间",
|
||||
"type": "string"
|
||||
},
|
||||
"store_list": {
|
||||
"store_id": {
|
||||
"description": "门店复选",
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
@ -10922,6 +10987,13 @@ const docTemplate = `{
|
|||
"description": "创建时间",
|
||||
"type": "string"
|
||||
},
|
||||
"decision_store_id": {
|
||||
"description": "门店编号列表(查询进销存的时候使用)",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"dispatch_count": {
|
||||
"description": "调拨中数量(调拨中调入)",
|
||||
"type": "integer"
|
||||
|
@ -11362,6 +11434,123 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"models.FundRecord": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amount": {
|
||||
"type": "integer"
|
||||
},
|
||||
"createdAt": {
|
||||
"description": "创建时间",
|
||||
"type": "string"
|
||||
},
|
||||
"fund_type": {
|
||||
"description": "-member_gold -member_platinum -member_black_gold",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "数据库记录编号",
|
||||
"type": "integer"
|
||||
},
|
||||
"out_trade_no": {
|
||||
"type": "string"
|
||||
},
|
||||
"payment_no": {
|
||||
"description": "付款单号",
|
||||
"type": "string"
|
||||
},
|
||||
"refund_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"remark": {
|
||||
"description": "备注",
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"description": "1-待支付 2-已支付 3-已退款",
|
||||
"type": "integer"
|
||||
},
|
||||
"transaction_id": {
|
||||
"description": "支付单号",
|
||||
"type": "string"
|
||||
},
|
||||
"uid": {
|
||||
"type": "integer"
|
||||
},
|
||||
"updatedAt": {
|
||||
"description": "更新时间",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.FundRecordListReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"description": "结束时间",
|
||||
"type": "string"
|
||||
},
|
||||
"fund_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"is_export": {
|
||||
"description": "1-导出",
|
||||
"type": "integer"
|
||||
},
|
||||
"out_trade_no": {
|
||||
"type": "string"
|
||||
},
|
||||
"pageIndex": {
|
||||
"type": "integer"
|
||||
},
|
||||
"pageSize": {
|
||||
"type": "integer"
|
||||
},
|
||||
"payment_no": {
|
||||
"type": "string"
|
||||
},
|
||||
"refund_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"start_time": {
|
||||
"description": "开始时间",
|
||||
"type": "string"
|
||||
},
|
||||
"transaction_id": {
|
||||
"description": "支付单号",
|
||||
"type": "string"
|
||||
},
|
||||
"uid": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.FundRecordListResp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"export_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"list": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.FundRecord"
|
||||
}
|
||||
},
|
||||
"pageIndex": {
|
||||
"description": "页码",
|
||||
"type": "integer"
|
||||
},
|
||||
"pageSize": {
|
||||
"description": "每页展示条数",
|
||||
"type": "integer"
|
||||
},
|
||||
"total": {
|
||||
"description": "总条数",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.GameCard": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -11987,6 +12176,10 @@ const docTemplate = `{
|
|||
"description": "性别",
|
||||
"type": "string"
|
||||
},
|
||||
"shopper_code": {
|
||||
"description": "店员兑换码",
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"description": "状态",
|
||||
"type": "string"
|
||||
|
@ -15124,6 +15317,14 @@ const docTemplate = `{
|
|||
"description": "员工成本:商品员工成本价之和",
|
||||
"type": "number"
|
||||
},
|
||||
"employee_gross_margins": {
|
||||
"description": "员工毛利率: 零售销售时:员工毛利/销售金额 零售退货时:员工毛利/退货金额",
|
||||
"type": "string"
|
||||
},
|
||||
"employee_margin": {
|
||||
"description": "员工毛利:零售销售时:销售金额-员工成本 零售退货时:实际退货金额-员工成本",
|
||||
"type": "number"
|
||||
},
|
||||
"erp_category_id": {
|
||||
"description": "分类id",
|
||||
"type": "integer"
|
||||
|
@ -16044,6 +16245,10 @@ const docTemplate = `{
|
|||
"description": "性别",
|
||||
"type": "string"
|
||||
},
|
||||
"shopper_code": {
|
||||
"description": "店员兑换码",
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"description": "状态",
|
||||
"type": "string"
|
||||
|
@ -16095,6 +16300,10 @@ const docTemplate = `{
|
|||
"description": "总条数",
|
||||
"type": "integer"
|
||||
},
|
||||
"export_url": {
|
||||
"description": "导出excel路径",
|
||||
"type": "string"
|
||||
},
|
||||
"list": {
|
||||
"description": "采购报表信息",
|
||||
"type": "array",
|
||||
|
@ -16195,6 +16404,10 @@ const docTemplate = `{
|
|||
"description": "性别",
|
||||
"type": "string"
|
||||
},
|
||||
"shopper_code": {
|
||||
"description": "店员兑换码",
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"description": "状态",
|
||||
"type": "string"
|
||||
|
|
|
@ -4578,6 +4578,39 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/order/fund_record/list": {
|
||||
"post": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"财务管理"
|
||||
],
|
||||
"summary": "查询财务统计列表",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "查询财务统计列表模型",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.FundRecordListReq"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.FundRecordListResp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/order/list": {
|
||||
"post": {
|
||||
"consumes": [
|
||||
|
@ -5714,6 +5747,18 @@
|
|||
"description": "门店id",
|
||||
"name": "storeId",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "店员兑换码",
|
||||
"name": "shopper_code",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "是否导出:1-导出",
|
||||
"name": "is_export",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
@ -6837,6 +6882,10 @@
|
|||
"description": "系统生成串码:2-是(系统生成) 3-否(手动添加)",
|
||||
"type": "integer"
|
||||
},
|
||||
"img": {
|
||||
"description": "图片",
|
||||
"type": "string"
|
||||
},
|
||||
"is_imei": {
|
||||
"description": "是否串码:1-串码类 2-非串码",
|
||||
"type": "integer"
|
||||
|
@ -6939,6 +6988,10 @@
|
|||
"description": "1-无串码 2-串码(系统生成) 3-串码(手动添加)",
|
||||
"type": "integer"
|
||||
},
|
||||
"img": {
|
||||
"description": "图片",
|
||||
"type": "string"
|
||||
},
|
||||
"is_imei": {
|
||||
"description": "是否串码:1-串码类 2-非串码",
|
||||
"type": "integer"
|
||||
|
@ -8007,6 +8060,10 @@
|
|||
"description": "1-无串码 2-串码(系统生成) 3-串码(手动添加)",
|
||||
"type": "integer"
|
||||
},
|
||||
"img": {
|
||||
"description": "图片",
|
||||
"type": "string"
|
||||
},
|
||||
"is_imei": {
|
||||
"description": "是否串码:1-串码类 2-非串码",
|
||||
"type": "integer"
|
||||
|
@ -9616,6 +9673,14 @@
|
|||
"description": "总员工成本:商品员工成本价之和",
|
||||
"type": "number"
|
||||
},
|
||||
"total_employee_gross_margins": {
|
||||
"description": "总员工毛利率: 员工毛利/销售/退货金额",
|
||||
"type": "string"
|
||||
},
|
||||
"total_employee_margin": {
|
||||
"description": "总员工毛利:销售金额/实际退货金额-员工成本",
|
||||
"type": "number"
|
||||
},
|
||||
"total_gross_margins": {
|
||||
"description": "销售毛利率:销售毛利/销售/退货金额",
|
||||
"type": "string"
|
||||
|
@ -10720,7 +10785,7 @@
|
|||
"description": "入/出库,开始时间",
|
||||
"type": "string"
|
||||
},
|
||||
"store_list": {
|
||||
"store_id": {
|
||||
"description": "门店复选",
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
@ -10911,6 +10976,13 @@
|
|||
"description": "创建时间",
|
||||
"type": "string"
|
||||
},
|
||||
"decision_store_id": {
|
||||
"description": "门店编号列表(查询进销存的时候使用)",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"dispatch_count": {
|
||||
"description": "调拨中数量(调拨中调入)",
|
||||
"type": "integer"
|
||||
|
@ -11351,6 +11423,123 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"models.FundRecord": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"amount": {
|
||||
"type": "integer"
|
||||
},
|
||||
"createdAt": {
|
||||
"description": "创建时间",
|
||||
"type": "string"
|
||||
},
|
||||
"fund_type": {
|
||||
"description": "-member_gold -member_platinum -member_black_gold",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "数据库记录编号",
|
||||
"type": "integer"
|
||||
},
|
||||
"out_trade_no": {
|
||||
"type": "string"
|
||||
},
|
||||
"payment_no": {
|
||||
"description": "付款单号",
|
||||
"type": "string"
|
||||
},
|
||||
"refund_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"remark": {
|
||||
"description": "备注",
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"description": "1-待支付 2-已支付 3-已退款",
|
||||
"type": "integer"
|
||||
},
|
||||
"transaction_id": {
|
||||
"description": "支付单号",
|
||||
"type": "string"
|
||||
},
|
||||
"uid": {
|
||||
"type": "integer"
|
||||
},
|
||||
"updatedAt": {
|
||||
"description": "更新时间",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.FundRecordListReq": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"description": "结束时间",
|
||||
"type": "string"
|
||||
},
|
||||
"fund_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"is_export": {
|
||||
"description": "1-导出",
|
||||
"type": "integer"
|
||||
},
|
||||
"out_trade_no": {
|
||||
"type": "string"
|
||||
},
|
||||
"pageIndex": {
|
||||
"type": "integer"
|
||||
},
|
||||
"pageSize": {
|
||||
"type": "integer"
|
||||
},
|
||||
"payment_no": {
|
||||
"type": "string"
|
||||
},
|
||||
"refund_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"start_time": {
|
||||
"description": "开始时间",
|
||||
"type": "string"
|
||||
},
|
||||
"transaction_id": {
|
||||
"description": "支付单号",
|
||||
"type": "string"
|
||||
},
|
||||
"uid": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.FundRecordListResp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"export_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"list": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.FundRecord"
|
||||
}
|
||||
},
|
||||
"pageIndex": {
|
||||
"description": "页码",
|
||||
"type": "integer"
|
||||
},
|
||||
"pageSize": {
|
||||
"description": "每页展示条数",
|
||||
"type": "integer"
|
||||
},
|
||||
"total": {
|
||||
"description": "总条数",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.GameCard": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -11976,6 +12165,10 @@
|
|||
"description": "性别",
|
||||
"type": "string"
|
||||
},
|
||||
"shopper_code": {
|
||||
"description": "店员兑换码",
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"description": "状态",
|
||||
"type": "string"
|
||||
|
@ -15113,6 +15306,14 @@
|
|||
"description": "员工成本:商品员工成本价之和",
|
||||
"type": "number"
|
||||
},
|
||||
"employee_gross_margins": {
|
||||
"description": "员工毛利率: 零售销售时:员工毛利/销售金额 零售退货时:员工毛利/退货金额",
|
||||
"type": "string"
|
||||
},
|
||||
"employee_margin": {
|
||||
"description": "员工毛利:零售销售时:销售金额-员工成本 零售退货时:实际退货金额-员工成本",
|
||||
"type": "number"
|
||||
},
|
||||
"erp_category_id": {
|
||||
"description": "分类id",
|
||||
"type": "integer"
|
||||
|
@ -16033,6 +16234,10 @@
|
|||
"description": "性别",
|
||||
"type": "string"
|
||||
},
|
||||
"shopper_code": {
|
||||
"description": "店员兑换码",
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"description": "状态",
|
||||
"type": "string"
|
||||
|
@ -16084,6 +16289,10 @@
|
|||
"description": "总条数",
|
||||
"type": "integer"
|
||||
},
|
||||
"export_url": {
|
||||
"description": "导出excel路径",
|
||||
"type": "string"
|
||||
},
|
||||
"list": {
|
||||
"description": "采购报表信息",
|
||||
"type": "array",
|
||||
|
@ -16184,6 +16393,10 @@
|
|||
"description": "性别",
|
||||
"type": "string"
|
||||
},
|
||||
"shopper_code": {
|
||||
"description": "店员兑换码",
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"description": "状态",
|
||||
"type": "string"
|
||||
|
|
|
@ -510,6 +510,9 @@ definitions:
|
|||
imei_type:
|
||||
description: 系统生成串码:2-是(系统生成) 3-否(手动添加)
|
||||
type: integer
|
||||
img:
|
||||
description: 图片
|
||||
type: string
|
||||
is_imei:
|
||||
description: 是否串码:1-串码类 2-非串码
|
||||
type: integer
|
||||
|
@ -583,6 +586,9 @@ definitions:
|
|||
imei_type:
|
||||
description: 1-无串码 2-串码(系统生成) 3-串码(手动添加)
|
||||
type: integer
|
||||
img:
|
||||
description: 图片
|
||||
type: string
|
||||
is_imei:
|
||||
description: 是否串码:1-串码类 2-非串码
|
||||
type: integer
|
||||
|
@ -1369,6 +1375,9 @@ definitions:
|
|||
imei_type:
|
||||
description: 1-无串码 2-串码(系统生成) 3-串码(手动添加)
|
||||
type: integer
|
||||
img:
|
||||
description: 图片
|
||||
type: string
|
||||
is_imei:
|
||||
description: 是否串码:1-串码类 2-非串码
|
||||
type: integer
|
||||
|
@ -2546,6 +2555,12 @@ definitions:
|
|||
total_employee_cost:
|
||||
description: 总员工成本:商品员工成本价之和
|
||||
type: number
|
||||
total_employee_gross_margins:
|
||||
description: '总员工毛利率: 员工毛利/销售/退货金额'
|
||||
type: string
|
||||
total_employee_margin:
|
||||
description: 总员工毛利:销售金额/实际退货金额-员工成本
|
||||
type: number
|
||||
total_gross_margins:
|
||||
description: 销售毛利率:销售毛利/销售/退货金额
|
||||
type: string
|
||||
|
@ -3351,7 +3366,7 @@ definitions:
|
|||
start_time:
|
||||
description: 入/出库,开始时间
|
||||
type: string
|
||||
store_list:
|
||||
store_id:
|
||||
description: 门店复选
|
||||
items:
|
||||
type: integer
|
||||
|
@ -3489,6 +3504,11 @@ definitions:
|
|||
createdAt:
|
||||
description: 创建时间
|
||||
type: string
|
||||
decision_store_id:
|
||||
description: 门店编号列表(查询进销存的时候使用)
|
||||
items:
|
||||
type: integer
|
||||
type: array
|
||||
dispatch_count:
|
||||
description: 调拨中数量(调拨中调入)
|
||||
type: integer
|
||||
|
@ -3811,6 +3831,88 @@ definitions:
|
|||
required:
|
||||
- erp_commodity_id
|
||||
type: object
|
||||
models.FundRecord:
|
||||
properties:
|
||||
amount:
|
||||
type: integer
|
||||
createdAt:
|
||||
description: 创建时间
|
||||
type: string
|
||||
fund_type:
|
||||
description: -member_gold -member_platinum -member_black_gold
|
||||
type: string
|
||||
id:
|
||||
description: 数据库记录编号
|
||||
type: integer
|
||||
out_trade_no:
|
||||
type: string
|
||||
payment_no:
|
||||
description: 付款单号
|
||||
type: string
|
||||
refund_id:
|
||||
type: string
|
||||
remark:
|
||||
description: 备注
|
||||
type: string
|
||||
status:
|
||||
description: 1-待支付 2-已支付 3-已退款
|
||||
type: integer
|
||||
transaction_id:
|
||||
description: 支付单号
|
||||
type: string
|
||||
uid:
|
||||
type: integer
|
||||
updatedAt:
|
||||
description: 更新时间
|
||||
type: string
|
||||
type: object
|
||||
models.FundRecordListReq:
|
||||
properties:
|
||||
end_time:
|
||||
description: 结束时间
|
||||
type: string
|
||||
fund_type:
|
||||
type: string
|
||||
is_export:
|
||||
description: 1-导出
|
||||
type: integer
|
||||
out_trade_no:
|
||||
type: string
|
||||
pageIndex:
|
||||
type: integer
|
||||
pageSize:
|
||||
type: integer
|
||||
payment_no:
|
||||
type: string
|
||||
refund_id:
|
||||
type: string
|
||||
start_time:
|
||||
description: 开始时间
|
||||
type: string
|
||||
transaction_id:
|
||||
description: 支付单号
|
||||
type: string
|
||||
uid:
|
||||
type: integer
|
||||
type: object
|
||||
models.FundRecordListResp:
|
||||
properties:
|
||||
export_url:
|
||||
type: string
|
||||
list:
|
||||
items:
|
||||
$ref: '#/definitions/models.FundRecord'
|
||||
type: array
|
||||
pageIndex:
|
||||
description: 页码
|
||||
type: integer
|
||||
pageSize:
|
||||
description: 每页展示条数
|
||||
type: integer
|
||||
total:
|
||||
description: 总条数
|
||||
type: integer
|
||||
type: object
|
||||
models.GameCard:
|
||||
properties:
|
||||
coverImg:
|
||||
|
@ -4253,6 +4355,9 @@ definitions:
|
|||
sex:
|
||||
description: 性别
|
||||
type: string
|
||||
shopper_code:
|
||||
description: 店员兑换码
|
||||
type: string
|
||||
status:
|
||||
description: 状态
|
||||
type: string
|
||||
|
@ -6516,6 +6621,12 @@ definitions:
|
|||
employee_cost:
|
||||
description: 员工成本:商品员工成本价之和
|
||||
type: number
|
||||
employee_gross_margins:
|
||||
description: '员工毛利率: 零售销售时:员工毛利/销售金额 零售退货时:员工毛利/退货金额'
|
||||
type: string
|
||||
employee_margin:
|
||||
description: 员工毛利:零售销售时:销售金额-员工成本 零售退货时:实际退货金额-员工成本
|
||||
type: number
|
||||
erp_category_id:
|
||||
description: 分类id
|
||||
type: integer
|
||||
|
@ -7180,6 +7291,9 @@ definitions:
|
|||
sex:
|
||||
description: 性别
|
||||
type: string
|
||||
shopper_code:
|
||||
description: 店员兑换码
|
||||
type: string
|
||||
status:
|
||||
description: 状态
|
||||
type: string
|
||||
|
@ -7217,6 +7331,9 @@ definitions:
|
|||
count:
|
||||
description: 总条数
|
||||
type: integer
|
||||
export_url:
|
||||
description: 导出excel路径
|
||||
type: string
|
||||
list:
|
||||
description: 采购报表信息
|
||||
items:
|
||||
|
@ -7290,6 +7407,9 @@ definitions:
|
|||
sex:
|
||||
description: 性别
|
||||
type: string
|
||||
shopper_code:
|
||||
description: 店员兑换码
|
||||
type: string
|
||||
status:
|
||||
description: 状态
|
||||
type: string
|
||||
|
@ -10836,6 +10956,27 @@ paths:
|
|||
summary: 操作日志列表(update)
|
||||
tags:
|
||||
- system/日志
|
||||
/api/v1/order/fund_record/list:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
parameters:
|
||||
- description: 查询财务统计列表模型
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/models.FundRecordListReq'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/models.FundRecordListResp'
|
||||
summary: 查询财务统计列表
|
||||
tags:
|
||||
- 财务管理
|
||||
/api/v1/order/list:
|
||||
post:
|
||||
consumes:
|
||||
|
@ -11555,6 +11696,14 @@ paths:
|
|||
in: query
|
||||
name: storeId
|
||||
type: string
|
||||
- description: 店员兑换码
|
||||
in: query
|
||||
name: shopper_code
|
||||
type: string
|
||||
- description: 是否导出:1-导出
|
||||
in: query
|
||||
name: is_export
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
|
|
|
@ -535,8 +535,10 @@ func TestMemberExpirationReminder(t *testing.T) {
|
|||
func TestExpireMemberSMSSendDay(t *testing.T) {
|
||||
InitIODBTest()
|
||||
orm.Eloquent = IODBTest
|
||||
nowTime := time.Now()
|
||||
models.ExpireMemberSMSSendDay(1, nowTime)
|
||||
models.ExpireMemberSMSSend()
|
||||
|
||||
//nowTime := time.Now()
|
||||
//models.ExpireMemberSMSSendDay(1, nowTime)
|
||||
}
|
||||
|
||||
func TestCreateInviteMemberReport(t *testing.T) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"gorm.io/gorm"
|
||||
"log"
|
||||
"math"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
@ -134,3 +135,32 @@ func StringSliceContains(slice []string, val string) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RoundFloat 保留 float64 两位小数
|
||||
func RoundFloat(f float64) float64 {
|
||||
return math.Round(f*100) / 100
|
||||
}
|
||||
|
||||
// RoundFloatFields 递归处理结构体中的 float64 字段,四舍五入保留两位小数
|
||||
func RoundFloatFields(v interface{}) {
|
||||
val := reflect.ValueOf(v).Elem()
|
||||
|
||||
for i := 0; i < val.NumField(); i++ {
|
||||
field := val.Field(i)
|
||||
switch field.Kind() {
|
||||
case reflect.Float64:
|
||||
// 对 float64 类型进行四舍五入
|
||||
field.SetFloat(RoundFloat(field.Float()))
|
||||
case reflect.Struct:
|
||||
// 递归处理子结构体
|
||||
RoundFloatFields(field.Addr().Interface())
|
||||
case reflect.Slice:
|
||||
// 对于 slice 中的结构体,逐个处理
|
||||
for j := 0; j < field.Len(); j++ {
|
||||
if field.Index(j).Kind() == reflect.Struct {
|
||||
RoundFloatFields(field.Index(j).Addr().Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user