|
@@ -1,437 +0,0 @@
|
|
-package timetask
|
|
|
|
-
|
|
|
|
-import (
|
|
|
|
- "bytes"
|
|
|
|
- "database/sql"
|
|
|
|
- "fmt"
|
|
|
|
- "log"
|
|
|
|
- "math/rand"
|
|
|
|
- "qfw/util"
|
|
|
|
- "qfw/util/jy"
|
|
|
|
- . "service/config"
|
|
|
|
- "strconv"
|
|
|
|
- "strings"
|
|
|
|
- "time"
|
|
|
|
- . "util"
|
|
|
|
-
|
|
|
|
- "github.com/tealeg/xlsx"
|
|
|
|
-)
|
|
|
|
-
|
|
|
|
-type timetaskConf struct {
|
|
|
|
- Settlement struct {
|
|
|
|
- Day int
|
|
|
|
- Time string
|
|
|
|
- }
|
|
|
|
- ToCashout struct {
|
|
|
|
- Day int
|
|
|
|
- Time string
|
|
|
|
- }
|
|
|
|
- FlyerUserTime string
|
|
|
|
- ShareAutoInc map[string][]*shareAutoInc
|
|
|
|
- Finance struct {
|
|
|
|
- ReTry int
|
|
|
|
- From string
|
|
|
|
- Title string
|
|
|
|
- Fname string
|
|
|
|
- Mails []string
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-type shareAutoInc struct {
|
|
|
|
- Hour string
|
|
|
|
- Inc string
|
|
|
|
- Duration string
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-var (
|
|
|
|
- TimetaskConf *timetaskConf
|
|
|
|
-)
|
|
|
|
-
|
|
|
|
-func init() {
|
|
|
|
- util.ReadConfig("./timetask.json", &TimetaskConf)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-var ShareUser []map[string]interface{}
|
|
|
|
-
|
|
|
|
-type myWrite struct {
|
|
|
|
- Byte *bytes.Buffer
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (m *myWrite) Write(p []byte) (n int, err error) {
|
|
|
|
- n, err = m.Byte.Write(p)
|
|
|
|
- return
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-type settlementFx struct {
|
|
|
|
- name string //姓名
|
|
|
|
- idcard string //身份证号
|
|
|
|
- commission float64 //佣金
|
|
|
|
- tax float64 //个税
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-var fx *xlsx.File
|
|
|
|
-
|
|
|
|
-func init() {
|
|
|
|
- //20号把已结算的佣金转入可提现金额
|
|
|
|
- go toCashOut()
|
|
|
|
- //虚拟分享次数
|
|
|
|
- go func() {
|
|
|
|
- for k, v := range TimetaskConf.ShareAutoInc {
|
|
|
|
- shareCount(k, v)
|
|
|
|
- time.Sleep(50 * time.Millisecond)
|
|
|
|
- }
|
|
|
|
- }()
|
|
|
|
- //介绍页用户头像姓名
|
|
|
|
- //go util.SimpleCrontab(true, TimetaskConf.FlyerUserTime, Getshareinfo)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
-应纳税额计算方法
|
|
|
|
-
|
|
|
|
-劳务报酬所得
|
|
|
|
-级数 预扣预缴应纳税所得额 预扣税率 速算扣除数
|
|
|
|
-1 不超过20000元的部分 20% 0
|
|
|
|
-2 超过20000元至50000元的部分 30% 2000
|
|
|
|
-3 超过50000元的部分 40% 7000
|
|
|
|
-
|
|
|
|
-预扣预缴应纳税所得额的计算方式:
|
|
|
|
-预扣预缴应纳税所得额=劳务报酬(小于4000元)-800元
|
|
|
|
-预扣预缴应纳税所得额=劳务报酬(超过4000元)*(1-20%)
|
|
|
|
-应纳税额的计算公式:
|
|
|
|
-应纳税额=预扣预缴应纳税所得额*适用税率-速算扣除数
|
|
|
|
-备注:
|
|
|
|
-1.劳务报酬所得在800元以下的,不需要缴纳个人所得税
|
|
|
|
-2.劳务报酬所得大于800元且没有超过4000元,可减除800元的扣除费用
|
|
|
|
-3.劳务报酬所得超过4000元的,可减除劳务报酬收入20%的扣除费用
|
|
|
|
-
|
|
|
|
-举例:
|
|
|
|
-1.劳务报酬收入为2000
|
|
|
|
-预扣预缴应纳税所得额=2000-800=1200
|
|
|
|
-应纳税额=1200*20%=240
|
|
|
|
-
|
|
|
|
-2.劳务报酬收入为4500
|
|
|
|
-预扣预缴应纳税所得额=4500*(1-20%)=3600
|
|
|
|
-应纳税额=3600*20%=720
|
|
|
|
-
|
|
|
|
-3.劳务报酬收入为30000
|
|
|
|
-预扣预缴应纳税所得额=30000*(1*20%)=24000
|
|
|
|
-应纳税额=24000*30%-2000=5200
|
|
|
|
-*/
|
|
|
|
-func TaxPayable(commission float64) int64 {
|
|
|
|
- var tax_cash float64 //应纳税额
|
|
|
|
- var ynssde float64 //预扣预缴应纳税所得额
|
|
|
|
- if commission > 800 && commission <= 4000 {
|
|
|
|
- ynssde = commission - 800
|
|
|
|
- } else if commission > 4000 {
|
|
|
|
- ynssde = commission * 0.8
|
|
|
|
- }
|
|
|
|
- if ynssde > 0 {
|
|
|
|
- sysl := 0.2 //适用税率
|
|
|
|
- var sskcs float64 //速算扣除数
|
|
|
|
- if ynssde > 20000 && ynssde <= 50000 {
|
|
|
|
- sysl = 0.3
|
|
|
|
- sskcs = 2000
|
|
|
|
- } else if ynssde > 50000 {
|
|
|
|
- sysl = 0.4
|
|
|
|
- sskcs = 7000
|
|
|
|
- }
|
|
|
|
- tax_cash = ynssde*sysl - sskcs
|
|
|
|
- }
|
|
|
|
- return int64(util.RetainDecimal(tax_cash, 2) * 100)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//虚拟分享次数
|
|
|
|
-func shareCount(product string, shareAutoIncs []*shareAutoInc) {
|
|
|
|
- defer util.Catch()
|
|
|
|
- hour := time.Now().Hour()
|
|
|
|
- for _, v := range shareAutoIncs {
|
|
|
|
- hour_array := strings.Split(v.Hour, "-")
|
|
|
|
- if len(hour_array) != 2 {
|
|
|
|
- log.Println("配置项 hour error")
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- hour_min, err := strconv.Atoi(hour_array[0])
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println("配置项 hour_min error", err)
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- hour_max, err := strconv.Atoi(hour_array[1])
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println("配置项 hour_max error", err)
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- if hour < hour_min || hour > hour_max {
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- inc_array := strings.Split(v.Inc, "-")
|
|
|
|
- if len(inc_array) != 2 {
|
|
|
|
- log.Println("配置项 inc error")
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- duration_array := strings.Split(v.Duration, "-")
|
|
|
|
- if len(duration_array) != 2 {
|
|
|
|
- log.Println("配置项 duration error")
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- //
|
|
|
|
- inc_min, err := strconv.Atoi(inc_array[0])
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println("配置项 inc_min error", err)
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- inc_max, err := strconv.Atoi(inc_array[1])
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println("配置项 inc_max error", err)
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- //
|
|
|
|
- duration_min, err := strconv.Atoi(duration_array[0])
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println("配置项 duration_min error", err)
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- duration_max, err := strconv.Atoi(duration_array[1])
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println("配置项 duration_max error", err)
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- //
|
|
|
|
- r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
|
|
- inc := r.Intn(inc_max)
|
|
|
|
- if inc < inc_min {
|
|
|
|
- inc += inc_min
|
|
|
|
- }
|
|
|
|
- duration_m := r.Intn(duration_max)
|
|
|
|
- if duration_m < duration_min {
|
|
|
|
- duration_m += duration_min
|
|
|
|
- }
|
|
|
|
- duration_s := r.Intn(duration_max)
|
|
|
|
- if duration_s < duration_min {
|
|
|
|
- duration_s += duration_min
|
|
|
|
- }
|
|
|
|
- d := time.Duration(duration_m)*time.Minute + time.Duration(duration_s)*time.Second
|
|
|
|
- MQFW.Update("dis_product", map[string]interface{}{
|
|
|
|
- "s_name": product,
|
|
|
|
- }, map[string]interface{}{
|
|
|
|
- "$inc": map[string]interface{}{
|
|
|
|
- "i_shareCount": inc,
|
|
|
|
- },
|
|
|
|
- }, false, false)
|
|
|
|
- log.Println(product, "分享次数自增", "hour", hour, "inc", inc, "duration", d)
|
|
|
|
- time.AfterFunc(d, func() {
|
|
|
|
- shareCount(product, shareAutoIncs)
|
|
|
|
- })
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- log.Println("没有符合条件的配置项,请检查配置项!")
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func Getshareinfo() {
|
|
|
|
- log.Println("开始获取1000名用户头像")
|
|
|
|
- ShareUser = []map[string]interface{}{}
|
|
|
|
- data, ok := MQFW.Find("user", map[string]interface{}{
|
|
|
|
- "$or": []map[string]interface{}{
|
|
|
|
- map[string]interface{}{"s_headimageurl": map[string]interface{}{"$exists": true}},
|
|
|
|
- map[string]interface{}{"s_headimage": map[string]interface{}{"$exists": true}},
|
|
|
|
- },
|
|
|
|
- "i_appid": 2,
|
|
|
|
- }, `{"l_registedate":-1}`, `{"s_headimageurl":1,"s_headimage":1,"s_phone":1,"s_m_phone":1,"s_nickname":1}`, false, 0, 300)
|
|
|
|
- if ok && data != nil && *data != nil {
|
|
|
|
- for _, v := range *data {
|
|
|
|
- nickname := ""
|
|
|
|
- info := map[string]interface{}{}
|
|
|
|
- if s_phone, _ := v["s_phone"].(string); s_phone != "" {
|
|
|
|
- nickname = s_phone
|
|
|
|
- } else if s_m_phone, _ := v["s_m_phone"].(string); s_m_phone != "" {
|
|
|
|
- nickname = s_m_phone
|
|
|
|
- } else if s_nickname, _ := v["s_nickname"].(string); s_nickname != "" {
|
|
|
|
- nickname = s_nickname
|
|
|
|
- }
|
|
|
|
- if s_headimageurl, _ := v["s_headimageurl"].(string); s_headimageurl != "" {
|
|
|
|
- info["headimageurl"] = s_headimageurl
|
|
|
|
- } else if s_headimage, _ := v["s_headimage"].(string); s_headimage != "" {
|
|
|
|
- info["headimageurl"] = Sysconfig.Webdomain + s_headimage
|
|
|
|
- }
|
|
|
|
- info["nickname"] = EncryptionInfo(nickname)
|
|
|
|
- if util.ObjToString(info["nickname"]) == "" || util.ObjToString(info["headimageurl"]) == "" {
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- ShareUser = append(ShareUser, info)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func EncryptionInfo(s string) string {
|
|
|
|
- if jy.IsPhone(s) {
|
|
|
|
- s = string(s[0:3]) + "****" + string(s[len(s)-4:])
|
|
|
|
- } else {
|
|
|
|
- strArray := []rune(s)
|
|
|
|
- length := strings.Count(s, "") - 1
|
|
|
|
- if length > 2 {
|
|
|
|
- star := ""
|
|
|
|
- for i := 0; i < length-2; i++ {
|
|
|
|
- star += "*"
|
|
|
|
- }
|
|
|
|
- s = string(strArray[0:1]) + star + string(strArray[len(strArray)-1:])
|
|
|
|
- } else if length == 2 {
|
|
|
|
- s = string(strArray[0:1]) + "*"
|
|
|
|
- } else {
|
|
|
|
- s = ""
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return s
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func createSettlementFx(sFxs []*settlementFx) []byte {
|
|
|
|
- fx_sheet := fx.Sheets[0]
|
|
|
|
- var index = 0
|
|
|
|
- var count_commission float64 //合计佣金
|
|
|
|
- var count_tax float64 //合计个税
|
|
|
|
- for _, v := range sFxs {
|
|
|
|
- index++
|
|
|
|
- var row *xlsx.Row
|
|
|
|
- if index < len(fx_sheet.Rows) {
|
|
|
|
- row = fx_sheet.Rows[index]
|
|
|
|
- } else {
|
|
|
|
- row = fx_sheet.AddRow()
|
|
|
|
- }
|
|
|
|
- var cell *xlsx.Cell
|
|
|
|
- //姓名
|
|
|
|
- if len(row.Cells) > 0 {
|
|
|
|
- cell = row.Cells[0]
|
|
|
|
- } else {
|
|
|
|
- cell = row.AddCell()
|
|
|
|
- }
|
|
|
|
- cell.SetValue(v.name)
|
|
|
|
- //身份证号
|
|
|
|
- if len(row.Cells) > 1 {
|
|
|
|
- cell = row.Cells[1]
|
|
|
|
- } else {
|
|
|
|
- cell = row.AddCell()
|
|
|
|
- }
|
|
|
|
- cell.SetValue(v.idcard)
|
|
|
|
- //佣金
|
|
|
|
- if len(row.Cells) > 2 {
|
|
|
|
- cell = row.Cells[2]
|
|
|
|
- } else {
|
|
|
|
- cell = row.AddCell()
|
|
|
|
- }
|
|
|
|
- cell.SetValue(fmt.Sprintf("%.2f", v.commission))
|
|
|
|
- count_commission += v.commission
|
|
|
|
- //个税
|
|
|
|
- cell = row.AddCell()
|
|
|
|
- if len(row.Cells) > 3 {
|
|
|
|
- cell = row.Cells[3]
|
|
|
|
- } else {
|
|
|
|
- cell = row.AddCell()
|
|
|
|
- }
|
|
|
|
- cell.SetValue(fmt.Sprintf("%.2f", v.tax))
|
|
|
|
- count_tax += v.tax
|
|
|
|
- }
|
|
|
|
- index += 3
|
|
|
|
- fx_sheet.AddRow()
|
|
|
|
- fx_sheet.AddRow()
|
|
|
|
- fx_sheet.AddRow()
|
|
|
|
- //小计上面空三行
|
|
|
|
- //小计
|
|
|
|
- index++
|
|
|
|
- var row *xlsx.Row
|
|
|
|
- if index < len(fx_sheet.Rows) {
|
|
|
|
- row = fx_sheet.Rows[index]
|
|
|
|
- } else {
|
|
|
|
- row = fx_sheet.AddRow()
|
|
|
|
- }
|
|
|
|
- //姓名
|
|
|
|
- if len(row.Cells) == 0 {
|
|
|
|
- row.AddCell()
|
|
|
|
- }
|
|
|
|
- //身份证号
|
|
|
|
- if len(row.Cells) == 1 {
|
|
|
|
- row.AddCell()
|
|
|
|
- }
|
|
|
|
- var cell *xlsx.Cell
|
|
|
|
- //合计佣金
|
|
|
|
- if len(row.Cells) > 2 {
|
|
|
|
- cell = row.Cells[2]
|
|
|
|
- } else {
|
|
|
|
- cell = row.AddCell()
|
|
|
|
- }
|
|
|
|
- cell.SetValue(fmt.Sprintf("小计:%.2f", count_commission))
|
|
|
|
- //合计个税
|
|
|
|
- cell = row.AddCell()
|
|
|
|
- if len(row.Cells) > 3 {
|
|
|
|
- cell = row.Cells[3]
|
|
|
|
- } else {
|
|
|
|
- cell = row.AddCell()
|
|
|
|
- }
|
|
|
|
- cell.SetValue(fmt.Sprintf("小计:%.2f", count_tax))
|
|
|
|
- fpath := "./res/settlement/" + util.NowFormat("20060102150405") + ".xlsx"
|
|
|
|
- //
|
|
|
|
- w := &myWrite{
|
|
|
|
- Byte: &bytes.Buffer{},
|
|
|
|
- }
|
|
|
|
- if err := fx.Write(w); err != nil {
|
|
|
|
- log.Println(fpath, "获取结算列表xlsx文件的byte出错", err)
|
|
|
|
- } else {
|
|
|
|
- log.Println(fpath, "成功获取结算列表xlsx文件的byte", len(w.Byte.Bytes()))
|
|
|
|
- }
|
|
|
|
- //
|
|
|
|
- if err := fx.Save(fpath); err != nil {
|
|
|
|
- log.Println(fpath, "生成结算列表xlsx出错", err)
|
|
|
|
- } else {
|
|
|
|
- log.Println(fpath, "成功生成结算列表xlsx")
|
|
|
|
- }
|
|
|
|
- return w.Byte.Bytes()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//20号把已结算的佣金转入可提现金额
|
|
|
|
-func toCashOut() {
|
|
|
|
- util.SimpleCrontab(false, TimetaskConf.ToCashout.Time, func() {
|
|
|
|
- defer util.Catch()
|
|
|
|
- now := time.Now()
|
|
|
|
- if TimetaskConf.ToCashout.Day != now.Day() {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- log.Println("开始执行转入可提现定时任务。。。")
|
|
|
|
- stmtOut, err := Mysql.DB.Prepare(`select id,uid,count_cash from dis_count where count_status=0`)
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println(err)
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- defer stmtOut.Close()
|
|
|
|
- rows, err := stmtOut.Query()
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println(err)
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- if rows != nil {
|
|
|
|
- defer rows.Close()
|
|
|
|
- }
|
|
|
|
- for rows.Next() {
|
|
|
|
- var id int64
|
|
|
|
- var uid_uint8 []uint8 //用户id
|
|
|
|
- var count_cash int64 //结算金额
|
|
|
|
- err = rows.Scan(&id, &uid_uint8, &count_cash)
|
|
|
|
- if err != nil {
|
|
|
|
- log.Println(err)
|
|
|
|
- break
|
|
|
|
- }
|
|
|
|
- uid := string(uid_uint8)
|
|
|
|
- nowFormat := util.NowFormat(util.Date_Full_Layout)
|
|
|
|
- if Mysql.ExecTx("转入可提现定时任务", func(tx *sql.Tx) bool {
|
|
|
|
- ok_1 := int64(1)
|
|
|
|
- if count_cash > 0 {
|
|
|
|
- ok_1 = Mysql.UpdateOrDeleteBySqlByTx(tx, `update account set money=money+? where uid=?`, count_cash, uid)
|
|
|
|
- }
|
|
|
|
- ok_2 := Mysql.UpdateOrDeleteBySqlByTx(tx, `update dis_count set count_status=1,timestamp=? where id=?`, nowFormat, id)
|
|
|
|
- return ok_1 > 0 && ok_2 > 0
|
|
|
|
- }) {
|
|
|
|
- log.Println("转入可提现成功", uid, "id", id, "结算金额", count_cash)
|
|
|
|
- } else {
|
|
|
|
- log.Println("转入可提现失败", uid, "id", id, "结算金额", count_cash)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- log.Println("转入可提现定时任务执行完成。。。")
|
|
|
|
- })
|
|
|
|
-}
|
|
|