Browse Source

add reverse:for v1.0.0 条件统计

tags/v1.0.0
huangjiajun 1 year ago
commit
78851fed78
27 changed files with 2263 additions and 0 deletions
  1. +8
    -0
      .idea/.gitignore
  2. +8
    -0
      .idea/modules.xml
  3. +6
    -0
      .idea/vcs.xml
  4. +9
    -0
      .idea/zyos_go_condition_statistics.iml
  5. +9
    -0
      db/db.go
  6. +64
    -0
      db/db_mall_order.go
  7. +68
    -0
      db/db_order.go
  8. +16
    -0
      db/db_user_level_ord.go
  9. +65
    -0
      db/model/b2c_ord.go
  10. +66
    -0
      db/model/mall_ord.go
  11. +12
    -0
      db/model/mall_ord_list_relate.go
  12. +64
    -0
      db/model/o2o_ord.go
  13. +30
    -0
      db/model/o2o_pay_to_merchant.go
  14. +46
    -0
      db/model/ord_list.go
  15. +12
    -0
      db/model/ord_list_relate.go
  16. +20
    -0
      db/model/user_level_ord.go
  17. +11
    -0
      go.mod
  18. +325
    -0
      hdl/hdl_condition.go
  19. +366
    -0
      utils/convert.go
  20. +209
    -0
      utils/curl.go
  21. +22
    -0
      utils/file.go
  22. +59
    -0
      utils/format.go
  23. +245
    -0
      utils/logx/log.go
  24. +105
    -0
      utils/logx/output.go
  25. +192
    -0
      utils/logx/sugar.go
  26. +23
    -0
      utils/serialize.go
  27. +203
    -0
      utils/string.go

+ 8
- 0
.idea/.gitignore View File

@@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/

+ 8
- 0
.idea/modules.xml View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/zyos_go_condition_statistics.iml" filepath="$PROJECT_DIR$/.idea/zyos_go_condition_statistics.iml" />
</modules>
</component>
</project>

+ 6
- 0
.idea/vcs.xml View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

+ 9
- 0
.idea/zyos_go_condition_statistics.iml View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

+ 9
- 0
db/db.go View File

@@ -0,0 +1,9 @@
package db

import "xorm.io/xorm"

// QueryNativeString 查询原生sql
func QueryNativeString(Db *xorm.Engine, sql string, args ...interface{}) ([]map[string]string, error) {
results, err := Db.SQL(sql, args...).QueryString()
return results, err
}

+ 64
- 0
db/db_mall_order.go View File

@@ -0,0 +1,64 @@
package db

import (
"code.fnuoos.com/go_rely_warehouse/zyos_go_condition_statistics.git/db/model"
zhios_condition_statistics_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_condition_statistics.git/utils/logx"
"fmt"
"xorm.io/xorm"
)

func MallOrdByTimeWithCount(Db *xorm.Engine, uid, buyType, state, stime, etime interface{}) (int64, error) {
total, err := Db.Where("uid = ? AND state in (?) AND create_time > ? AND create_time < ?", uid, state, stime, etime).Count(&model.MallOrd{})
fmt.Println(err)
fmt.Println(total)
if err != nil {
return 0, zhios_condition_statistics_logx.Error(err)
}
return total, nil
}

// 查询用户某时间段内某状态的佣金(ord_id => amount)
func MallOrderRelateListByTimeByState(Db *xorm.Engine, uid, state, startTime, endTime interface{}) (*map[int64]float64, float64, error) {
var o []*model.MallOrd
var or []*model.MallOrdListRelate
var idAmountMap = make(map[int64]float64)
// 分佣明细数据
err := Db.Where("`uid` = ?", uid).Find(&or)
if err != nil {
zhios_condition_statistics_logx.Error(err)
return nil, 0, err
}
if len(or) == 0 {
return &idAmountMap, 0, nil
}
var ids []int64
for _, item := range or {
ids = append(ids, item.Oid)
}
str := fmt.Sprintf("state in (%s) AND create_time >%s AND create_time < %s", state, startTime, endTime)
fmt.Println("============test佣金数=================")
fmt.Println(str)
// 已结算的订单数据
err = Db.In("ord_id", ids).Where("state in (?) AND create_time > ? AND create_time < ?", state, startTime, endTime).Find(&o)
if err != nil {
zhios_condition_statistics_logx.Error(err)
return nil, 0, err
}
if len(o) == 0 {
return &idAmountMap, 0, nil
}

// id => amount
for _, item := range o {
for _, i := range or {
if item.OrdId == i.Oid {
idAmountMap[i.Oid] = i.Amount
}
}
}
var sum float64
for _, item := range idAmountMap {
sum += item
}
return &idAmountMap, sum, nil
}

+ 68
- 0
db/db_order.go View File

@@ -0,0 +1,68 @@
package db

import (
"code.fnuoos.com/go_rely_warehouse/zyos_go_condition_statistics.git/db/model"
zhios_condition_statistics_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_condition_statistics.git/utils"
zhios_condition_statistics_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_condition_statistics.git/utils/logx"
"fmt"
"xorm.io/xorm"
)

// OrderListCountByUIDByOrderTypeByTime is 查询订单 by uid by time ,获取规定时间内的订单类型的订单数
func OrderListCountByUIDByOrderTypeByTime(Db *xorm.Engine, uid, buyType, state, stime, etime interface{}) (int64, error) {
str := fmt.Sprintf("uid = %s AND order_type = %s AND ( state in (%s) or settle_at>0) AND create_at > %s AND create_at < %s",
zhios_condition_statistics_utils.AnyToString(uid), buyType, state, stime, etime)
fmt.Println("============test订单数=================")
fmt.Println(str)
total, err := Db.Where("uid = ? AND order_type = ? AND ( state in (?) or settle_at>0) AND create_at > ? AND create_at < ?", uid, buyType, state, stime, etime).Count(&model.OrdList{})
fmt.Println(err)
fmt.Println(total)

if err != nil {
return 0, zhios_condition_statistics_logx.Error(err)
}
return total, nil
}

// 查询用户某时间段内某状态的佣金(ord_id => amount)
func OrderRelateListByTimeByState(Db *xorm.Engine, uid, state, startTime, endTime interface{}) (*map[int64]float64, error) {
var o []*model.OrdList
var or []*model.OrdListRelate
var idAmountMap = make(map[int64]float64)
// 分佣明细数据
err := Db.Where("`uid` = ?", uid).Find(&or)
if err != nil {
zhios_condition_statistics_logx.Error(err)
return nil, err
}
if len(or) == 0 {
return &idAmountMap, nil
}
var ids []int64
for _, item := range or {
ids = append(ids, item.Oid)
}
str := fmt.Sprintf("state in (%s) AND create_at >%s AND create_at < %s", state, startTime, endTime)
fmt.Println("============test佣金数=================")
fmt.Println(str)
// 已结算的订单数据
err = Db.In("ord_id", ids).Where("state in (?) AND create_at > ? AND create_at < ?", state, startTime, endTime).Find(&o)
if err != nil {
zhios_condition_statistics_logx.Error(err)
return nil, err
}
if len(o) == 0 {
return &idAmountMap, nil
}

// id => amount
for _, item := range o {
for _, i := range or {
if item.OrdId == i.Oid {
idAmountMap[i.Oid] = i.Amount
}
}
}

return &idAmountMap, nil
}

+ 16
- 0
db/db_user_level_ord.go View File

@@ -0,0 +1,16 @@
package db

import (
"code.fnuoos.com/go_rely_warehouse/zyos_go_condition_statistics.git/db/model"
"xorm.io/xorm"
)

// 获取一个订单
func UserLevelOrderByTaskId(Db *xorm.Engine, uid, id string) (*model.UserLevelOrd, error) {
var m model.UserLevelOrd
has, err := Db.Where("uid = ? AND task_id = ? AND state = 1 ", uid, id).Desc("expire_at").Get(&m)
if err != nil || has == false {
return nil, err
}
return &m, nil
}

+ 65
- 0
db/model/b2c_ord.go View File

@@ -0,0 +1,65 @@
package model

import (
"time"
)

type B2cOrd struct {
OrdId int64 `json:"ord_id" xorm:"not null pk BIGINT(20)"`
MainOrdId int64 `json:"main_ord_id" xorm:"not null comment('主订单号') index BIGINT(20)"`
Uid int `json:"uid" xorm:"comment('用户id') index INT(11)"`
BelongStoreId int `json:"belong_store_id" xorm:"comment('归属店铺id') INT(11)"`
BuyerName string `json:"buyer_name" xorm:"comment('购买人') VARCHAR(255)"`
BuyerPhone string `json:"buyer_phone" xorm:"comment('购买人手机号') VARCHAR(255)"`
CostPrice string `json:"cost_price" xorm:"comment('价格') DECIMAL(12,2)"`
CostVirtualCoin string `json:"cost_virtual_coin" xorm:"comment('消耗的虚拟币') DECIMAL(12,2)"`
VirtualCoinId int `json:"virtual_coin_id" xorm:"comment('使用的虚拟币id') INT(11)"`
State int `json:"state" xorm:"comment('订单状态:0未支付 1已支付 ...(其余状态根据订单类型不同)') TINYINT(1)"`
PayTime time.Time `json:"pay_time" xorm:"comment('支付时间') DATETIME"`
PickUp int `json:"pick_up" xorm:"not null comment('取货方式:1堂食 2打包带走') TINYINT(1)"`
PayChannel int `json:"pay_channel" xorm:"not null comment('支付方式:1balance 2alipay 3wx_pay 4zhios_pay_alipay') TINYINT(1)"`
ShippingTime time.Time `json:"shipping_time" xorm:"comment('发货时间') DATETIME"`
DeliveryWay int `json:"delivery_way" xorm:"default 1 comment('发货方式(1:自己联系)') TINYINT(1)"`
LogisticCompany string `json:"logistic_company" xorm:"not null default '' comment('物流公司') VARCHAR(255)"`
LogisticNum string `json:"logistic_num" xorm:"not null default '' comment('物流单号') VARCHAR(255)"`
ReceiverPhone string `json:"receiver_phone" xorm:"not null default '' comment('收货人手机号') VARCHAR(20)"`
ReceiverName string `json:"receiver_name" xorm:"not null default '' comment('收货人名字') VARCHAR(255)"`
ReceiverAddressDetail string `json:"receiver_address_detail" xorm:"not null default '' comment('收货人地址') VARCHAR(255)"`
ShippingType int `json:"shipping_type" xorm:"not null default 1 comment('运送方式:1快递送货') TINYINT(1)"`
CouponDiscount string `json:"coupon_discount" xorm:"not null default 0.00 comment('优惠券折扣额') DECIMAL(12,2)"`
DiscountPrice string `json:"discount_price" xorm:"not null default 0.00 comment('立减') DECIMAL(12,2)"`
UserCouponId int64 `json:"user_coupon_id" xorm:"comment('使用的优惠券id') BIGINT(20)"`
ReturnInsuranceFee string `json:"return_insurance_fee" xorm:"not null default 0.00 comment('退货无忧费用') DECIMAL(12,2)"`
IsReceipt int `json:"is_receipt" xorm:"not null default 0 comment('是否开具发票 0否 1是') TINYINT(255)"`
ShippingFee string `json:"shipping_fee" xorm:"not null default 0.00 comment('运费') DECIMAL(12,2)"`
Comment string `json:"comment" xorm:"not null comment('备注') VARCHAR(2048)"`
ProvinceName string `json:"province_name" xorm:"not null default '' comment('收货省份') VARCHAR(255)"`
CityName string `json:"city_name" xorm:"not null default '' comment('收货城市') VARCHAR(255)"`
CountyName string `json:"county_name" xorm:"not null default '' comment('收货区域') VARCHAR(255)"`
PayNum string `json:"pay_num" xorm:"not null default '' comment('交易流水') VARCHAR(255)"`
ConfirmTime time.Time `json:"confirm_time" xorm:"comment('确认时间') DATETIME"`
EstimateCommission string `json:"estimate_commission" xorm:"not null default 0.0000 comment('预计佣金(三方分账完之后站长的佣金)') DECIMAL(12,4)"`
CreateTime time.Time `json:"create_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('创建时间') DATETIME"`
UpdateTime time.Time `json:"update_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('更新时间') DATETIME"`
DeletedTime time.Time `json:"deleted_time" xorm:"comment('删除时间') DATETIME"`
FinishTime time.Time `json:"finish_time" xorm:"comment('完成时间') DATETIME"`
OrderType int `json:"order_type" xorm:"not null default 1 comment('订单类型:1(小店订单)') TINYINT(3)"`
Data string `json:"data" xorm:"not null comment('订单相关的数据') TEXT"`
SettleTime time.Time `json:"settle_time" xorm:"comment('结算时间') DATETIME"`
CommissionTime time.Time `json:"commission_time" xorm:"comment('分佣时间') DATETIME"`
ShareUid int `json:"share_uid" xorm:"comment('分享人') INT(11)"`
TotalPrice float32 `json:"total_price" xorm:"comment('订单总金额') FLOAT(8,2)"`
PickUpNum string `json:"pick_up_num" xorm:"comment('取餐号') VARCHAR(255)"`
TradeNo string `json:"trade_no" xorm:"comment('支付平台的订单号') VARCHAR(50)"`
PayTradeNo string `json:"pay_trade_no" xorm:"comment('支付联盟支付的订单号') VARCHAR(50)"`
ConsumptionType int `json:"consumption_type" xorm:"default 1 comment('消费类型:1到店消费2立即制作') TINYINT(1)"`
TableNum string `json:"table_num" xorm:"default '' comment('桌号') VARCHAR(12)"`
IsThreePartySplit int `json:"is_three_party_split" xorm:"comment('是否进行了三方分账,0:否,1:是') TINYINT(1)"`
MainCommission string `json:"main_commission" xorm:"not null default 0.0000 comment('总佣金') DECIMAL(12,4)"`
SkuPriceInfo string `json:"sku_price_info" xorm:"comment('新版本支付规则(规则计算信息)') VARCHAR(500)"`
PlatformCommission string `json:"platform_commission" xorm:"comment('平台所得的佣金(平台不是站长)') DECIMAL(12,4)"`
MealFee string `json:"meal_fee" xorm:"comment('餐位费') VARCHAR(50)"`
SupplierMerchantId int `json:"supplier_merchant_id" xorm:"comment('供应商id') INT(11)"`
SupplierOrdId string `json:"supplier_ord_id" xorm:"comment('供应商订单id') VARCHAR(255)"`
IsSetOutAch int `xorm:"not null default 0 INT(1)" json:"is_set_out_ach"`
}

+ 66
- 0
db/model/mall_ord.go View File

@@ -0,0 +1,66 @@
package model

import (
"time"
)

type MallOrd struct {
OrdId int64 `json:"ord_id" xorm:"not null pk BIGINT(20)"`
MainOrdId int64 `json:"main_ord_id" xorm:"not null comment('主订单号') index BIGINT(20)"`
Uid int `json:"uid" xorm:"comment('用户id') index INT(11)"`
BuyerName string `json:"buyer_name" xorm:"comment('购买人') VARCHAR(255)"`
IsSetSubsidy int `json:"is_set_subsidy" xorm:"comment('') default '0' INT(11)"`
BuyerPhone string `json:"buyer_phone" xorm:"comment('购买人手机号') VARCHAR(255)"`
CostPrice string `json:"cost_price" xorm:"comment('价格') DECIMAL(12,2)"`
DeductCoin string `json:"deduct_coin" xorm:"comment('抵扣券') DECIMAL(12,2)"`
CostVirtualCoin string `json:"cost_virtual_coin" xorm:"comment('消耗的虚拟币') DECIMAL(12,2)"`
VirtualCoinId int `json:"virtual_coin_id" xorm:"comment('使用的虚拟币id') INT(11)"`
State int `json:"state" xorm:"comment('订单状态:0未支付 1已支付 2已发货 3已完成 4售后中 5部分售后中 6关闭') TINYINT(1)"`
PayTime time.Time `json:"pay_time" xorm:"comment('支付时间') DATETIME"`
PayChannel int `json:"pay_channel" xorm:"not null comment('支付方式:1balance 2alipay 3wx_pay') TINYINT(1)"`
ShippingTime time.Time `json:"shipping_time" xorm:"comment('发货时间') DATETIME"`
LogisticCompany string `json:"logistic_company" xorm:"not null default '' comment('物流公司') VARCHAR(255)"`
LogisticNum string `json:"logistic_num" xorm:"not null default '' comment('物流单号') VARCHAR(255)"`
ReceiverPhone string `json:"receiver_phone" xorm:"not null default '' comment('收货人手机号') VARCHAR(20)"`
ReceiverName string `json:"receiver_name" xorm:"not null default '' comment('收货人名字') VARCHAR(255)"`
ReceiverAddressDetail string `json:"receiver_address_detail" xorm:"not null default '' comment('收货人地址') VARCHAR(255)"`
ShippingType int `json:"shipping_type" xorm:"not null default 1 comment('运送方式:1快递送货') TINYINT(1)"`
CouponDiscount string `json:"coupon_discount" xorm:"not null default 0.00 comment('优惠券折扣额') DECIMAL(12,2)"`
DiscountPrice string `json:"discount_price" xorm:"not null default 0.00 comment('立减') DECIMAL(12,2)"`
UserCouponId int64 `json:"user_coupon_id" xorm:"comment('使用的优惠券id') BIGINT(20)"`
ReturnInsuranceFee string `json:"return_insurance_fee" xorm:"not null default 0.00 comment('退货无忧费用') DECIMAL(12,2)"`
IsReceipt int `json:"is_receipt" xorm:"not null default 0 comment('是否开具发票 0否 1是') TINYINT(255)"`
ShippingFee string `json:"shipping_fee" xorm:"not null default 0.00 comment('运费') DECIMAL(12,2)"`
Comment string `json:"comment" xorm:"not null comment('备注') VARCHAR(2048)"`
ProvinceName string `json:"province_name" xorm:"not null default '' comment('收货省份') VARCHAR(255)"`
CityName string `json:"city_name" xorm:"not null default '' comment('收货城市') VARCHAR(255)"`
CountyName string `json:"county_name" xorm:"not null default '' comment('收货区域') VARCHAR(255)"`
PayNum string `json:"pay_num" xorm:"not null default '' comment('交易流水') VARCHAR(255)"`
ConfirmTime time.Time `json:"confirm_time" xorm:"comment('确认时间') DATETIME"`
EstimateIntegral string `json:"estimate_integral" xorm:"not null default 0.0000 comment('预计积分') DECIMAL(12,4)"`
EstimateCommission string `json:"estimate_commission" xorm:"not null default 0.0000 comment('预计佣金') DECIMAL(12,4)"`
CreateTime time.Time `json:"create_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('创建时间') DATETIME"`
UpdateTime time.Time `json:"update_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('更新时间') DATETIME"`
DeletedTime time.Time `json:"deleted_time" xorm:"comment('删除时间') DATETIME"`
FinishTime time.Time `json:"finish_time" xorm:"comment('完成时间') DATETIME"`
OrderType int `json:"order_type" xorm:"not null default 1 comment('订单类型:1普通订单 2拼团订单 3秒杀 4超级拼团 5会员礼包') TINYINT(3)"`
Data string `json:"data" xorm:"comment('订单相关的数据') TEXT"`
GroupBuyCommission string `json:"group_buy_commission" xorm:"default 0.0000 comment('团购未中奖佣金') DECIMAL(12,4)"`
GroupBuySettleTime time.Time `json:"group_buy_settle_time" xorm:"comment('拼团结算时间[废弃 合并到settle_time]') DATETIME"`
SettleTime time.Time `json:"settle_time" xorm:"comment('结算时间') DATETIME"`
GroupBuyCommissionTime time.Time `json:"group_buy_commission_time" xorm:"comment('拼团分佣时间[废弃 合并到commission_tiem]') DATETIME"`
CommissionTime time.Time `json:"commission_time" xorm:"comment('分佣时间') DATETIME"`
ShareUid int `json:"share_uid" xorm:"comment('分享人') INT(11)"`
IsConsign int `json:"is_consign" xorm:"not null default 0 comment('是否是超级拼团寄售0否1是') TINYINT(1)"`
UserLevelData string `json:"user_level_data" xorm:"comment('会员礼包相关') TEXT"`
ReturnMoneySettleAt int `json:"return_money_settle_at" xorm:"comment('返现金额结算') INT(11)"`
IsSetReduce int `xorm:"not null default 0 INT(1)" json:"is_set_reduce"`
IsSetOutAch int `xorm:"not null default 0 INT(1)" json:"is_set_out_ach"`
IsSubsidyEnd int `xorm:"not null default 0 INT(1)" json:"is_subsidy_end"`
RunTime int `xorm:"not null default 0 INT(11)" json:"run_time"`
ConsumptionCoinReward string `json:"consumption_coin_reward" xorm:"default 0.000000 comment('当前计算金额') DECIMAL(16,6)"`
DeductCoinReward string `json:"deduct_coin_reward" xorm:"default 0.000000 comment('当前计算金额') DECIMAL(16,6)"`
ConsumptionCoinRewardOut string `json:"consumption_coin_reward_out" xorm:"default 0.000000 comment('出局的金额') DECIMAL(16,6)"`
DeductCoinRewardOut string `json:"deduct_coin_reward_out" xorm:"default 0.000000 comment('出局的计算金额') DECIMAL(16,6)"`
PayOnBehalfUid int `json:"pay_on_behalf_uid" xorm:"comment('0') INT(11)"`
}

+ 12
- 0
db/model/mall_ord_list_relate.go View File

@@ -0,0 +1,12 @@
package model

type MallOrdListRelate struct {
Id int64 `json:"id" xorm:"pk autoincr BIGINT(20)"`
Oid int64 `json:"oid" xorm:"not null default 0 comment('订单号') index unique(IDX_ORD) BIGINT(20)"`
Uid int `json:"uid" xorm:"not null default 0 comment('用户ID') unique(IDX_ORD) index INT(10)"`
Amount float64 `json:"amount" xorm:"not null default 0.00 comment('金额') FLOAT(10,2)"`
Pvd string `json:"pvd" xorm:"not null default '' comment('类型:mall_goods 自营普通商品 group_buy 拼团未中奖分佣') index VARCHAR(255)"`
CreateAt int `json:"create_at" xorm:"not null default 0 comment('订单创建时间') index INT(10)"`
Level int `json:"level" xorm:"not null default 0 comment('0自购 1直推 大于1:间推') INT(10)"`
ReturnMoney float64 `json:"return_money" xorm:"not null default 0.00 comment('返现金额') DOUBLE(10,2)"`
}

+ 64
- 0
db/model/o2o_ord.go View File

@@ -0,0 +1,64 @@
package model

import (
"time"
)

type O2oOrd struct {
OrdId int64 `json:"ord_id" xorm:"not null pk BIGINT(20)"`
MainOrdId int64 `json:"main_ord_id" xorm:"not null comment('主订单号') index BIGINT(20)"`
Uid int `json:"uid" xorm:"comment('用户id') index INT(11)"`
BelongStoreId int `json:"belong_store_id" xorm:"comment('归属店铺id') INT(11)"`
BuyerName string `json:"buyer_name" xorm:"comment('购买人') VARCHAR(255)"`
BuyerPhone string `json:"buyer_phone" xorm:"comment('购买人手机号') VARCHAR(255)"`
CostPrice string `json:"cost_price" xorm:"comment('价格') DECIMAL(12,2)"`
CostVirtualCoin string `json:"cost_virtual_coin" xorm:"comment('消耗的虚拟币') DECIMAL(12,2)"`
VirtualCoinId int `json:"virtual_coin_id" xorm:"comment('使用的虚拟币id') INT(11)"`
State int `json:"state" xorm:"comment('订单状态:0未支付 1已支付 ...(其余状态根据订单类型不同)') TINYINT(1)"`
PayTime time.Time `json:"pay_time" xorm:"comment('支付时间') DATETIME"`
PickUp int `json:"pick_up" xorm:"not null comment('取货方式:1堂食 2打包带走') TINYINT(1)"`
PayChannel int `json:"pay_channel" xorm:"not null comment('支付方式:1balance 2alipay 3wx_pay 4zhios_pay_alipay') TINYINT(1)"`
ShippingTime time.Time `json:"shipping_time" xorm:"comment('发货时间') DATETIME"`
LogisticCompany string `json:"logistic_company" xorm:"not null default '' comment('物流公司') VARCHAR(255)"`
LogisticNum string `json:"logistic_num" xorm:"not null default '' comment('物流单号') VARCHAR(255)"`
ReceiverPhone string `json:"receiver_phone" xorm:"not null default '' comment('收货人手机号') VARCHAR(20)"`
ReceiverName string `json:"receiver_name" xorm:"not null default '' comment('收货人名字') VARCHAR(255)"`
ReceiverAddressDetail string `json:"receiver_address_detail" xorm:"not null default '' comment('收货人地址') VARCHAR(255)"`
ShippingType int `json:"shipping_type" xorm:"not null default 1 comment('运送方式:1快递送货') TINYINT(1)"`
CouponDiscount string `json:"coupon_discount" xorm:"not null default 0.00 comment('优惠券折扣额') DECIMAL(12,2)"`
DiscountPrice string `json:"discount_price" xorm:"not null default 0.00 comment('立减') DECIMAL(12,2)"`
UserCouponId int64 `json:"user_coupon_id" xorm:"comment('使用的优惠券id') BIGINT(20)"`
ReturnInsuranceFee string `json:"return_insurance_fee" xorm:"not null default 0.00 comment('退货无忧费用') DECIMAL(12,2)"`
IsReceipt int `json:"is_receipt" xorm:"not null default 0 comment('是否开具发票 0否 1是') TINYINT(255)"`
ShippingFee string `json:"shipping_fee" xorm:"not null default 0.00 comment('运费') DECIMAL(12,2)"`
Comment string `json:"comment" xorm:"not null comment('备注') VARCHAR(2048)"`
ProvinceName string `json:"province_name" xorm:"not null default '' comment('收货省份') VARCHAR(255)"`
CityName string `json:"city_name" xorm:"not null default '' comment('收货城市') VARCHAR(255)"`
CountyName string `json:"county_name" xorm:"not null default '' comment('收货区域') VARCHAR(255)"`
PayNum string `json:"pay_num" xorm:"not null default '' comment('交易流水') VARCHAR(255)"`
ConfirmTime time.Time `json:"confirm_time" xorm:"comment('确认时间') DATETIME"`
EstimateCommission string `json:"estimate_commission" xorm:"not null default 0.0000 comment('预计佣金(三方分账完之后站长的佣金)') DECIMAL(12,4)"`
CreateTime time.Time `json:"create_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('创建时间') DATETIME"`
UpdateTime time.Time `json:"update_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('更新时间') DATETIME"`
DeletedTime time.Time `json:"deleted_time" xorm:"comment('删除时间') DATETIME"`
FinishTime time.Time `json:"finish_time" xorm:"comment('完成时间') DATETIME"`
OrderType int `json:"order_type" xorm:"not null default 1 comment('订单类型:1(小店订单)') TINYINT(3)"`
Data string `json:"data" xorm:"not null comment('订单相关的数据') TEXT"`
SettleTime time.Time `json:"settle_time" xorm:"comment('结算时间') DATETIME"`
CommissionTime time.Time `json:"commission_time" xorm:"comment('分佣时间') DATETIME"`
ShareUid int `json:"share_uid" xorm:"comment('分享人') INT(11)"`
TotalPrice float32 `json:"total_price" xorm:"comment('订单总金额') FLOAT(8,2)"`
PickUpNum string `json:"pick_up_num" xorm:"comment('取餐号') VARCHAR(255)"`
TradeNo string `json:"trade_no" xorm:"comment('支付平台的订单号') VARCHAR(50)"`
PayTradeNo string `json:"pay_trade_no" xorm:"comment('支付联盟支付的订单号') VARCHAR(50)"`
ConsumptionType int `json:"consumption_type" xorm:"not null default 1 comment('消费类型:1到店消费2立即制作') TINYINT(1)"`
TableNum string `json:"table_num" xorm:"default '' comment('桌号') VARCHAR(12)"`
IsThreePartySplit int `json:"is_three_party_split" xorm:"comment('是否进行了三方分账,0:否,1:是') TINYINT(1)"`
MainCommission string `json:"main_commission" xorm:"not null default 0.0000 comment('总佣金') DECIMAL(12,4)"`
SkuPriceInfo string `json:"sku_price_info" xorm:"comment('新版本支付规则(规则计算信息)') VARCHAR(500)"`
PlatformCommission string `json:"platform_commission" xorm:"comment('平台所得的佣金(平台不是站长)') DECIMAL(12,4)"`
MealFee string `json:"meal_fee" xorm:"comment('餐位费') VARCHAR(50)"`
ReturnMoneySettleAt int `json:"return_money_settle_at" xorm:"default 0 comment('小口袋定制返现时间') INT(11)"`
IsSetReduce int `json:"is_set_reduce" xorm:"default 0 comment('小口袋定制设置退回 0否 1是') INT(1)"`
IsSetOutAch int `xorm:"not null default 0 INT(1)" json:"is_set_out_ach"`
}

+ 30
- 0
db/model/o2o_pay_to_merchant.go View File

@@ -0,0 +1,30 @@
package model

import (
"time"
)

type O2oPayToMerchant struct {
Id int64 `json:"id" xorm:"pk autoincr BIGINT(20)"`
PayId int64 `json:"pay_id" xorm:"not null comment('付款id') BIGINT(20)"`
Uid int `json:"uid" xorm:"not null comment('用户id') INT(11)"`
MerchantId int `json:"merchant_id" xorm:"comment('商户id') INT(11)"`
BelongStoreId int `json:"belong_store_id" xorm:"comment('归属店铺id') INT(11)"`
PayAmount string `json:"pay_amount" xorm:"comment('付款金额') DECIMAL(12,4)"`
ActualPayAmount string `json:"actual_pay_amount" xorm:"comment('实际付款金额') DECIMAL(12,4)"`
CoinId int `json:"coin_id" xorm:"comment('虚拟币id') INT(11)"`
TradeNo string `json:"trade_no" xorm:"comment('支付平台的订单号') VARCHAR(50)"`
PayTradeNo string `json:"pay_trade_no" xorm:"comment('支付联盟支付的订单号') VARCHAR(50)"`
MainCommission string `json:"main_commission" xorm:"comment('总佣金') DECIMAL(12,4)"`
EstimateCommission string `json:"estimate_commission" xorm:"comment('预计佣金(三方分账完之后站长的佣金)') DECIMAL(12,4)"`
PlatformCommission string `json:"platform_commission" xorm:"comment('平台所得的佣金') DECIMAL(12,4)"`
PayChannel int `json:"pay_channel" xorm:"comment('支付方式:1balance 2alipay 3wx_pay 4zhios_pay_alipay') TINYINT(2)"`
State int `json:"state" xorm:"not null default 0 comment('支付状态:0:未支付,1:已支付') TINYINT(2)"`
PayTime *time.Time `json:"pay_time" xorm:"comment('支付时间') DATETIME"`
Data string `json:"data" xorm:"comment('回调数据') VARCHAR(5000)"`
Remarks string `json:"remarks" xorm:"comment('备注') VARCHAR(255)"`
CreateTime time.Time `json:"create_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('创建时间') DATETIME"`
UpdateTime time.Time `json:"update_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('更新时间') DATETIME"`
SettleTime time.Time `json:"settle_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('结算时间') DATETIME"`
CommissionTime time.Time `json:"commission_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('时间') DATETIME"`
}

+ 46
- 0
db/model/ord_list.go View File

@@ -0,0 +1,46 @@
package model

type OrdList struct {
OrdId int64 `xorm:"pk autoincr BIGINT(20)" json:"ord_id"`
Uid int `xorm:"not null index INT(10)" json:"uid"`
PvdOid string `xorm:"not null index(IDX_PVD) VARCHAR(50)" json:"pvd_oid"`
ParentOrdId int64 `xorm:" BIGINT(20)" json:"parent_ord_id"`
Pvd string `xorm:"not null default '' index(IDX_PVD) index(IDX_PVD_ITEM) VARCHAR(8)" json:"pvd"`
ItemId string `xorm:"not null default '' index(IDX_PVD_ITEM) VARCHAR(50)" json:"item_id"`
ItemNum int `xorm:"not null default 1 TINYINT(3)" json:"item_num"`
ItemPrice float64 `xorm:"not null default 0.00 FLOAT(10,2)" json:"item_price"`
ItemCommissionRate float64 `xorm:"not null default 0.00 FLOAT(6,4)" json:"item_commission_rate"`
PaidPrice float64 `xorm:"not null default 0.00 FLOAT(10,2)" json:"paid_price"`
CostPrice float64 `xorm:"not null default 0.00 FLOAT(10,2)" json:"cost_price"`
OrderType int `xorm:"not null default 0 TINYINT(1)" json:"order_type"`
PriceType int `xorm:"not null default 0 INT(1)" json:"price_type"`
OrderCompare int `xorm:"not null default 0 TINYINT(1)" json:"order_compare"`
SubsidyFee float64 `xorm:"not null default 0.00 FLOAT(8,2)" json:"subsidy_fee"`
SubsidyRate float64 `xorm:"not null default 0.0000 FLOAT(10,4)" json:"subsidy_rate"`
UserCommission float64 `xorm:"not null default 0.000 FLOAT(8,3)" json:"user_commission"`
UserCommissionRate float64 `xorm:"not null default 0.0000 FLOAT(6,4)" json:"user_commission_rate"`
PvdCommission float64 `xorm:"not null default 0.0000 FLOAT(8,4)" json:"pvd_commission"`
PvdCommissionRate float64 `xorm:"not null default 0.0000 FLOAT(6,4)" json:"pvd_commission_rate"`
SysCommission float64 `xorm:"not null default 0.0000 FLOAT(8,4)" json:"sys_commission"`
SysCommissionRate float64 `xorm:"not null default 0.0000 FLOAT(6,4)" json:"sys_commission_rate"`
PlanCommissionId int `xorm:"not null default 0 INT(10)" json:"plan_commission_id"`
PlanCommissionState int `xorm:"not null default 0 TINYINT(1)" json:"plan_commission_state"`
Reason string `xorm:"not null default '' VARCHAR(32)" json:"reason"`
State int `xorm:"not null default 0 TINYINT(1)" json:"state"`
LockState int `xorm:"not null default 0 TINYINT(1)" json:"lock_state"`
CreateAt int `xorm:"not null default 0 INT(10)" json:"create_at"`
UpdateAt int `xorm:"not null default 0 INT(11)" json:"update_at"`
ConfirmAt int `xorm:"not null default 0 INT(10)" json:"confirm_at"`
PvdSettleAt int `xorm:"not null default 0 INT(10)" json:"pvd_settle_at"`
SettleAt int `xorm:"not null default 0 INT(10)" json:"settle_at"`
SubsidyAt int `xorm:"not null default 0 INT(10)" json:"subsidy_at"`
BenefitList string `xorm:"not null default '' index VARCHAR(200)" json:"benefit_list"`
BenefitAll float64 `xorm:"not null default 0.00 FLOAT(8,2)" json:"benefit_all"`
Data string `xorm:"not null default '' VARCHAR(2000)" json:"data"`
UpdateFrom int `xorm:"not null default 0 TINYINT(1)" json:"update_from"`
CreateFrom int `xorm:"not null default 0 TINYINT(1)" json:"create_from"`
PvdPid string `xorm:"not null default '' index VARCHAR(100)" json:"pvd_pid"`
UserReturnMoney float64 `xorm:"not null default 0.000 FLOAT(8,3)" json:"user_return_money"`
ReturnMoneySettleAt int `xorm:"not null default 0 INT(10)" json:"return_money_settle_at"`
IsSetReduce int `json:"is_set_reduce" xorm:"default 0 comment('小口袋定制设置退回 0否 1是') INT(1)"`
}

+ 12
- 0
db/model/ord_list_relate.go View File

@@ -0,0 +1,12 @@
package model

type OrdListRelate struct {
Id int64 `json:"id" xorm:"pk autoincr BIGINT(20)"`
Oid int64 `json:"oid" xorm:"not null default 0 comment('订单号') index unique(IDX_ORD) BIGINT(20)"`
Uid int `json:"uid" xorm:"not null default 0 comment('用户ID') unique(IDX_ORD) index INT(10)"`
Amount float64 `json:"amount" xorm:"not null default 0.00 comment('金额') FLOAT(10,2)"`
Pvd string `json:"pvd" xorm:"not null default '' comment('供应商taobao,jd,pdd,vip,suning,kaola') index VARCHAR(8)"`
CreateAt int `json:"create_at" xorm:"not null default 0 comment('订单创建时间') index INT(10)"`
Level int `json:"level" xorm:"not null default 0 comment('0自购 1直推 大于1:间推') INT(10)"`
ReturnMoney float64 `json:"return_money" xorm:"not null default 0.00 comment('返现金额') DOUBLE(10,2)"`
}

+ 20
- 0
db/model/user_level_ord.go View File

@@ -0,0 +1,20 @@
package model

import (
"time"
)

type UserLevelOrd struct {
Id int64 `json:"id" xorm:"pk autoincr comment('订单id') BIGINT(22)"`
Uid int `json:"uid" xorm:"not null default 0 comment('uid') INT(10)"`
TaskId int `json:"task_id" xorm:"not null comment('任务id(对应 user_level_upgrade_task 中Id)') INT(11)"`
LevelId int `json:"level_id" xorm:"not null default 0 comment('等级id') INT(10)"`
PayAmount string `json:"pay_amount" xorm:"not null default 0 comment('付费金额') DECIMAL(2)"`
PayChannel int `json:"pay_channel" xorm:"not null default 0 comment('1:支付宝,2:微信,3:余额') TINYINT(1)"`
DateType int `json:"date_type" xorm:"not null default 0 comment('1:包月,2:包季,3:包年,4:永久') TINYINT(1)"`
State int `json:"state" xorm:"not null default 0 comment('支付状态:0未支付1已支付') TINYINT(1)"`
OrderType int `json:"order_type" xorm:"not null default 1 comment('订单类型(1是开通,2是续费)') TINYINT(3)"`
CreateAt time.Time `json:"create_at" xorm:"not null default CURRENT_TIMESTAMP comment('创建时间') TIMESTAMP"`
ExpireAt time.Time `json:"expire_at" xorm:"not null default CURRENT_TIMESTAMP comment('过期时间') TIMESTAMP"`
SettleAt int `json:"settle_at" xorm:" default 0 comment('平台结算时间') INT(11)"`
}

+ 11
- 0
go.mod View File

@@ -0,0 +1,11 @@
module code.fnuoos.com/go_rely_warehouse/zyos_go_condition_statistics.git

go 1.15

require (
github.com/syyongx/php2go v0.9.6
go.uber.org/zap v1.13.0
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f
gopkg.in/natefinch/lumberjack.v2 v2.0.0
xorm.io/xorm v1.3.1
)

+ 325
- 0
hdl/hdl_condition.go View File

@@ -0,0 +1,325 @@
package zyos_go_condition_hdl

import (
"code.fnuoos.com/go_rely_warehouse/zyos_go_condition_statistics.git/db"
"code.fnuoos.com/go_rely_warehouse/zyos_go_condition_statistics.git/db/model"
zhios_condition_statistics_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_condition_statistics.git/utils"
zhios_condition_statistics_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_condition_statistics.git/utils/logx"
"fmt"
"time"
"xorm.io/xorm"
)

// 累计自购数
func OwnBuyTotal(engine *xorm.Engine, uid interface{}, task map[string]string, t time.Time) string {

stime := time.Date(t.Year(), t.Month(), t.Day()-zhios_condition_statistics_utils.StrToInt(task["within_days"]), t.Hour(), 0, 0, 0, t.Location()).Unix()
etime := t.Unix()
//联盟结算后的
total, err := db.OrderListCountByUIDByOrderTypeByTime(engine, uid, 0, "3,5", stime, etime)
if err != nil {
zhios_condition_statistics_logx.Warn(err)
return ""
}
mallStime := time.Date(t.Year(), t.Month(), t.Day()-zhios_condition_statistics_utils.StrToInt(task["within_days"]), t.Hour(), 0, 0, 0, t.Location())
mallEtime := t
//确认收货的才算
mallTotal, err := db.MallOrdByTimeWithCount(engine, uid, 0, "3", mallStime.Format("2006-01-02 15:04:05"), mallEtime.Format("2006-01-02 15:04:05"))
if err != nil {
zhios_condition_statistics_logx.Warn(err)
return zhios_condition_statistics_utils.Int64ToStr(total)
}
total += mallTotal
return zhios_condition_statistics_utils.Int64ToStr(total)
}

// 累计已结算佣金
func SettleOrderSum(engine *xorm.Engine, uid interface{}, task map[string]string, t time.Time) string {

stime := time.Date(t.Year(), t.Month(), t.Day()-zhios_condition_statistics_utils.StrToInt(task["within_days"]), t.Hour(), 0, 0, 0, t.Location()).Unix()
etime := t.Unix()
// 用户分佣的订单
idAmountMap, err := db.OrderRelateListByTimeByState(engine, uid, "3,5", stime, etime)
if err != nil {
zhios_condition_statistics_logx.Warn(err)
return ""
}
var sum float64
for _, item := range *idAmountMap {
sum += item
}
mallStime := time.Date(t.Year(), t.Month(), t.Day()-zhios_condition_statistics_utils.StrToInt(task["within_days"]), t.Hour(), 0, 0, 0, t.Location())
mallEtime := t
_, mallSum, err := db.MallOrderRelateListByTimeByState(engine, uid, 3, mallStime, mallEtime)
if err != nil {
zhios_condition_statistics_logx.Warn(err)
return zhios_condition_statistics_utils.Float64ToStr(sum)
}
sum += mallSum
return zhios_condition_statistics_utils.Float64ToStr(sum)
}

func ExtendCount(engine *xorm.Engine, uid interface{}, task map[string]string, t time.Time) string {

// 累计直推人数
stime := time.Date(t.Year(), t.Month(), t.Day()-zhios_condition_statistics_utils.StrToInt(task["within_days"]), t.Hour(), 0, 0, 0, t.Location()).Format("2006-1-02 15:04:05")
etime := t.Format("2006-1-02 15:04:05")
sqlTpl := `SELECT count(*) as count
FROM user_profile as up
LEFT JOIN user as u ON u.uid=up.uid
WHERE %s;`
condStr := fmt.Sprintf("up.parent_uid=%s AND u.create_at>'%s' AND u.create_at<'%s'", zhios_condition_statistics_utils.AnyToString(uid), stime, etime)
sql := fmt.Sprintf(sqlTpl, condStr)
results, err := db.QueryNativeString(engine, sql)
if err != nil {
zhios_condition_statistics_logx.Warn(err)
return ""
}
count := ""
if len(results) > 0 {
count = zhios_condition_statistics_utils.AnyToString(results[0]["count"])
}
return count
}
func TeamCount(engine *xorm.Engine, uid interface{}, task map[string]string, t time.Time) string {

// 累计团队有效直推人数
stime := time.Date(t.Year(), t.Month(), t.Day()-zhios_condition_statistics_utils.StrToInt(task["within_days"]), t.Hour(), 0, 0, 0, t.Location()).Format("2006-1-02 15:04:05")
etime := t.Format("2006-1-02 15:04:05")
sqlTpl := `SELECT count(*) as count
FROM user_profile as up
LEFT JOIN user as u ON u.uid=up.uid
WHERE %s;`
condStr := fmt.Sprintf("up.parent_uid=%s AND u.create_at>'%s' AND u.create_at<'%s' and up.is_verify=%d", zhios_condition_statistics_utils.AnyToString(uid), stime, etime, 1)
sql := fmt.Sprintf(sqlTpl, condStr)
results, err := db.QueryNativeString(engine, sql)
if err != nil {
zhios_condition_statistics_logx.Warn(err)
return ""
}
count := ""
if len(results) > 0 {
count = zhios_condition_statistics_utils.AnyToString(results[0]["count"])
}
return count
}

// 累计团队符合相应等级的人数

func TeamByLvCount(engine *xorm.Engine, uid interface{}, task map[string]string, t time.Time) string {

stime := time.Date(t.Year(), t.Month(), t.Day()-zhios_condition_statistics_utils.StrToInt(task["within_days"]), t.Hour(), 0, 0, 0, t.Location()).Format("2006-1-02 15:04:05")
etime := t.Format("2006-1-02 15:04:05")
sqlTpl := `SELECT count(*) as count
FROM user_relate as ur
LEFT JOIN user as u ON u.uid=ur.uid
WHERE %s;`
condStr := fmt.Sprintf("ur.parent_uid=%s AND u.level='%s' AND u.create_at>'%s' AND u.create_at<'%s'", zhios_condition_statistics_utils.AnyToString(uid), task["task_type_level_id"], stime, etime)
sql := fmt.Sprintf(sqlTpl, condStr)
results, err := db.QueryNativeString(engine, sql)
if err != nil {
zhios_condition_statistics_logx.Warn(err)
return ""
}
count := ""
if len(results) > 0 {
count = zhios_condition_statistics_utils.AnyToString(results[0]["count"])
}
return count
}

// 累计直推符合相应等级的人数

func ExtendByLvCount(engine *xorm.Engine, uid interface{}, task map[string]string, t time.Time) string {

stime := time.Date(t.Year(), t.Month(), t.Day()-zhios_condition_statistics_utils.StrToInt(task["within_days"]), t.Hour(), 0, 0, 0, t.Location()).Format("2006-1-02 15:04:05")
etime := t.Format("2006-1-02 15:04:05")

sqlTpl := `SELECT count(*) as count
FROM user_relate as ur
LEFT JOIN user as u ON u.uid=ur.uid
WHERE %s;`
condStr := fmt.Sprintf("ur.parent_uid=%s AND ur.level=%s AND u.level='%s' AND u.create_at>'%s' AND u.create_at<'%s'", zhios_condition_statistics_utils.AnyToString(uid), "1", task["TaskTypeLevelId"], stime, etime)
sql := fmt.Sprintf(sqlTpl, condStr)
results, err := db.QueryNativeString(engine, sql)
if err != nil {
zhios_condition_statistics_logx.Warn(err)
return ""
}
count := ""
if len(results) > 0 {
count = zhios_condition_statistics_utils.AnyToString(results[0]["count"])
}
return count
}

//累计团队消费金额
func TeamBuySum(engine *xorm.Engine, uid interface{}, task map[string]string, t time.Time) string {

var total float64 = 0
if zhios_condition_statistics_utils.InArr(task["task_type_pvd"], []string{"0", "2", "8", "9"}) {
sqlTpl := `SELECT SUM(ol.cost_price) AS amount
FROM mall_ord_list_relate olr
JOIN mall_ord ol ON olr.oid = ol.ord_id
WHERE olr.uid = ?
AND ol.state =3 and olr.level>0 ?;
`
str := ""
if zhios_condition_statistics_utils.InArr(task["task_type_pvd"], []string{"8", "9"}) {
str += " and ol.order_type=" + task["task_type_pvd"]
}
result, err := db.QueryNativeString(engine, sqlTpl, uid, str)
if err == nil {
total += zhios_condition_statistics_utils.StrToFloat64(result[0]["amount"])
}
}
if zhios_condition_statistics_utils.InArr(task["task_type_pvd"], []string{"0", "3"}) {

o2oSqlTpl := `SELECT SUM(ol.cost_price) AS amount
FROM o2o_ord_list_relate olr
JOIN o2o_ord ol ON olr.oid = ol.ord_id
WHERE olr.uid = ?
AND ol.state =3 and olr.level>0;
`
o2oResult, err := db.QueryNativeString(engine, o2oSqlTpl, uid)
if err == nil {
total += zhios_condition_statistics_utils.StrToFloat64(o2oResult[0]["amount"])
}
}
if zhios_condition_statistics_utils.InArr(task["task_type_pvd"], []string{"0", "4"}) {

b2cSqlTpl := `SELECT SUM(ol.cost_price) AS amount
FROM b2c_ord_list_relate olr
JOIN b2c_ord ol ON olr.oid = ol.ord_id
WHERE olr.uid = ?
AND ol.state =3 and olr.level>0;
`
b2cResult, err := db.QueryNativeString(engine, b2cSqlTpl, uid)
if err == nil {
total += zhios_condition_statistics_utils.StrToFloat64(b2cResult[0]["amount"])
}
}
if zhios_condition_statistics_utils.InArr(task["task_type_pvd"], []string{"0", "1"}) {

guideSqlTpl := `SELECT SUM(ol.paid_price) AS amount
FROM ord_list_relate olr
JOIN ord_list ol ON olr.oid = ol.ord_id
WHERE olr.uid = ?
AND ol.state in(3,5) and olr.level>0;
`
guideResult, err := db.QueryNativeString(engine, guideSqlTpl, uid)
if err == nil {
total += zhios_condition_statistics_utils.StrToFloat64(guideResult[0]["amount"])
}
}
return zhios_condition_statistics_utils.Float64ToStr(zhios_condition_statistics_utils.FloatFormat(total, 2))
}

//小市场团队符合条件人数
func SmallTeamSum(engine *xorm.Engine, uid interface{}, task map[string]string, t time.Time) string {

//小市场团队符合条件人数
smallUid := TotalSmallTeam(engine, zhios_condition_statistics_utils.AnyToString(uid))
sqlTpl := `SELECT count(*) as count
FROM user_relate as ur
LEFT JOIN user as u ON u.uid=ur.uid
WHERE %s;`
condStr := fmt.Sprintf("ur.parent_uid=%s AND u.level='%s' ", smallUid, task["task_type_level_id"])
sql := fmt.Sprintf(sqlTpl, condStr)
results, err := db.QueryNativeString(engine, sql)
if err != nil {
zhios_condition_statistics_logx.Warn(err)
return ""
}
count := ""
if len(results) > 0 {
count = zhios_condition_statistics_utils.AnyToString(results[0]["count"])
}
return count
}
func ExtendStoreCount(engine *xorm.Engine, uid interface{}, task map[string]string, t time.Time) string {

if zhios_condition_statistics_utils.StrToInt(task["task_type_count"]) == 0 {
return "0"
}

if zhios_condition_statistics_utils.InArr(task["task_type_pvd"], []string{"1"}) { //o2o
sqlTpl := `SELECT os.id
FROM user_relate ur
LEFT JOIN o2o_merchant om ON ur.uid = om.uid
LEFT JOIN o2o_store os on om.id=os.store_manager
WHERE ur.parent_uid = ?
AND ur.level =1 ORDER BY ur.invite_time asc LIMIT 0,?;
`
var ids = make([]string, 0)
result, err := db.QueryNativeString(engine, sqlTpl, uid, task["task_type_count"])
if err == nil {
for _, v := range result {
ids = append(ids, v["id"])
}
}
if len(ids) > 0 {
sum, _ := engine.In("belong_store_id", ids).In("state", []string{"3", "4"}).Sum(&model.O2oOrd{}, "cost_price")
sum1, _ := engine.In("belong_store_id", ids).Sum(&model.O2oPayToMerchant{}, "actual_pay_amount")
return zhios_condition_statistics_utils.Float64ToStrByPrec(sum+sum1, 4)
}
}
if zhios_condition_statistics_utils.InArr(task["task_type_pvd"], []string{"2"}) { //b2c
sqlTpl := `SELECT os.id
FROM user_relate ur
LEFT JOIN o2o_merchant om ON ur.uid = om.uid
LEFT JOIN b2c_ord os on om.id=os.store_manager
WHERE ur.parent_uid = ?
AND ur.level =1 ORDER BY ur.invite_time asc LIMIT 0,?;
`
var ids = make([]string, 0)
result, err := db.QueryNativeString(engine, sqlTpl, uid, task["task_type_count"])
if err == nil {
for _, v := range result {
ids = append(ids, v["id"])
}
}
if len(ids) > 0 {
sum, _ := engine.In("belong_store_id", ids).In("state", []string{"4"}).Sum(&model.B2cOrd{}, "cost_price")
return zhios_condition_statistics_utils.Float64ToStrByPrec(sum, 4)
}
}
return "0"
}
func PayData(engine *xorm.Engine, uid interface{}, task map[string]string, t time.Time, hasPay bool, payOrdId int64) (string, bool, int64) {
hasPay = true
//TODO::根据 RegionalAgentSchemeTask 表中的 task_id 判断是否完成付费任务
regionalAgentUserOrd, err := db.UserLevelOrderByTaskId(engine, zhios_condition_statistics_utils.AnyToString(uid), task["id"])
if err != nil {
_ = zhios_condition_statistics_logx.Warn(err)
return "", hasPay, payOrdId
}
if regionalAgentUserOrd != nil {
if regionalAgentUserOrd.ExpireAt.Unix() < t.Unix() && regionalAgentUserOrd.CreateAt.Format("2006-01-02 15:04:05") != regionalAgentUserOrd.ExpireAt.Format("2006-01-02 15:04:05") && regionalAgentUserOrd.DateType != 4 {
return "0", hasPay, payOrdId
}
payOrdId = regionalAgentUserOrd.Id
return "1", hasPay, payOrdId
} else {
return "0", hasPay, payOrdId
}

return "1", hasPay, payOrdId
}

func TotalSmallTeam(eg *xorm.Engine, uid string) string {

sqlTpl := `SELECT sum(cstp.team_all_ord_price)+sum(cstp.my_ord_price) as amount,u.uid
FROM user_profile u
LEFT JOIN more_mall_outstanding_achievement cstp ON (cstp.uid =u.uid)
WHERE u.parent_uid=%s GROUP BY u.uid ORDER BY amount desc,u.uid asc`
sql := fmt.Sprintf(sqlTpl, uid)
results, err := db.QueryNativeString(eg, sql)
if err != nil {
return "0"
}
if len(results) > 1 {
return results[1]["uid"]
}
return "0"
}

+ 366
- 0
utils/convert.go View File

@@ -0,0 +1,366 @@
package zhios_condition_statistics_utils

import (
"encoding/binary"
"encoding/json"
"fmt"
"math"
"strconv"
"strings"
)

func ToString(raw interface{}, e error) (res string) {
if e != nil {
return ""
}
return AnyToString(raw)
}

func ToInt64(raw interface{}, e error) int64 {
if e != nil {
return 0
}
return AnyToInt64(raw)
}

func AnyToBool(raw interface{}) bool {
switch i := raw.(type) {
case float32, float64, int, int64, uint, uint8, uint16, uint32, uint64, int8, int16, int32:
return i != 0
case []byte:
return i != nil
case string:
if i == "false" {
return false
}
return i != ""
case error:
return false
case nil:
return true
}
val := fmt.Sprint(raw)
val = strings.TrimLeft(val, "&")
if strings.TrimLeft(val, "{}") == "" {
return false
}
if strings.TrimLeft(val, "[]") == "" {
return false
}
// ptr type
b, err := json.Marshal(raw)
if err != nil {
return false
}
if strings.TrimLeft(string(b), "\"\"") == "" {
return false
}
if strings.TrimLeft(string(b), "{}") == "" {
return false
}
return true
}

func AnyToInt64(raw interface{}) int64 {
switch i := raw.(type) {
case string:
res, _ := strconv.ParseInt(i, 10, 64)
return res
case []byte:
return BytesToInt64(i)
case int:
return int64(i)
case int64:
return i
case uint:
return int64(i)
case uint8:
return int64(i)
case uint16:
return int64(i)
case uint32:
return int64(i)
case uint64:
return int64(i)
case int8:
return int64(i)
case int16:
return int64(i)
case int32:
return int64(i)
case float32:
return int64(i)
case float64:
return int64(i)
case error:
return 0
case bool:
if i {
return 1
}
return 0
}
return 0
}

func AnyToString(raw interface{}) string {
switch i := raw.(type) {
case []byte:
return string(i)
case int:
return strconv.FormatInt(int64(i), 10)
case int64:
return strconv.FormatInt(i, 10)
case float32:
return Float64ToStr(float64(i))
case float64:
return Float64ToStr(i)
case uint:
return strconv.FormatInt(int64(i), 10)
case uint8:
return strconv.FormatInt(int64(i), 10)
case uint16:
return strconv.FormatInt(int64(i), 10)
case uint32:
return strconv.FormatInt(int64(i), 10)
case uint64:
return strconv.FormatInt(int64(i), 10)
case int8:
return strconv.FormatInt(int64(i), 10)
case int16:
return strconv.FormatInt(int64(i), 10)
case int32:
return strconv.FormatInt(int64(i), 10)
case string:
return i
case error:
return i.Error()
case bool:
return strconv.FormatBool(i)
}
return fmt.Sprintf("%#v", raw)
}

func AnyToFloat64(raw interface{}) float64 {
switch i := raw.(type) {
case []byte:
f, _ := strconv.ParseFloat(string(i), 64)
return f
case int:
return float64(i)
case int64:
return float64(i)
case float32:
return float64(i)
case float64:
return i
case uint:
return float64(i)
case uint8:
return float64(i)
case uint16:
return float64(i)
case uint32:
return float64(i)
case uint64:
return float64(i)
case int8:
return float64(i)
case int16:
return float64(i)
case int32:
return float64(i)
case string:
f, _ := strconv.ParseFloat(i, 64)
return f
case bool:
if i {
return 1
}
}
return 0
}

func ToByte(raw interface{}, e error) []byte {
if e != nil {
return []byte{}
}
switch i := raw.(type) {
case string:
return []byte(i)
case int:
return Int64ToBytes(int64(i))
case int64:
return Int64ToBytes(i)
case float32:
return Float32ToByte(i)
case float64:
return Float64ToByte(i)
case uint:
return Int64ToBytes(int64(i))
case uint8:
return Int64ToBytes(int64(i))
case uint16:
return Int64ToBytes(int64(i))
case uint32:
return Int64ToBytes(int64(i))
case uint64:
return Int64ToBytes(int64(i))
case int8:
return Int64ToBytes(int64(i))
case int16:
return Int64ToBytes(int64(i))
case int32:
return Int64ToBytes(int64(i))
case []byte:
return i
case error:
return []byte(i.Error())
case bool:
if i {
return []byte("true")
}
return []byte("false")
}
return []byte(fmt.Sprintf("%#v", raw))
}

func Int64ToBytes(i int64) []byte {
var buf = make([]byte, 8)
binary.BigEndian.PutUint64(buf, uint64(i))
return buf
}

func BytesToInt64(buf []byte) int64 {
return int64(binary.BigEndian.Uint64(buf))
}

func StrToInt(s string) int {
res, _ := strconv.Atoi(s)
return res
}

func StrToInt64(s string) int64 {
res, _ := strconv.ParseInt(s, 10, 64)
return res
}

func Float32ToByte(float float32) []byte {
bits := math.Float32bits(float)
bytes := make([]byte, 4)
binary.LittleEndian.PutUint32(bytes, bits)

return bytes
}

func ByteToFloat32(bytes []byte) float32 {
bits := binary.LittleEndian.Uint32(bytes)
return math.Float32frombits(bits)
}

func Float64ToByte(float float64) []byte {
bits := math.Float64bits(float)
bytes := make([]byte, 8)
binary.LittleEndian.PutUint64(bytes, bits)
return bytes
}

func ByteToFloat64(bytes []byte) float64 {
bits := binary.LittleEndian.Uint64(bytes)
return math.Float64frombits(bits)
}

func Float64ToStr(f float64) string {
return strconv.FormatFloat(f, 'f', 2, 64)
}
func Float64ToStrPrec1(f float64) string {
return strconv.FormatFloat(f, 'f', 1, 64)
}
func Float64ToStrByPrec(f float64, prec int) string {
return strconv.FormatFloat(f, 'f', prec, 64)
}

func Float32ToStr(f float32) string {
return Float64ToStr(float64(f))
}

func StrToFloat64(s string) float64 {
res, err := strconv.ParseFloat(s, 64)
if err != nil {
return 0
}
return res
}
func StrToFormat(s string, prec int) string {
ex := strings.Split(s, ".")
if len(ex) == 2 {
if StrToFloat64(ex[1]) == 0 { //小数点后面为空就是不要小数点了
return ex[0]
}
//看取多少位
str := ex[1]
str1 := str
if prec < len(str) {
str1 = str[0:prec]
} else {
for i := 0; i < prec-len(str); i++ {
str1 += "0"
}
}
if prec > 0 {
return ex[0] + "." + str1
} else {
return ex[0]
}
}
return s
}

func StrToFloat32(s string) float32 {
res, err := strconv.ParseFloat(s, 32)
if err != nil {
return 0
}
return float32(res)
}

func StrToBool(s string) bool {
b, _ := strconv.ParseBool(s)
return b
}

func BoolToStr(b bool) string {
if b {
return "true"
}
return "false"
}

func FloatToInt64(f float64) int64 {
return int64(f)
}

func IntToStr(i int) string {
return strconv.Itoa(i)
}

func Int64ToStr(i int64) string {
return strconv.FormatInt(i, 10)
}

func IntToFloat64(i int) float64 {
s := strconv.Itoa(i)
res, err := strconv.ParseFloat(s, 64)
if err != nil {
return 0
}
return res
}
func Int64ToFloat64(i int64) float64 {
s := strconv.FormatInt(i, 10)
res, err := strconv.ParseFloat(s, 64)
if err != nil {
return 0
}
return res
}

+ 209
- 0
utils/curl.go View File

@@ -0,0 +1,209 @@
package zhios_condition_statistics_utils

import (
"bytes"
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"sort"
"strings"
"time"
)

var CurlDebug bool

func CurlGet(router string, header map[string]string) ([]byte, error) {
return curl(http.MethodGet, router, nil, header)
}
func CurlGetJson(router string, body interface{}, header map[string]string) ([]byte, error) {
return curl_new(http.MethodGet, router, body, header)
}

// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string
func CurlPost(router string, body interface{}, header map[string]string) ([]byte, error) {
return curl(http.MethodPost, router, body, header)
}

func CurlPut(router string, body interface{}, header map[string]string) ([]byte, error) {
return curl(http.MethodPut, router, body, header)
}

// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string
func CurlPatch(router string, body interface{}, header map[string]string) ([]byte, error) {
return curl(http.MethodPatch, router, body, header)
}

// CurlDelete is curl delete
func CurlDelete(router string, body interface{}, header map[string]string) ([]byte, error) {
return curl(http.MethodDelete, router, body, header)
}

func curl(method, router string, body interface{}, header map[string]string) ([]byte, error) {
var reqBody io.Reader
contentType := "application/json"
switch v := body.(type) {
case string:
reqBody = strings.NewReader(v)
case []byte:
reqBody = bytes.NewReader(v)
case map[string]string:
val := url.Values{}
for k, v := range v {
val.Set(k, v)
}
reqBody = strings.NewReader(val.Encode())
contentType = "application/x-www-form-urlencoded"
case map[string]interface{}:
val := url.Values{}
for k, v := range v {
val.Set(k, v.(string))
}
reqBody = strings.NewReader(val.Encode())
contentType = "application/x-www-form-urlencoded"
}
if header == nil {
header = map[string]string{"Content-Type": contentType}
}
if _, ok := header["Content-Type"]; !ok {
header["Content-Type"] = contentType
}
resp, er := CurlReq(method, router, reqBody, header)
if er != nil {
return nil, er
}
res, err := ioutil.ReadAll(resp.Body)
if CurlDebug {
blob := SerializeStr(body)
if contentType != "application/json" {
blob = HttpBuild(body)
}
fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n",
router,
time.Now().Format("2006-01-02 15:04:05.000"),
method,
contentType,
HttpBuildQuery(header),
blob,
err,
SerializeStr(resp.Header),
string(res),
)
}
resp.Body.Close()
return res, err
}

func curl_new(method, router string, body interface{}, header map[string]string) ([]byte, error) {
var reqBody io.Reader
contentType := "application/json"

if header == nil {
header = map[string]string{"Content-Type": contentType}
}
if _, ok := header["Content-Type"]; !ok {
header["Content-Type"] = contentType
}
resp, er := CurlReq(method, router, reqBody, header)
if er != nil {
return nil, er
}
res, err := ioutil.ReadAll(resp.Body)
if CurlDebug {
blob := SerializeStr(body)
if contentType != "application/json" {
blob = HttpBuild(body)
}
fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n",
router,
time.Now().Format("2006-01-02 15:04:05.000"),
method,
contentType,
HttpBuildQuery(header),
blob,
err,
SerializeStr(resp.Header),
string(res),
)
}
resp.Body.Close()
return res, err
}

func CurlReq(method, router string, reqBody io.Reader, header map[string]string) (*http.Response, error) {
req, _ := http.NewRequest(method, router, reqBody)
if header != nil {
for k, v := range header {
req.Header.Set(k, v)
}
}
// 绕过github等可能因为特征码返回503问题
// https://www.imwzk.com/posts/2021-03-14-why-i-always-get-503-with-golang/
defaultCipherSuites := []uint16{0xc02f, 0xc030, 0xc02b, 0xc02c, 0xcca8, 0xcca9, 0xc013, 0xc009,
0xc014, 0xc00a, 0x009c, 0x009d, 0x002f, 0x0035, 0xc012, 0x000a}
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
CipherSuites: append(defaultCipherSuites[8:], defaultCipherSuites[:8]...),
},
},
// 获取301重定向
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
return client.Do(req)
}

// 组建get请求参数,sortAsc true为小到大,false为大到小,nil不排序 a=123&b=321
func HttpBuildQuery(args map[string]string, sortAsc ...bool) string {
str := ""
if len(args) == 0 {
return str
}
if len(sortAsc) > 0 {
keys := make([]string, 0, len(args))
for k := range args {
keys = append(keys, k)
}
if sortAsc[0] {
sort.Strings(keys)
} else {
sort.Sort(sort.Reverse(sort.StringSlice(keys)))
}
for _, k := range keys {
str += "&" + k + "=" + args[k]
}
} else {
for k, v := range args {
str += "&" + k + "=" + v
}
}
return str[1:]
}

func HttpBuild(body interface{}, sortAsc ...bool) string {
params := map[string]string{}
if args, ok := body.(map[string]interface{}); ok {
for k, v := range args {
params[k] = AnyToString(v)
}
return HttpBuildQuery(params, sortAsc...)
}
if args, ok := body.(map[string]string); ok {
for k, v := range args {
params[k] = AnyToString(v)
}
return HttpBuildQuery(params, sortAsc...)
}
if args, ok := body.(map[string]int); ok {
for k, v := range args {
params[k] = AnyToString(v)
}
return HttpBuildQuery(params, sortAsc...)
}
return AnyToString(body)
}

+ 22
- 0
utils/file.go View File

@@ -0,0 +1,22 @@
package zhios_condition_statistics_utils

import (
"os"
"path"
"strings"
"time"
)

// 获取文件后缀
func FileExt(fname string) string {
return strings.ToLower(strings.TrimLeft(path.Ext(fname), "."))
}

func FilePutContents(fileName string, content string) {
fd, _ := os.OpenFile("./tmp/"+fileName+".logs", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
fd_time := time.Now().Format("2006-01-02 15:04:05")
fd_content := strings.Join([]string{"[", fd_time, "] ", content, "\n"}, "")
buf := []byte(fd_content)
fd.Write(buf)
fd.Close()
}

+ 59
- 0
utils/format.go View File

@@ -0,0 +1,59 @@
package zhios_condition_statistics_utils

import (
"math"
)

func CouponFormat(data string) string {
switch data {
case "0.00", "0", "":
return ""
default:
return Int64ToStr(FloatToInt64(StrToFloat64(data)))
}
}
func CommissionFormat(data string) string {
if data != "" && data != "0" {
return data
}

return ""
}

func HideString(src string, hLen int) string {
str := []rune(src)
if hLen == 0 {
hLen = 4
}
hideStr := ""
for i := 0; i < hLen; i++ {
hideStr += "*"
}
hideLen := len(str) / 2
showLen := len(str) - hideLen
if hideLen == 0 || showLen == 0 {
return hideStr
}
subLen := showLen / 2
if subLen == 0 {
return string(str[:showLen]) + hideStr
}
s := string(str[:subLen])
s += hideStr
s += string(str[len(str)-subLen:])
return s
}

//SaleCountFormat is 格式化销量
func SaleCountFormat(s string) string {
return s + "已售"
}

// 小数格式化
func FloatFormat(f float64, i int) float64 {
if i > 14 {
return f
}
p := math.Pow10(i)
return float64(int64((f+0.000000000000009)*p)) / p
}

+ 245
- 0
utils/logx/log.go View File

@@ -0,0 +1,245 @@
package zhios_condition_statistics_logx

import (
"os"
"strings"
"time"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

type LogConfig struct {
AppName string `yaml:"app_name" json:"app_name" toml:"app_name"`
Level string `yaml:"level" json:"level" toml:"level"`
StacktraceLevel string `yaml:"stacktrace_level" json:"stacktrace_level" toml:"stacktrace_level"`
IsStdOut bool `yaml:"is_stdout" json:"is_stdout" toml:"is_stdout"`
TimeFormat string `yaml:"time_format" json:"time_format" toml:"time_format"` // second, milli, nano, standard, iso,
Encoding string `yaml:"encoding" json:"encoding" toml:"encoding"` // console, json
Skip int `yaml:"skip" json:"skip" toml:"skip"`

IsFileOut bool `yaml:"is_file_out" json:"is_file_out" toml:"is_file_out"`
FileDir string `yaml:"file_dir" json:"file_dir" toml:"file_dir"`
FileName string `yaml:"file_name" json:"file_name" toml:"file_name"`
FileMaxSize int `yaml:"file_max_size" json:"file_max_size" toml:"file_max_size"`
FileMaxAge int `yaml:"file_max_age" json:"file_max_age" toml:"file_max_age"`
}

var (
l *LogX = defaultLogger()
conf *LogConfig
)

// default logger setting
func defaultLogger() *LogX {
conf = &LogConfig{
Level: "debug",
StacktraceLevel: "error",
IsStdOut: true,
TimeFormat: "standard",
Encoding: "console",
Skip: 2,
}
writers := []zapcore.WriteSyncer{os.Stdout}
lg, lv := newZapLogger(setLogLevel(conf.Level), setLogLevel(conf.StacktraceLevel), conf.Encoding, conf.TimeFormat, conf.Skip, zapcore.NewMultiWriteSyncer(writers...))
zap.RedirectStdLog(lg)
return &LogX{logger: lg, atomLevel: lv}
}

// initial standard log, if you don't init, it will use default logger setting
func InitDefaultLogger(cfg *LogConfig) {
var writers []zapcore.WriteSyncer
if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) {
writers = append(writers, os.Stdout)
}
if cfg.IsFileOut {
writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge))
}

lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...))
zap.RedirectStdLog(lg)
if cfg.AppName != "" {
lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称
}
l = &LogX{logger: lg, atomLevel: lv}
}

// create a new logger
func NewLogger(cfg *LogConfig) *LogX {
var writers []zapcore.WriteSyncer
if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) {
writers = append(writers, os.Stdout)
}
if cfg.IsFileOut {
writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge))
}

lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...))
zap.RedirectStdLog(lg)
if cfg.AppName != "" {
lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称
}
return &LogX{logger: lg, atomLevel: lv}
}

// create a new zaplog logger
func newZapLogger(level, stacktrace zapcore.Level, encoding, timeType string, skip int, output zapcore.WriteSyncer) (*zap.Logger, *zap.AtomicLevel) {
encCfg := zapcore.EncoderConfig{
TimeKey: "T",
LevelKey: "L",
NameKey: "N",
CallerKey: "C",
MessageKey: "M",
StacktraceKey: "S",
LineEnding: zapcore.DefaultLineEnding,
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeDuration: zapcore.NanosDurationEncoder,
EncodeLevel: zapcore.LowercaseLevelEncoder,
}
setTimeFormat(timeType, &encCfg) // set time type
atmLvl := zap.NewAtomicLevel() // set level
atmLvl.SetLevel(level)
encoder := zapcore.NewJSONEncoder(encCfg) // 确定encoder格式
if encoding == "console" {
encoder = zapcore.NewConsoleEncoder(encCfg)
}
return zap.New(zapcore.NewCore(encoder, output, atmLvl), zap.AddCaller(), zap.AddStacktrace(stacktrace), zap.AddCallerSkip(skip)), &atmLvl
}

// set log level
func setLogLevel(lvl string) zapcore.Level {
switch strings.ToLower(lvl) {
case "panic":
return zapcore.PanicLevel
case "fatal":
return zapcore.FatalLevel
case "error":
return zapcore.ErrorLevel
case "warn", "warning":
return zapcore.WarnLevel
case "info":
return zapcore.InfoLevel
default:
return zapcore.DebugLevel
}
}

// set time format
func setTimeFormat(timeType string, z *zapcore.EncoderConfig) {
switch strings.ToLower(timeType) {
case "iso": // iso8601 standard
z.EncodeTime = zapcore.ISO8601TimeEncoder
case "sec": // only for unix second, without millisecond
z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendInt64(t.Unix())
}
case "second": // unix second, with millisecond
z.EncodeTime = zapcore.EpochTimeEncoder
case "milli", "millisecond": // millisecond
z.EncodeTime = zapcore.EpochMillisTimeEncoder
case "nano", "nanosecond": // nanosecond
z.EncodeTime = zapcore.EpochNanosTimeEncoder
default: // standard format
z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
}
}
}

func GetLevel() string {
switch l.atomLevel.Level() {
case zapcore.PanicLevel:
return "panic"
case zapcore.FatalLevel:
return "fatal"
case zapcore.ErrorLevel:
return "error"
case zapcore.WarnLevel:
return "warn"
case zapcore.InfoLevel:
return "info"
default:
return "debug"
}
}

func SetLevel(lvl string) {
l.atomLevel.SetLevel(setLogLevel(lvl))
}

// temporary add call skip
func AddCallerSkip(skip int) *LogX {
l.logger.WithOptions(zap.AddCallerSkip(skip))
return l
}

// permanent add call skip
func AddDepth(skip int) *LogX {
l.logger = l.logger.WithOptions(zap.AddCallerSkip(skip))
return l
}

// permanent add options
func AddOptions(opts ...zap.Option) *LogX {
l.logger = l.logger.WithOptions(opts...)
return l
}

func AddField(k string, v interface{}) {
l.logger.With(zap.Any(k, v))
}

func AddFields(fields map[string]interface{}) *LogX {
for k, v := range fields {
l.logger.With(zap.Any(k, v))
}
return l
}

// Normal log
func Debug(e interface{}, args ...interface{}) error {
return l.Debug(e, args...)
}
func Info(e interface{}, args ...interface{}) error {
return l.Info(e, args...)
}
func Warn(e interface{}, args ...interface{}) error {
return l.Warn(e, args...)
}
func Error(e interface{}, args ...interface{}) error {
return l.Error(e, args...)
}
func Panic(e interface{}, args ...interface{}) error {
return l.Panic(e, args...)
}
func Fatal(e interface{}, args ...interface{}) error {
return l.Fatal(e, args...)
}

// Format logs
func Debugf(format string, args ...interface{}) error {
return l.Debugf(format, args...)
}
func Infof(format string, args ...interface{}) error {
return l.Infof(format, args...)
}
func Warnf(format string, args ...interface{}) error {
return l.Warnf(format, args...)
}
func Errorf(format string, args ...interface{}) error {
return l.Errorf(format, args...)
}
func Panicf(format string, args ...interface{}) error {
return l.Panicf(format, args...)
}
func Fatalf(format string, args ...interface{}) error {
return l.Fatalf(format, args...)
}

func formatFieldMap(m FieldMap) []Field {
var res []Field
for k, v := range m {
res = append(res, zap.Any(k, v))
}
return res
}

+ 105
- 0
utils/logx/output.go View File

@@ -0,0 +1,105 @@
package zhios_condition_statistics_logx

import (
"bytes"
"io"
"os"
"path/filepath"
"time"

"gopkg.in/natefinch/lumberjack.v2"
)

// output interface
type WriteSyncer interface {
io.Writer
Sync() error
}

// split writer
func NewRollingFile(dir, filename string, maxSize, MaxAge int) WriteSyncer {
s, err := os.Stat(dir)
if err != nil || !s.IsDir() {
os.RemoveAll(dir)
if err := os.MkdirAll(dir, 0766); err != nil {
panic(err)
}
}
return newLumberjackWriteSyncer(&lumberjack.Logger{
Filename: filepath.Join(dir, filename),
MaxSize: maxSize, // megabytes, MB
MaxAge: MaxAge, // days
LocalTime: true,
Compress: false,
})
}

type lumberjackWriteSyncer struct {
*lumberjack.Logger
buf *bytes.Buffer
logChan chan []byte
closeChan chan interface{}
maxSize int
}

func newLumberjackWriteSyncer(l *lumberjack.Logger) *lumberjackWriteSyncer {
ws := &lumberjackWriteSyncer{
Logger: l,
buf: bytes.NewBuffer([]byte{}),
logChan: make(chan []byte, 5000),
closeChan: make(chan interface{}),
maxSize: 1024,
}
go ws.run()
return ws
}

func (l *lumberjackWriteSyncer) run() {
ticker := time.NewTicker(1 * time.Second)

for {
select {
case <-ticker.C:
if l.buf.Len() > 0 {
l.sync()
}
case bs := <-l.logChan:
_, err := l.buf.Write(bs)
if err != nil {
continue
}
if l.buf.Len() > l.maxSize {
l.sync()
}
case <-l.closeChan:
l.sync()
return
}
}
}

func (l *lumberjackWriteSyncer) Stop() {
close(l.closeChan)
}

func (l *lumberjackWriteSyncer) Write(bs []byte) (int, error) {
b := make([]byte, len(bs))
for i, c := range bs {
b[i] = c
}
l.logChan <- b
return 0, nil
}

func (l *lumberjackWriteSyncer) Sync() error {
return nil
}

func (l *lumberjackWriteSyncer) sync() error {
defer l.buf.Reset()
_, err := l.Logger.Write(l.buf.Bytes())
if err != nil {
return err
}
return nil
}

+ 192
- 0
utils/logx/sugar.go View File

@@ -0,0 +1,192 @@
package zhios_condition_statistics_logx

import (
"errors"
"fmt"
"strconv"

"go.uber.org/zap"
)

type LogX struct {
logger *zap.Logger
atomLevel *zap.AtomicLevel
}

type Field = zap.Field
type FieldMap map[string]interface{}

// 判断其他类型--start
func getFields(msg string, format bool, args ...interface{}) (string, []Field) {
var str []interface{}
var fields []zap.Field
if len(args) > 0 {
for _, v := range args {
if f, ok := v.(Field); ok {
fields = append(fields, f)
} else if f, ok := v.(FieldMap); ok {
fields = append(fields, formatFieldMap(f)...)
} else {
str = append(str, AnyToString(v))
}
}
if format {
return fmt.Sprintf(msg, str...), fields
}
str = append([]interface{}{msg}, str...)
return fmt.Sprintln(str...), fields
}
return msg, []Field{}
}

func (l *LogX) Debug(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Debug(msg, field...)
}
return e
}
func (l *LogX) Info(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Info(msg, field...)
}
return e
}
func (l *LogX) Warn(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Warn(msg, field...)
}
return e
}
func (l *LogX) Error(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Error(msg, field...)
}
return e
}
func (l *LogX) DPanic(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.DPanic(msg, field...)
}
return e
}
func (l *LogX) Panic(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Panic(msg, field...)
}
return e
}
func (l *LogX) Fatal(s interface{}, args ...interface{}) error {
es, e := checkErr(s)
if es != "" {
msg, field := getFields(es, false, args...)
l.logger.Fatal(msg, field...)
}
return e
}

func checkErr(s interface{}) (string, error) {
switch e := s.(type) {
case error:
return e.Error(), e
case string:
return e, errors.New(e)
case []byte:
return string(e), nil
default:
return "", nil
}
}

func (l *LogX) LogError(err error) error {
return l.Error(err.Error())
}

func (l *LogX) Debugf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Debug(s, f...)
return errors.New(s)
}

func (l *LogX) Infof(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Info(s, f...)
return errors.New(s)
}

func (l *LogX) Warnf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Warn(s, f...)
return errors.New(s)
}

func (l *LogX) Errorf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Error(s, f...)
return errors.New(s)
}

func (l *LogX) DPanicf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.DPanic(s, f...)
return errors.New(s)
}

func (l *LogX) Panicf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Panic(s, f...)
return errors.New(s)
}

func (l *LogX) Fatalf(msg string, args ...interface{}) error {
s, f := getFields(msg, true, args...)
l.logger.Fatal(s, f...)
return errors.New(s)
}

func AnyToString(raw interface{}) string {
switch i := raw.(type) {
case []byte:
return string(i)
case int:
return strconv.FormatInt(int64(i), 10)
case int64:
return strconv.FormatInt(i, 10)
case float32:
return strconv.FormatFloat(float64(i), 'f', 2, 64)
case float64:
return strconv.FormatFloat(i, 'f', 2, 64)
case uint:
return strconv.FormatInt(int64(i), 10)
case uint8:
return strconv.FormatInt(int64(i), 10)
case uint16:
return strconv.FormatInt(int64(i), 10)
case uint32:
return strconv.FormatInt(int64(i), 10)
case uint64:
return strconv.FormatInt(int64(i), 10)
case int8:
return strconv.FormatInt(int64(i), 10)
case int16:
return strconv.FormatInt(int64(i), 10)
case int32:
return strconv.FormatInt(int64(i), 10)
case string:
return i
case error:
return i.Error()
}
return fmt.Sprintf("%#v", raw)
}

+ 23
- 0
utils/serialize.go View File

@@ -0,0 +1,23 @@
package zhios_condition_statistics_utils

import (
"encoding/json"
)

func Serialize(data interface{}) []byte {
res, err := json.Marshal(data)
if err != nil {
return []byte{}
}
return res
}

func Unserialize(b []byte, dst interface{}) {
if err := json.Unmarshal(b, dst); err != nil {
dst = nil
}
}

func SerializeStr(data interface{}, arg ...interface{}) string {
return string(Serialize(data))
}

+ 203
- 0
utils/string.go View File

@@ -0,0 +1,203 @@
package zhios_condition_statistics_utils

import (
"fmt"
"github.com/syyongx/php2go"
"math/rand"
"reflect"
"sort"
"strings"
"time"
)

func Implode(glue string, args ...interface{}) string {
data := make([]string, len(args))
for i, s := range args {
data[i] = fmt.Sprint(s)
}
return strings.Join(data, glue)
}

//字符串是否在数组里
func InArr(target string, str_array []string) bool {
for _, element := range str_array {
if target == element {
return true
}
}
return false
}
func InArrToInt(target int, str_array []int) bool {
for _, element := range str_array {
if target == element {
return true
}
}
return false
}

//把数组的值放到key里
func ArrayColumn(array interface{}, key string) (result map[string]interface{}, err error) {
result = make(map[string]interface{})
t := reflect.TypeOf(array)
v := reflect.ValueOf(array)
if t.Kind() != reflect.Slice {
return nil, nil
}
if v.Len() == 0 {
return nil, nil
}
for i := 0; i < v.Len(); i++ {
indexv := v.Index(i)
if indexv.Type().Kind() != reflect.Struct {
return nil, nil
}
mapKeyInterface := indexv.FieldByName(key)
if mapKeyInterface.Kind() == reflect.Invalid {
return nil, nil
}
mapKeyString, err := InterfaceToString(mapKeyInterface.Interface())
if err != nil {
return nil, err
}
result[mapKeyString] = indexv.Interface()
}
return result, err
}

//转string
func InterfaceToString(v interface{}) (result string, err error) {
switch reflect.TypeOf(v).Kind() {
case reflect.Int64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
result = fmt.Sprintf("%v", v)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
result = fmt.Sprintf("%v", v)
case reflect.String:
result = v.(string)
default:
err = nil
}
return result, err
}

func HideTrueName(name string) string {
res := "**"
if name != "" {
runs := []rune(name)
leng := len(runs)
if leng <= 3 {
res = string(runs[0:1]) + res
} else if leng < 5 {
res = string(runs[0:2]) + res
} else if leng < 10 {
res = string(runs[0:2]) + "***" + string(runs[leng-2:leng])
} else if leng < 16 {
res = string(runs[0:3]) + "****" + string(runs[leng-3:leng])
} else {
res = string(runs[0:4]) + "*****" + string(runs[leng-4:leng])
}
}
return res
}

func GetQueryParam(uri string) map[string]string {
//根据问号分割路由还是query参数
uriList := strings.Split(uri, "?")
var query = make(map[string]string, 0)
//有参数才处理
if len(uriList) == 2 {
//分割query参数
var queryList = strings.Split(uriList[1], "&")
if len(queryList) > 0 {
//key value 分别赋值
for _, v := range queryList {
var valueList = strings.Split(v, "=")
if len(valueList) == 2 {
value, _ := php2go.URLDecode(valueList[1])
if value == "" {
value = valueList[1]
}
query[valueList[0]] = value
}
}
}
}
return query
}

//JoinStringsInASCII 按照规则,参数名ASCII码从小到大排序后拼接
//data 待拼接的数据
//sep 连接符
//onlyValues 是否只包含参数值,true则不包含参数名,否则参数名和参数值均有
//includeEmpty 是否包含空值,true则包含空值,否则不包含,注意此参数不影响参数名的存在
//exceptKeys 被排除的参数名,不参与排序及拼接
func JoinStringsInASCII(data map[string]string, sep string, onlyValues, includeEmpty bool, exceptKeys ...string) string {
var list []string
var keyList []string
m := make(map[string]int)
if len(exceptKeys) > 0 {
for _, except := range exceptKeys {
m[except] = 1
}
}
for k := range data {
if _, ok := m[k]; ok {
continue
}
value := data[k]
if !includeEmpty && value == "" {
continue
}
if onlyValues {
keyList = append(keyList, k)
} else {
list = append(list, fmt.Sprintf("%s=%s", k, value))
}
}
if onlyValues {
sort.Strings(keyList)
for _, v := range keyList {
list = append(list, AnyToString(data[v]))
}
} else {
sort.Strings(list)
}
return strings.Join(list, sep)
}

//x的y次方
func RandPow(l int) string {
var i = "1"
for j := 0; j < l; j++ {
i += "0"
}
k := StrToInt64(i)
n := rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(k)
ls := "%0" + IntToStr(l) + "v"
str := fmt.Sprintf(ls, n)
//min := int(math.Pow10(l - 1))
//max := int(math.Pow10(l) - 1)
return str
}

//根据显示长度截取字符串
func ShowSubstr(s string, l int) string {
if len(s) <= l {
return s
}
ss, sl, rl, rs := "", 0, 0, []rune(s)
for _, r := range rs {
rint := int(r)
if rint < 128 {
rl = 1
} else {
rl = 2
}
if sl+rl > l {
break
}
sl += rl
ss += string(r)
}
return ss
}

Loading…
Cancel
Save