271 lines
7.0 KiB
Go
271 lines
7.0 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/csv"
|
|
"fmt"
|
|
"mime/multipart"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"go-common/app/admin/main/coupon/model"
|
|
"go-common/library/database/sql"
|
|
"go-common/library/ecode"
|
|
"go-common/library/log"
|
|
xtime "go-common/library/time"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// AddAllowanceBatchInfo add allowance batch info.
|
|
func (s *Service) AddAllowanceBatchInfo(c context.Context, b *model.CouponBatchInfo) (token string, err error) {
|
|
if b.ExpireDay < 0 && (b.StartTime <= 0 && b.ExpireTime <= 0) {
|
|
err = ecode.CouponExpireErr
|
|
return
|
|
}
|
|
if b.ExpireDay < 0 && b.StartTime >= b.ExpireTime {
|
|
err = ecode.CouPonBatchTimeErr
|
|
return
|
|
}
|
|
if b.Amount >= b.FullAmount {
|
|
err = ecode.CouponAmountErr
|
|
return
|
|
}
|
|
b.BatchToken = s.token()
|
|
b.Ctime = xtime.Time(time.Now().Unix())
|
|
if _, err = s.dao.AddAllowanceBatchInfo(c, b); err != nil {
|
|
err = errors.WithStack(err)
|
|
}
|
|
token = b.BatchToken
|
|
return
|
|
}
|
|
|
|
//UpdateAllowanceBatchInfo update allowance batch info.
|
|
func (s *Service) UpdateAllowanceBatchInfo(c context.Context, b *model.CouponBatchInfo) (err error) {
|
|
if _, err = s.dao.UpdateAllowanceBatchInfo(c, b); err != nil {
|
|
err = errors.WithStack(err)
|
|
}
|
|
return
|
|
}
|
|
|
|
//UpdateCodeBatchInfo update code batch info.
|
|
func (s *Service) UpdateCodeBatchInfo(c context.Context, b *model.CouponBatchInfo) (err error) {
|
|
var data *model.CouponBatchInfo
|
|
if data, err = s.BatchInfoByID(c, b.ID); err != nil {
|
|
return
|
|
}
|
|
if data == nil || batchState(data) != model.CodeBatchUsable {
|
|
return ecode.RequestErr
|
|
}
|
|
if _, err = s.dao.UpdateCodeBatchInfo(c, b); err != nil {
|
|
err = errors.WithStack(err)
|
|
}
|
|
return
|
|
}
|
|
|
|
//UpdateBatchStatus update batch status.
|
|
func (s *Service) UpdateBatchStatus(c context.Context, status int8, operator string, id int64) (err error) {
|
|
var data *model.CouponBatchInfo
|
|
if data, err = s.BatchInfoByID(c, id); err != nil {
|
|
return
|
|
}
|
|
if data == nil ||
|
|
(status == model.CodeBatchBlock && batchState(data) != model.CodeBatchUsable) ||
|
|
(status == model.CodeBatchUsable && batchState(data) != model.CodeBatchBlock) {
|
|
return ecode.RequestErr
|
|
}
|
|
if _, err = s.dao.UpdateBatchStatus(c, status, operator, id); err != nil {
|
|
err = errors.WithStack(err)
|
|
}
|
|
return
|
|
}
|
|
|
|
//BatchInfo allowance batch info.
|
|
func (s *Service) BatchInfo(c context.Context, token string) (res *model.CouponBatchInfo, err error) {
|
|
if res, err = s.dao.BatchInfo(c, token); err != nil {
|
|
err = errors.WithStack(err)
|
|
}
|
|
return
|
|
}
|
|
|
|
//BatchInfoByID allowance batch info.
|
|
func (s *Service) BatchInfoByID(c context.Context, id int64) (*model.CouponBatchInfo, error) {
|
|
return s.dao.BatchInfoByID(c, id)
|
|
}
|
|
|
|
// AllowanceSalary allowance salary.
|
|
func (s *Service) AllowanceSalary(c context.Context, f multipart.File, h *multipart.FileHeader, mids []int64, token, msgType string) (count int, err error) {
|
|
var bi *model.CouponBatchInfo
|
|
if len(mids) == 0 {
|
|
if mids, err = s.ReadCsv(f, h); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
}
|
|
if len(mids) == 0 {
|
|
err = ecode.CouponBatchSalaryCountZeroErr
|
|
return
|
|
}
|
|
if len(mids) > _maxSalaryCount {
|
|
err = ecode.CouponBatchSalaryLimitErr
|
|
return
|
|
}
|
|
if bi, err = s.dao.BatchInfo(c, token); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
if bi == nil {
|
|
err = ecode.CouPonTokenNotFoundErr
|
|
return
|
|
}
|
|
if bi.State != model.BatchStateNormal {
|
|
err = ecode.CouPonHadBlockErr
|
|
return
|
|
}
|
|
if bi.ExpireDay < 0 && bi.ExpireTime < time.Now().Unix() {
|
|
err = ecode.CouponBatchExpireTimeErr
|
|
return
|
|
}
|
|
if bi.MaxCount != _notLimitSalary && len(mids) > int(bi.MaxCount-bi.CurrentCount) {
|
|
err = ecode.CouponBatchSalaryLimitErr
|
|
return
|
|
}
|
|
s.RunSalaryCoupon(c, mids, token, bi.AppID, model.CouponAllowance, model.AdminSalaryOrigin, msgType)
|
|
count = len(mids)
|
|
return
|
|
}
|
|
|
|
// ReadCsv read csv file
|
|
func (s *Service) ReadCsv(f multipart.File, h *multipart.FileHeader) (mids []int64, err error) {
|
|
var (
|
|
mid int64
|
|
records [][]string
|
|
)
|
|
mids = []int64{}
|
|
defer f.Close()
|
|
if h != nil && !strings.HasSuffix(h.Filename, ".csv") {
|
|
err = ecode.CouponUpdateFileErr
|
|
return
|
|
}
|
|
r := csv.NewReader(f)
|
|
records, err = r.ReadAll()
|
|
if err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
for _, v := range records {
|
|
if len(v) <= 0 {
|
|
continue
|
|
}
|
|
if mid, err = strconv.ParseInt(v[0], 10, 64); err != nil {
|
|
err = errors.WithStack(err)
|
|
break
|
|
}
|
|
mids = append(mids, mid)
|
|
}
|
|
return
|
|
}
|
|
|
|
// //AllowancePage allowance page.
|
|
// func (s *Service) AllowancePage(c context.Context, arg *model.ArgAllowanceSearch) (res *model.PageCouponInfo, err error) {
|
|
// var page *model.SearchData
|
|
// res = &model.PageCouponInfo{}
|
|
// if page, err = s.dao.AllowancePage(c, arg); err != nil {
|
|
// err = errors.WithStack(err)
|
|
// return
|
|
// }
|
|
// if page != nil && page.Data != nil && page.Data.Page != nil {
|
|
// res.Count = page.Data.Page.Total
|
|
// res.Item = page.Data.Result
|
|
// }
|
|
// return
|
|
// }
|
|
|
|
//AllowanceList allowance list.
|
|
func (s *Service) AllowanceList(c context.Context, arg *model.ArgAllowanceSearch) (res []*model.CouponAllowanceInfo, err error) {
|
|
if res, err = s.dao.AllowanceList(c, arg); err != nil {
|
|
err = errors.WithStack(err)
|
|
}
|
|
for _, v := range res {
|
|
if v.State == model.NotUsed && v.ExpireTime < time.Now().Unix() {
|
|
v.State = model.Expire
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
//UpdateAllowanceState update allowance state.
|
|
func (s *Service) UpdateAllowanceState(c context.Context, mid int64, state int8, token string) (err error) {
|
|
var (
|
|
cp *model.CouponAllowanceInfo
|
|
changeType int8
|
|
)
|
|
if cp, err = s.dao.AllowanceByToken(c, mid, token); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
if cp == nil {
|
|
err = ecode.CouPonTokenNotFoundErr
|
|
return
|
|
}
|
|
if state == model.Block {
|
|
changeType = model.AllowanceBlock
|
|
} else {
|
|
changeType = model.AllowanceUnBlock
|
|
}
|
|
if err = s.UpdateAllowanceCoupon(c, mid, state, token, cp.Ver, changeType, cp); err != nil {
|
|
err = errors.WithStack(err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// UpdateAllowanceCoupon update coupon info.
|
|
func (s *Service) UpdateAllowanceCoupon(c context.Context, mid int64, state int8, token string, ver int64, changeType int8, cp *model.CouponAllowanceInfo) (err error) {
|
|
var (
|
|
tx *sql.Tx
|
|
aff int64
|
|
)
|
|
if tx, err = s.dao.BeginTran(c); err != nil {
|
|
log.Error("%+v", err)
|
|
return
|
|
}
|
|
defer func() {
|
|
if err != nil {
|
|
if err1 := tx.Rollback(); err1 != nil {
|
|
log.Error("tx.Rollback %+v", err1)
|
|
}
|
|
return
|
|
}
|
|
if err = tx.Commit(); err != nil {
|
|
log.Error("tx.Commit %+v", err)
|
|
}
|
|
}()
|
|
if aff, err = s.dao.UpdateAllowanceStatus(c, tx, state, mid, token, ver); err != nil {
|
|
err = errors.WithStack(err)
|
|
}
|
|
if aff != 1 {
|
|
err = fmt.Errorf("coupon update faild")
|
|
return
|
|
}
|
|
l := &model.CouponAllowanceChangeLog{
|
|
CouponToken: cp.CouponToken,
|
|
Mid: cp.Mid,
|
|
State: state,
|
|
Ctime: xtime.Time(time.Now().Unix()),
|
|
OrderNO: cp.OrderNO,
|
|
ChangeType: changeType,
|
|
}
|
|
if aff, err = s.dao.InsertCouponAllowanceHistory(c, tx, l); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
if aff != 1 {
|
|
err = fmt.Errorf("add change log faild")
|
|
return
|
|
}
|
|
s.dao.DelCouponAllowancesKey(c, cp.Mid, model.NotUsed)
|
|
s.dao.DelCouponAllowancesKey(c, cp.Mid, model.InUse)
|
|
return
|
|
}
|