resouce.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. package service
  2. import (
  3. "context"
  4. "crypto/md5"
  5. "encoding/hex"
  6. "fmt"
  7. "math"
  8. "math/rand"
  9. "time"
  10. "go-common/app/admin/main/vip/model"
  11. "go-common/library/database/sql"
  12. "go-common/library/ecode"
  13. "go-common/library/log"
  14. xtime "go-common/library/time"
  15. "github.com/pkg/errors"
  16. )
  17. // QueryPool query pool
  18. func (s *Service) QueryPool(c context.Context, r *model.ResoucePoolBo) (res []*model.VipResourcePool, count int, err error) {
  19. var (
  20. batch *model.VipResourceBatch
  21. PN int
  22. PS int
  23. )
  24. PN = r.PN
  25. PS = r.PS
  26. if batch, err = s.dao.SelBatchRow(c, r.BatchID); err != nil {
  27. return
  28. }
  29. if r.BatchID != 0 {
  30. r.ID = -1
  31. }
  32. if batch != nil {
  33. r.ID = batch.PoolID
  34. }
  35. if count, err = s.dao.SelCountPool(c, r); err != nil || count == 0 {
  36. return
  37. }
  38. if res, err = s.dao.SelPool(c, r, PN, PS); err != nil {
  39. return
  40. }
  41. return
  42. }
  43. // PoolInfo pool info
  44. func (s *Service) PoolInfo(c context.Context, id int) (res *model.VipResourcePool, err error) {
  45. if res, err = s.dao.SelPoolRow(c, id); err != nil {
  46. return
  47. }
  48. return
  49. }
  50. // AddPool .
  51. func (s *Service) AddPool(c context.Context, r *model.ResoucePoolBo) (err error) {
  52. var (
  53. p *model.VipResourcePool
  54. )
  55. if err = s.verificationPool(r); err != nil {
  56. return
  57. }
  58. if p, err = s.dao.SelPoolByName(c, r.PoolName); err != nil {
  59. return
  60. }
  61. if p != nil {
  62. err = ecode.VipPoolNameExitErr
  63. return
  64. }
  65. if _, err = s.dao.AddPool(c, r); err != nil {
  66. return
  67. }
  68. return
  69. }
  70. func (s *Service) verificationPool(r *model.ResoucePoolBo) (err error) {
  71. var (
  72. business *model.VipBusinessInfo
  73. )
  74. if len(r.PoolName) == 0 {
  75. err = ecode.VipPoolNameErr
  76. return
  77. }
  78. if len(r.Reason) == 0 {
  79. err = ecode.VipPoolReasonErr
  80. return
  81. }
  82. if r.StartTime <= 0 {
  83. err = ecode.VipPoolStartTimeErr
  84. return
  85. }
  86. if r.EndTime <= 0 {
  87. err = ecode.VipPoolEndTimeErr
  88. return
  89. }
  90. if r.EndTime < r.StartTime {
  91. err = ecode.VipPoolValidityTimeErr
  92. return
  93. }
  94. if business, err = s.dao.SelBusiness(context.TODO(), r.BusinessID); err != nil {
  95. return
  96. }
  97. if business == nil {
  98. err = ecode.VipBusinessNotExitErr
  99. return
  100. }
  101. return
  102. }
  103. // UpdatePool .
  104. func (s *Service) UpdatePool(c context.Context, r *model.ResoucePoolBo) (err error) {
  105. var (
  106. pool *model.VipResourcePool
  107. p *model.VipResourcePool
  108. batchs []*model.VipResourceBatch
  109. )
  110. if err = s.verificationPool(r); err != nil {
  111. return
  112. }
  113. if pool, err = s.dao.SelPoolRow(c, r.ID); err != nil {
  114. return
  115. }
  116. if pool == nil {
  117. err = ecode.VipPoolIDErr
  118. return
  119. }
  120. if p, err = s.dao.SelPoolByName(c, r.PoolName); err != nil {
  121. return
  122. }
  123. if p != nil && pool.PoolName != p.PoolName {
  124. err = ecode.VipPoolNameExitErr
  125. return
  126. }
  127. if batchs, err = s.dao.SelBatchRows(context.TODO(), r.ID); err != nil {
  128. return
  129. }
  130. for _, v := range batchs {
  131. if !(r.StartTime <= v.StartTime && r.EndTime >= v.EndTime) {
  132. err = ecode.VipPoolValidityTimeErr
  133. return
  134. }
  135. }
  136. if _, err = s.dao.UpdatePool(c, r); err != nil {
  137. return
  138. }
  139. return
  140. }
  141. // BatchInfo .
  142. func (s *Service) BatchInfo(c context.Context, id int) (res *model.VipResourceBatch, err error) {
  143. if res, err = s.dao.SelBatchRow(c, id); err != nil {
  144. return
  145. }
  146. return
  147. }
  148. // BatchInfoOfPool .
  149. func (s *Service) BatchInfoOfPool(c context.Context, poolID int) (res []*model.VipResourceBatch, err error) {
  150. if res, err = s.dao.SelBatchRows(c, poolID); err != nil {
  151. return
  152. }
  153. return
  154. }
  155. // AddBatch .
  156. func (s *Service) AddBatch(c context.Context, r *model.ResouceBatchBo) (err error) {
  157. if err = s.verificationBatch(r); err != nil {
  158. return
  159. }
  160. r.SurplusCount = r.Count
  161. if _, err = s.dao.AddBatch(c, r); err != nil {
  162. return
  163. }
  164. return
  165. }
  166. // UpdateBatch .
  167. func (s *Service) UpdateBatch(c context.Context, id, increment int, startTime, endTime xtime.Time) (err error) {
  168. var (
  169. batch *model.VipResourceBatch
  170. r = new(model.ResouceBatchBo)
  171. )
  172. r.ID = id
  173. r.StartTime = startTime
  174. r.EndTime = endTime
  175. if batch, err = s.dao.SelBatchRow(c, id); err != nil {
  176. return
  177. }
  178. if batch == nil {
  179. err = ecode.VipBatchIDErr
  180. return
  181. }
  182. r.PoolID = batch.PoolID
  183. if err = s.verifBatchTime(r); err != nil {
  184. return
  185. }
  186. if increment < 0 {
  187. err = ecode.VipBatchPlusResouceErr
  188. return
  189. }
  190. if batch.Count+increment > math.MaxInt32 || batch.Count+increment < 0 {
  191. err = ecode.VipBatchCountErr
  192. return
  193. }
  194. batch.Count += increment
  195. batch.SurplusCount += increment
  196. batch.StartTime = r.StartTime
  197. batch.EndTime = r.EndTime
  198. ver := batch.Ver
  199. batch.Ver++
  200. if _, err = s.dao.UpdateBatch(c, batch, ver); err != nil {
  201. return
  202. }
  203. return
  204. }
  205. func (s *Service) verifBatchTime(r *model.ResouceBatchBo) (err error) {
  206. var (
  207. pool *model.VipResourcePool
  208. )
  209. if pool, err = s.dao.SelPoolRow(context.TODO(), r.PoolID); err != nil {
  210. return
  211. }
  212. if pool == nil {
  213. err = ecode.VipPoolIDErr
  214. return
  215. }
  216. if pool.StartTime > r.StartTime || pool.EndTime < r.EndTime {
  217. err = ecode.VipPoolValidityTimeErr
  218. return
  219. }
  220. return
  221. }
  222. func (s *Service) verificationBatch(r *model.ResouceBatchBo) (err error) {
  223. if r.Unit <= 0 || r.Unit > 3660 {
  224. err = ecode.VipBatchUnitErr
  225. return
  226. }
  227. if r.Count <= 0 {
  228. err = ecode.VipBatchCountErr
  229. return
  230. }
  231. if err = s.verifBatchTime(r); err != nil {
  232. return
  233. }
  234. return
  235. }
  236. // GrandResouce grand resouce mid
  237. func (s *Service) GrandResouce(c context.Context, remark string, batchID int64, mids []int, username string) (failMid []int, err error) {
  238. var (
  239. batch *model.VipResourceBatch
  240. )
  241. if len(remark) == 0 {
  242. err = ecode.VipRemarkErr
  243. return
  244. }
  245. if batch, err = s.dao.SelBatchRow(c, int(batchID)); err != nil {
  246. return
  247. }
  248. if batch == nil {
  249. err = ecode.VipBatchIDErr
  250. return
  251. }
  252. if err = s.checkBatchValid(batch); err != nil {
  253. return
  254. }
  255. for _, v := range mids {
  256. if err = s.grandMidOfResouce(c, v, int(batchID), username, remark); err != nil {
  257. log.Error("GrandResouce grandMidOfResouce(mid:%v,batchID:%v,username:%v,remark:%v error(%v))", v, batchID, username, remark, err)
  258. failMid = append(failMid, v)
  259. }
  260. }
  261. return
  262. }
  263. func (s *Service) grandMidOfResouce(c context.Context, mid, batchID int, username, remark string) (err error) {
  264. //var (
  265. // batch *model.VipResourceBatch
  266. // tx *sql.Tx
  267. // a int64
  268. // hv *inModel.HandlerVip
  269. //)
  270. //if batch, err = s.dao.SelBatchRow(c, batchID); err != nil {
  271. // return
  272. //}
  273. //if batch.SurplusCount-1 < 0 {
  274. // err = ecode.VipBatchNotEnoughErr
  275. // return
  276. //}
  277. //batch.DirectUseCount++
  278. //batch.SurplusCount--
  279. //ver := batch.Ver
  280. //batch.Ver++
  281. //if tx, err = s.dao.BeginTran(context.TODO()); err != nil {
  282. // return
  283. //}
  284. //defer func() {
  285. // if err != nil {
  286. // if err = tx.Commit(); err != nil {
  287. // tx.Rollback()
  288. // }
  289. // } else {
  290. // tx.Rollback()
  291. // }
  292. //}()
  293. //if a, err = s.dao.UseBatch(tx, batch, ver); err != nil {
  294. // return
  295. //}
  296. //if a > 0 {
  297. // if hv, err = s.exchangeVip(context.TODO(), tx, int(mid), batch.ID, batch.Unit, remark, username); err != nil {
  298. // return
  299. // }
  300. // s.asyncBcoin(func() {
  301. // s.vipRPC.BcoinProcesserHandler(context.TODO(), hv)
  302. // })
  303. //}
  304. return
  305. }
  306. func (s *Service) checkBatchValid(batch *model.VipResourceBatch) (err error) {
  307. var (
  308. pool *model.VipResourcePool
  309. business *model.VipBusinessInfo
  310. ct = time.Now()
  311. )
  312. if !(batch.StartTime.Time().Unix() <= ct.Unix() && ct.Unix() <= batch.EndTime.Time().Unix()) {
  313. err = ecode.VipBatchTTLErr
  314. return
  315. }
  316. if pool, err = s.dao.SelPoolRow(context.TODO(), batch.PoolID); err != nil {
  317. return
  318. }
  319. if pool == nil {
  320. err = ecode.VipPoolIDErr
  321. return
  322. }
  323. if !(pool.StartTime.Time().Unix() <= ct.Unix() && ct.Unix() <= pool.EndTime.Time().Unix()) {
  324. err = ecode.VipPoolValidityTimeErr
  325. return
  326. }
  327. if business, err = s.dao.SelBusiness(context.TODO(), pool.BusinessID); err != nil {
  328. return
  329. }
  330. if business == nil {
  331. err = ecode.VipBusinessNotExitErr
  332. return
  333. }
  334. if business.Status == 1 {
  335. err = ecode.VipBusinessStatusErr
  336. return
  337. }
  338. return
  339. }
  340. // SaveBatchCode .
  341. func (s *Service) SaveBatchCode(c context.Context, arg *model.BatchCode) (err error) {
  342. var batchID int64
  343. if arg.ID == 0 {
  344. if err = s.checkBatchCodeValid(c, arg); err != nil {
  345. return
  346. }
  347. arg.SurplusCount = arg.Count
  348. var tx *sql.Tx
  349. if tx, err = s.dao.BeginTran(c); err != nil {
  350. err = errors.WithStack(err)
  351. return
  352. }
  353. defer func() {
  354. if err == nil {
  355. if err = tx.Commit(); err != nil {
  356. log.Error("commimt error(%+v)", err)
  357. }
  358. } else {
  359. tx.Rollback()
  360. }
  361. }()
  362. arg.Status = 1
  363. if batchID, err = s.dao.TxAddBatchCode(tx, arg); err != nil {
  364. err = errors.WithStack(err)
  365. return
  366. }
  367. if err = s.createCode(tx, batchID, int(arg.Count)); err != nil {
  368. err = errors.WithStack(err)
  369. return
  370. }
  371. } else {
  372. var (
  373. bc *model.BatchCode
  374. bc1 *model.BatchCode
  375. )
  376. if bc, err = s.dao.SelBatchCodeID(c, arg.ID); err != nil {
  377. err = errors.WithStack(err)
  378. return
  379. }
  380. if bc == nil {
  381. err = ecode.VipBatchIDErr
  382. return
  383. }
  384. if bc.BatchName != arg.BatchName {
  385. if bc1, err = s.dao.SelBatchCodeName(c, arg.BatchName); err != nil {
  386. err = errors.WithStack(err)
  387. return
  388. }
  389. if bc1 != nil {
  390. err = ecode.VipBatchCodeNameErr
  391. return
  392. }
  393. }
  394. bc.BatchName = arg.BatchName
  395. bc.Reason = arg.Reason
  396. bc.Price = arg.Price
  397. bc.Contacts = arg.Contacts
  398. bc.ContactsNumber = arg.ContactsNumber
  399. bc.Type = arg.Type
  400. bc.MaxCount = arg.MaxCount
  401. bc.LimitDay = arg.LimitDay
  402. if _, err = s.dao.UpdateBatchCode(c, bc); err != nil {
  403. err = errors.WithStack(err)
  404. return
  405. }
  406. }
  407. return
  408. }
  409. func (s *Service) checkBatchCodeValid(c context.Context, arg *model.BatchCode) (err error) {
  410. var (
  411. b *model.VipBusinessInfo
  412. p *model.VipResourcePool
  413. bc *model.BatchCode
  414. )
  415. if b, err = s.BusinessInfo(c, int(arg.BusinessID)); err != nil {
  416. err = errors.WithStack(err)
  417. return
  418. }
  419. if b == nil {
  420. err = ecode.VipBusinessNotExitErr
  421. return
  422. }
  423. if p, err = s.PoolInfo(c, int(arg.PoolID)); err != nil {
  424. err = errors.WithStack(err)
  425. return
  426. }
  427. if p == nil {
  428. err = ecode.VipPoolIDErr
  429. return
  430. }
  431. if p.EndTime.Time().Before(arg.EndTime.Time()) || p.StartTime.Time().After(arg.StartTime.Time()) {
  432. err = ecode.VipPoolValidityTimeErr
  433. return
  434. }
  435. if bc, err = s.dao.SelBatchCodeName(c, arg.BatchName); err != nil {
  436. err = errors.WithStack(err)
  437. return
  438. }
  439. if bc != nil {
  440. err = ecode.VipBatchCodeNameErr
  441. return
  442. }
  443. if arg.Unit <= 0 || arg.Unit > 3660 {
  444. err = ecode.VipBatchUnitErr
  445. return
  446. }
  447. if arg.Count <= 0 || arg.Count > 200000 {
  448. err = ecode.VipBatchCodeCountErr
  449. }
  450. if arg.Price > 10000 || arg.Price < 0 {
  451. err = ecode.VipBatchPriceErr
  452. return
  453. }
  454. return
  455. }
  456. // FrozenCode .
  457. func (s *Service) FrozenCode(c context.Context, codeID int64, status int8) (err error) {
  458. var (
  459. code *model.ResourceCode
  460. )
  461. if code, err = s.dao.SelCodeID(c, codeID); err != nil {
  462. err = errors.WithStack(err)
  463. return
  464. }
  465. if code == nil {
  466. err = ecode.VipCodeIDErr
  467. return
  468. }
  469. code.Status = status
  470. if _, err = s.dao.UpdateCode(c, codeID, status); err != nil {
  471. err = errors.WithStack(err)
  472. return
  473. }
  474. return
  475. }
  476. // FrozenBatchCode .
  477. func (s *Service) FrozenBatchCode(c context.Context, BatchCodeID int64, status int8) (err error) {
  478. var bc *model.BatchCode
  479. if bc, err = s.dao.SelBatchCodeID(c, BatchCodeID); err != nil {
  480. err = errors.WithStack(err)
  481. return
  482. }
  483. if bc == nil {
  484. err = ecode.VipBatchIDErr
  485. return
  486. }
  487. bc.Status = status
  488. if _, err = s.dao.UpdateBatchCode(c, bc); err != nil {
  489. err = errors.WithStack(err)
  490. return
  491. }
  492. return
  493. }
  494. func (s *Service) createCode(tx *sql.Tx, batchCodeID int64, size int) (err error) {
  495. var (
  496. hash = md5.New()
  497. batchSize = 2000
  498. codes = make([]*model.ResourceCode, 0)
  499. )
  500. for i := 1; i <= size; i++ {
  501. unix := time.Now().UnixNano()
  502. key := fmt.Sprintf("%v,%v,%v,%v", unix, batchCodeID, i, rand.Intn(10000000))
  503. hash.Write([]byte(key))
  504. sum := hash.Sum(nil)
  505. code := hex.EncodeToString(sum)
  506. code = code[8:24]
  507. r := new(model.ResourceCode)
  508. r.Code = code
  509. r.Status = model.NOTUSER
  510. r.BatchCodeID = batchCodeID
  511. codes = append(codes, r)
  512. if i%batchSize == 0 || i == size {
  513. if err = s.dao.BatchAddCode(tx, codes); err != nil {
  514. log.Error("batch add code %+v", err)
  515. return
  516. }
  517. codes = make([]*model.ResourceCode, 0)
  518. }
  519. }
  520. return
  521. }
  522. // SelBatchCodes .
  523. func (s *Service) SelBatchCodes(c context.Context, batchIDs []int64) (res []*model.BatchCode, err error) {
  524. if res, err = s.dao.SelBatchCodes(c, batchIDs); err != nil {
  525. err = errors.WithStack(err)
  526. return
  527. }
  528. return
  529. }
  530. // SelCode .
  531. func (s *Service) SelCode(c context.Context, arg *model.ArgCode, username string, curID int64, ps int) (res []*model.CodeVo, cursor int64, pre int64, err error) {
  532. var (
  533. codes []*model.ResourceCode
  534. batchIDs []int64
  535. batchMap = make(map[int64]*model.BatchCode)
  536. batchCodes []*model.BatchCode
  537. linkmap map[int64]int64
  538. )
  539. if linkmap, err = s.dao.GetSelCode(c, username); err != nil {
  540. err = errors.WithStack(err)
  541. return
  542. }
  543. fmt.Printf("cur link map(%+v) \n", linkmap)
  544. if len(linkmap) == 0 {
  545. linkmap = make(map[int64]int64)
  546. }
  547. if codes, err = s.dao.SelCode(c, arg, curID, ps); err != nil {
  548. err = errors.WithStack(err)
  549. return
  550. }
  551. if len(codes) > 0 {
  552. cursor = codes[len(codes)-1].ID
  553. } else {
  554. return
  555. }
  556. linkmap[cursor] = curID
  557. pre = linkmap[curID]
  558. if err = s.dao.SetSelCode(c, username, linkmap); err != nil {
  559. err = errors.WithStack(err)
  560. return
  561. }
  562. for _, v := range codes {
  563. batchIDs = append(batchIDs, v.BatchCodeID)
  564. }
  565. if batchCodes, err = s.dao.SelBatchCodes(c, batchIDs); err != nil {
  566. err = errors.WithStack(err)
  567. return
  568. }
  569. for _, v := range batchCodes {
  570. batchMap[v.ID] = v
  571. }
  572. for _, v := range codes {
  573. r := new(model.CodeVo)
  574. r.ID = v.ID
  575. r.BatchCodeID = v.BatchCodeID
  576. r.Mid = v.Mid
  577. r.Ctime = v.Ctime
  578. r.Code = v.Code
  579. r.Status = v.Status
  580. r.UseTime = v.UseTime
  581. batchCode := batchMap[v.BatchCodeID]
  582. if batchCode == nil {
  583. err = ecode.VipBatchIDErr
  584. res = nil
  585. return
  586. }
  587. r.Unit = batchCode.Unit
  588. r.BatchName = batchCode.BatchName
  589. r.BatchStatus = batchCode.Status
  590. r.StartTime = batchCode.StartTime
  591. r.EndTime = batchCode.EndTime
  592. res = append(res, r)
  593. }
  594. return
  595. }
  596. // ExportCode .
  597. func (s *Service) ExportCode(c context.Context, batchID int64) (codes []string, err error) {
  598. var (
  599. rc []*model.ResourceCode
  600. curID int64
  601. ps = 2000
  602. )
  603. arg := new(model.ArgCode)
  604. arg.BatchCodeID = batchID
  605. arg.Status = model.NOTUSER
  606. for {
  607. if rc, err = s.dao.SelCode(c, arg, curID, ps); err != nil {
  608. err = errors.WithStack(err)
  609. return
  610. }
  611. if len(rc) == 0 {
  612. return
  613. }
  614. for _, v := range rc {
  615. codes = append(codes, v.Code)
  616. }
  617. curID = rc[len(rc)-1].ID
  618. }
  619. }
  620. // SelBatchCode .
  621. func (s *Service) SelBatchCode(c context.Context, arg *model.ArgBatchCode, pn, ps int) (res []*model.BatchCode, total int64, err error) {
  622. if total, err = s.dao.SelBatchCodeCount(c, arg); err != nil {
  623. err = errors.WithStack(err)
  624. return
  625. }
  626. if res, err = s.dao.SelBatchCode(c, arg, pn, ps); err != nil {
  627. err = errors.WithStack(err)
  628. return
  629. }
  630. return
  631. }