You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
359 lines
10 KiB
359 lines
10 KiB
package income |
|
|
|
import ( |
|
"bytes" |
|
"context" |
|
"fmt" |
|
"strconv" |
|
"time" |
|
|
|
upModel "go-common/app/admin/main/growup/model" |
|
model "go-common/app/admin/main/growup/model/income" |
|
"go-common/app/admin/main/growup/service" |
|
|
|
"go-common/library/database/sql" |
|
"go-common/library/log" |
|
xtime "go-common/library/time" |
|
"go-common/library/xstr" |
|
|
|
"golang.org/x/sync/errgroup" |
|
) |
|
|
|
// BreachList list |
|
func (s *Service) BreachList(c context.Context, mids, aids []int64, typ int, fromTime, toTime int64, reason string, from, limit int) (breachs []*model.AvBreach, total int, err error) { |
|
query := formatBreachQuery(mids, aids, typ, fromTime, toTime, reason) |
|
total, err = s.dao.BreachCount(c, query) |
|
if err != nil { |
|
log.Error("s.dao.GetBreachCount error(%v)", err) |
|
return |
|
} |
|
query = fmt.Sprintf("%s LIMIT %d,%d", query, from, limit) |
|
breachs, err = s.dao.ListArchiveBreach(c, query) |
|
if err != nil { |
|
log.Error("s.dao.ListArchiveBreach error(%v)", err) |
|
} |
|
|
|
mids = make([]int64, 0, len(breachs)) |
|
for _, b := range breachs { |
|
mids = append(mids, b.MID) |
|
} |
|
nickname, err := s.dao.ListUpInfo(c, mids) |
|
for _, b := range breachs { |
|
b.Nickname = nickname[b.MID] |
|
} |
|
return |
|
} |
|
|
|
// BreachStatis statis |
|
func (s *Service) BreachStatis(c context.Context, mids, aids []int64, typ, groupType int, fromTime, toTime int64, reason string) (date interface{}, err error) { |
|
from := getDateByGroup(groupType, time.Unix(fromTime, 0)) |
|
to := getDateByGroup(groupType, time.Unix(toTime, 0)) |
|
query := formatBreachQuery(mids, aids, typ, from.Unix(), to.Unix(), reason) |
|
breachs, err := s.dao.ListArchiveBreach(c, query) |
|
if err != nil { |
|
log.Error("s.dao.ListArchiveBreach error(%v)", err) |
|
return |
|
} |
|
date = breachStatis(breachs, from, to, groupType) |
|
return |
|
} |
|
|
|
func breachStatis(breachs []*model.AvBreach, from, to time.Time, groupType int) interface{} { |
|
dateIncome := make(map[string]int64) |
|
dateUps := make(map[string]map[int64]struct{}) |
|
for _, breach := range breachs { |
|
date := formatDateByGroup(breach.CDate.Time(), groupType) |
|
if _, ok := dateIncome[date]; ok { |
|
dateIncome[date] += breach.Money |
|
} else { |
|
dateIncome[date] = breach.Money |
|
} |
|
if _, ok := dateUps[date]; !ok { |
|
dateUps[date] = make(map[int64]struct{}) |
|
} |
|
dateUps[date][breach.MID] = struct{}{} |
|
} |
|
|
|
income, counts, xAxis := []string{}, []int{}, []string{} |
|
// get result by date |
|
to = to.AddDate(0, 0, 1) |
|
for from.Before(to) { |
|
dateStr := formatDateByGroup(from, groupType) |
|
xAxis = append(xAxis, dateStr) |
|
if val, ok := dateIncome[dateStr]; ok { |
|
income = append(income, fmt.Sprintf("%.2f", float64(val)/float64(100))) |
|
counts = append(counts, len(dateUps[dateStr])) |
|
} else { |
|
income = append(income, "0") |
|
counts = append(counts, 0) |
|
} |
|
from = addDayByGroup(groupType, from) |
|
} |
|
|
|
return map[string]interface{}{ |
|
"counts": counts, |
|
"incomes": income, |
|
"xaxis": xAxis, |
|
} |
|
} |
|
|
|
// ExportBreach export |
|
func (s *Service) ExportBreach(c context.Context, mids, aids []int64, typ int, fromTime, toTime int64, reason string, from, limit int) (res []byte, err error) { |
|
breachs, _, err := s.BreachList(c, mids, aids, typ, fromTime, toTime, reason, from, limit) |
|
if err != nil { |
|
log.Error("s.BreachList error(%v)", err) |
|
return |
|
} |
|
records := formatBreach(breachs) |
|
res, err = service.FormatCSV(records) |
|
if err != nil { |
|
log.Error("FormatCSV error(%v)") |
|
} |
|
return |
|
} |
|
|
|
func formatBreachQuery(mids, aids []int64, typ int, fromTime, toTime int64, reason string) (query string) { |
|
query = fmt.Sprintf("cdate >= '%s' AND cdate <= '%s'", time.Unix(fromTime, 0).Format(_layout), time.Unix(toTime, 0).Format(_layout)) |
|
if typ != 4 { |
|
query = fmt.Sprintf("%s AND ctype = %d", query, typ) |
|
} |
|
if len(mids) > 0 { |
|
query = fmt.Sprintf("%s AND mid IN (%s)", query, xstr.JoinInts(mids)) |
|
} |
|
if len(aids) > 0 { |
|
query = fmt.Sprintf("%s AND av_id IN (%s)", query, xstr.JoinInts(aids)) |
|
} |
|
if reason != "" { |
|
query = fmt.Sprintf("%s AND reason = '%s'", query, reason) |
|
} |
|
return |
|
} |
|
|
|
// ArchiveBreach breach archive batch |
|
func (s *Service) ArchiveBreach(c context.Context, typ int, aids []int64, mid int64, reason string, operator string) (err error) { |
|
count, err := s.dao.BreachCount(c, fmt.Sprintf("av_id in (%s) AND cdate = '%s'", xstr.JoinInts(aids), time.Now().Format(_layout))) |
|
if err != nil { |
|
log.Error("s.dao.AvBreachCount error(%v)", err) |
|
return |
|
} |
|
if count > 0 { |
|
err = fmt.Errorf("有稿件已被扣除") |
|
return |
|
} |
|
return s.avBreach(c, typ, aids, mid, reason, operator) |
|
} |
|
|
|
func assembleAvBreach(aids []int64, mid int64, ctype int, reason string, breach map[int64]int64, upload map[int64]string) (vals string) { |
|
var buf bytes.Buffer |
|
for _, aid := range aids { |
|
buf.WriteString("(") |
|
buf.WriteString(strconv.FormatInt(aid, 10)) |
|
buf.WriteByte(',') |
|
buf.WriteString(strconv.FormatInt(mid, 10)) |
|
buf.WriteByte(',') |
|
buf.WriteString("'" + time.Now().Format(_layout) + "'") |
|
buf.WriteByte(',') |
|
buf.WriteString(strconv.FormatInt(breach[aid], 10)) |
|
buf.WriteByte(',') |
|
buf.WriteString(strconv.Itoa(ctype)) |
|
buf.WriteByte(',') |
|
buf.WriteString("\"" + reason + "\"") |
|
buf.WriteByte(',') |
|
buf.WriteString("'" + upload[aid] + "'") |
|
buf.WriteString(")") |
|
buf.WriteByte(',') |
|
} |
|
if buf.Len() > 0 { |
|
buf.Truncate(buf.Len() - 1) |
|
} |
|
vals = buf.String() |
|
buf.Reset() |
|
return |
|
} |
|
|
|
// AvBreach av breach from av_income |
|
func (s *Service) avBreach(c context.Context, ctype int, aids []int64, mid int64, reason string, operator string) (err error) { |
|
archives, withdrawMonth, err := s.GetArchiveByUpAccount(c, ctype, aids, mid) |
|
if err != nil { |
|
log.Error("s.GetArchiveByUpAccount error(%v)", err) |
|
return |
|
} |
|
if len(archives) == 0 { |
|
return |
|
} |
|
preMonthBreach, thisMonthBreach, avBreach, avUpload := getBreachMoney(archives, withdrawMonth) |
|
|
|
tx, err := s.dao.BeginTran(c) |
|
if err != nil { |
|
log.Error("s.dao.BeginTran error(%v)", err) |
|
return |
|
} |
|
var eg errgroup.Group |
|
// insert av_breach |
|
eg.Go(func() (err error) { |
|
if _, err = s.dao.TxInsertAvBreach(tx, assembleAvBreach(aids, mid, ctype, reason, avBreach, avUpload)); err != nil { |
|
log.Error("s.TxInsertAvBreach error(%v)", err) |
|
tx.Rollback() |
|
} |
|
return |
|
}) |
|
|
|
// update av breach pre state = 2 |
|
eg.Go(func() (err error) { |
|
if _, err = s.dao.TxUpdateBreachPre(tx, aids, time.Now().Format(_layout)); err != nil { |
|
log.Error("s.TxUpdateBreachPre error(%v)", err) |
|
tx.Rollback() |
|
} |
|
return |
|
}) |
|
|
|
// save av_black_list |
|
eg.Go(func() (err error) { |
|
if err = s.TxInsertAvBlacklist(c, tx, ctype, aids, mid, _avBreach, len(aids)); err != nil { |
|
log.Error("s.InsertAvBlacklist error(%v)", err) |
|
} |
|
return |
|
}) |
|
// update up_account |
|
eg.Go(func() (err error) { |
|
if err = s.TxUpAccountBreach(c, tx, mid, preMonthBreach, thisMonthBreach); err != nil { |
|
log.Error("s.UpdateUpAccount error(%v)", err) |
|
} |
|
return |
|
}) |
|
// update up credit score |
|
eg.Go(func() (err error) { |
|
if err = s.UpdateUpCredit(c, tx, ctype, mid, aids, operator); err != nil { |
|
log.Error("s.UpdateUpCredit error(%v)", err) |
|
} |
|
return |
|
}) |
|
|
|
eg.Go(func() (err error) { |
|
if _, err = s.upDao.TxUpdateAvSpyState(tx, 1, aids); err != nil { |
|
tx.Rollback() |
|
log.Error("s.upDao.TxUpdateAvSpyState error(%v)", err) |
|
} |
|
return |
|
}) |
|
|
|
if err = eg.Wait(); err != nil { |
|
log.Error("run eg.Wait error(%v)", err) |
|
return |
|
} |
|
|
|
if err = tx.Commit(); err != nil { |
|
log.Error("tx.Commit error") |
|
return |
|
} |
|
|
|
var business string |
|
switch ctype { |
|
case _video: |
|
business = "avid" |
|
case _column: |
|
business = "cv" |
|
case _bgm: |
|
business = "au" |
|
} |
|
|
|
for _, aid := range aids { |
|
err = s.msg.Send(c, "1_14_5", |
|
fmt.Sprintf("您的稿件 %s %d 违反创作激励计划规则。", business, aid), |
|
fmt.Sprintf("您的稿件 %s %d 因为%s原因被取消参加创作激励计划资格,已获得收入将被扣除。如有疑问,请联系客服。", business, aid, reason), |
|
[]int64{mid}, |
|
time.Now().Unix()) |
|
if err != nil { |
|
log.Error("s.msg.Send error(%v)", err) |
|
return |
|
} |
|
} |
|
|
|
return |
|
} |
|
|
|
// UpdateUpCredit update up_info credit score |
|
func (s *Service) UpdateUpCredit(c context.Context, tx *sql.Tx, ctype int, mid int64, aids []int64, operator string) (err error) { |
|
score, err := s.upDao.CreditScore(c, mid) |
|
if err != nil { |
|
return |
|
} |
|
// insert credit_score_record |
|
creditRecord := &upModel.CreditRecord{ |
|
MID: mid, |
|
OperateAt: xtime.Time(time.Now().Unix()), |
|
Operator: operator, |
|
Reason: 9, |
|
Deducted: 3 * len(aids), |
|
Remaining: score - 3*len(aids), |
|
} |
|
r1, err := s.upDao.TxInsertCreditRecord(tx, creditRecord) |
|
if err != nil { |
|
tx.Rollback() |
|
return |
|
} |
|
|
|
r2, err := s.upDao.TxUpdateCreditScore(tx, mid, score-3*len(aids)) |
|
if err != nil { |
|
tx.Rollback() |
|
return |
|
} |
|
if r1 != r2 { |
|
tx.Rollback() |
|
return |
|
} |
|
return |
|
} |
|
|
|
// GetArchiveByUpAccount get archive income by withdraw date |
|
func (s *Service) GetArchiveByUpAccount(c context.Context, typ int, aids []int64, mid int64) (archives []*model.ArchiveIncome, withdrawMonth time.Month, err error) { |
|
archives = make([]*model.ArchiveIncome, 0) |
|
upAccount, err := s.dao.GetUpAccount(c, mid) |
|
if err != nil { |
|
if err == sql.ErrNoRows { |
|
err = nil |
|
return |
|
} |
|
log.Error("s.dao.GetUpAccount error(%v)", err) |
|
return |
|
} |
|
|
|
withdrawDateStr := upAccount.WithdrawDateVersion + "-01" |
|
withdrawDate, err := time.Parse(_layout, withdrawDateStr) |
|
if err != nil { |
|
log.Error("time.Parse error(%v)", err) |
|
return |
|
} |
|
withdrawMonth = withdrawDate.AddDate(0, 1, 0).Month() |
|
from, now := withdrawDate.AddDate(0, 1, 0).Format(_layout), time.Now().Format(_layout) |
|
query := "" |
|
switch typ { |
|
case _video: |
|
query = fmt.Sprintf("av_id in (%s)", xstr.JoinInts(aids)) |
|
case _column: |
|
query = fmt.Sprintf("aid in (%s)", xstr.JoinInts(aids)) |
|
case _bgm: |
|
query = fmt.Sprintf("sid in (%s)", xstr.JoinInts(aids)) |
|
} |
|
archives, err = s.GetArchiveIncome(c, typ, query, from, now) |
|
if err != nil { |
|
log.Error("s.GetArchiveIncome error(%v)", err) |
|
} |
|
return |
|
} |
|
|
|
func getBreachMoney(archives []*model.ArchiveIncome, withdrawMonth time.Month) (int64, int64, map[int64]int64, map[int64]string) { |
|
var preMonthBreach, thisMonthBreach int64 = 0, 0 |
|
avBreach := make(map[int64]int64) |
|
avUpload := make(map[int64]string) |
|
for _, arch := range archives { |
|
if arch.Date.Time().Month() == withdrawMonth { |
|
preMonthBreach += arch.Income |
|
} else { |
|
thisMonthBreach += arch.Income |
|
} |
|
avBreach[arch.AvID] += arch.Income |
|
avUpload[arch.AvID] = arch.UploadTime.Time().Format(_layout) |
|
} |
|
return preMonthBreach, thisMonthBreach, avBreach, avUpload |
|
}
|
|
|