banner.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. package dao
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. item "go-common/app/service/openplatform/ticket-item/api/grpc/v1"
  7. "go-common/app/service/openplatform/ticket-item/model"
  8. "go-common/library/ecode"
  9. "go-common/library/log"
  10. "go-common/library/time"
  11. "strconv"
  12. "strings"
  13. xtime "time"
  14. "github.com/jinzhu/gorm"
  15. )
  16. // DelBannerInfo 删除缓存所需banner信息
  17. type DelBannerInfo struct {
  18. Order int32
  19. Position int32
  20. SubPosition int32
  21. DistrictIDs []string
  22. }
  23. // AddBanner 添加新投放
  24. func (d *Dao) AddBanner(c context.Context, info *item.BannerEditRequest) (bannerID int64, verID uint64, err error) {
  25. // 开启事务
  26. tx := d.db.Begin()
  27. //创建banner信息
  28. banner := model.Banner{
  29. PubStart: time.Time(info.PubStart),
  30. PubEnd: time.Time(info.PubEnd),
  31. Name: info.Name,
  32. Pic: info.Pic,
  33. URL: info.Url,
  34. From: info.From,
  35. TargetUser: info.TargetUser,
  36. }
  37. if err = tx.Create(&banner).Error; err != nil {
  38. log.Error("创建banner失败:%s", err)
  39. tx.Rollback()
  40. return 0, 0, err
  41. }
  42. bannerID = banner.ID
  43. if bannerID == 0 {
  44. log.Error("bannerID为0")
  45. tx.Rollback()
  46. return 0, 0, err
  47. }
  48. var mainInfo []byte
  49. mainInfo, err = json.Marshal(info)
  50. if err != nil {
  51. log.Error("jsonMarshal版本详情失败:%s", err)
  52. tx.Rollback()
  53. return bannerID, 0, err
  54. }
  55. //生成新审核版本ver,verExt
  56. str := fmt.Sprintf("%d%d%.2d", info.Position, info.SubPosition, info.Order)
  57. forInt, _ := strconv.ParseInt(str, 10, 64)
  58. verInfo := model.Version{
  59. Type: model.VerTypeBanner,
  60. Status: info.OpType,
  61. ItemName: info.Name,
  62. TargetItem: bannerID,
  63. AutoPub: 1, // 自动上架
  64. PubStart: time.Time(info.PubStart),
  65. PubEnd: time.Time(info.PubEnd),
  66. For: forInt,
  67. }
  68. err = d.AddVersion(c, tx, &verInfo, &model.VersionExt{
  69. Type: model.VerTypeBanner,
  70. MainInfo: string(mainInfo),
  71. })
  72. if err != nil {
  73. log.Error("创建banner版本失败: %s", err)
  74. return 0, verInfo.VerID, ecode.TicketAddVersionFailed
  75. }
  76. if verInfo.VerID == 0 {
  77. log.Error("创建后获取verID为0")
  78. return 0, verInfo.VerID, ecode.TicketAddVersionFailed
  79. }
  80. // 提交事务
  81. tx.Commit()
  82. return bannerID, verInfo.VerID, nil
  83. }
  84. // EditBanner 编辑投放
  85. func (d *Dao) EditBanner(c context.Context, info *item.BannerEditRequest) (err error) {
  86. // 开启事务
  87. tx := d.db.Begin()
  88. var mainInfo []byte
  89. mainInfo, err = json.Marshal(info)
  90. if err != nil {
  91. log.Error("jsonMarshal版本详情失败:%s", err)
  92. tx.Rollback()
  93. return err
  94. }
  95. //更新审核版本ver,verExt
  96. str := fmt.Sprintf("%d%d%.2d", info.Position, info.SubPosition, info.Order)
  97. forInt, _ := strconv.ParseInt(str, 10, 64)
  98. if err = tx.Model(&model.Version{}).Where("ver_id = ?", info.VerId).Updates(
  99. map[string]interface{}{
  100. "item_name": info.Name,
  101. "status": info.OpType,
  102. "pub_start": time.Time(info.PubStart),
  103. "pub_end": time.Time(info.PubEnd),
  104. "for": forInt,
  105. }).Error; err != nil {
  106. log.Error("更新banner版本失败:%s", err)
  107. tx.Rollback()
  108. return err
  109. }
  110. if err = tx.Model(&model.VersionExt{}).Where("ver_id = ?", info.VerId).Updates(
  111. map[string]interface{}{
  112. "main_info": mainInfo,
  113. }).Error; err != nil {
  114. log.Error("更新banner版本详情失败:%s", err)
  115. tx.Rollback()
  116. return err
  117. }
  118. // 提交事务
  119. tx.Commit()
  120. return nil
  121. }
  122. // PassOrPublishBanner 审核通过或上架banner版本
  123. func (d *Dao) PassOrPublishBanner(c context.Context, verID uint64) (err error) {
  124. //获取版本信息
  125. verInfo, verExtInfo, getErr := d.GetVersion(c, verID, true)
  126. if getErr != nil {
  127. return getErr
  128. }
  129. //解析mainInfo
  130. var decodedMainInfo item.BannerEditRequest
  131. err = json.Unmarshal([]byte(verExtInfo.MainInfo), &decodedMainInfo)
  132. if err != nil {
  133. return err
  134. }
  135. bannerID := verInfo.TargetItem
  136. tx := d.db.Begin()
  137. //如果存在审核通过/进行中版本 删除版本
  138. var bannerVersions []model.Version
  139. if err = tx.Where("target_item = ? and status in (?) and ver_id != ? and deleted_at='0000-00-00 00:00:00'",
  140. bannerID, []int32{model.VerStatusReadyForSale, model.VerStatusOnShelf}, verID).Find(&bannerVersions).Error; err != nil {
  141. log.Error("获取banner所有审核通过/已上架版本失败:%s", err)
  142. tx.Rollback()
  143. return err
  144. }
  145. var delCacheInfos []DelBannerInfo
  146. var verIDs []uint64
  147. var delPosition int32
  148. var delSubPosition int32
  149. var delOrder int32
  150. var delDistrictIDs []string
  151. for _, v := range bannerVersions {
  152. //获取该版本详情 删除对应bannerDistrict信息
  153. if delPosition, delSubPosition, delOrder, delDistrictIDs, err = d.DelBannerDistrictByVerID(c, tx, v.VerID, bannerID); err != nil {
  154. return
  155. }
  156. delCacheInfos = append(delCacheInfos, DelBannerInfo{
  157. Order: delOrder,
  158. Position: delPosition,
  159. SubPosition: delSubPosition,
  160. DistrictIDs: delDistrictIDs,
  161. })
  162. verIDs = append(verIDs, v.VerID)
  163. }
  164. if verIDs != nil {
  165. if err = tx.Exec("UPDATE version SET deleted_at=? WHERE ver_id in (?)", xtime.Now().Format("2006-01-02 15:04:05"), verIDs).Error; err != nil {
  166. log.Error("删除banner版本失败:%s", err)
  167. tx.Rollback()
  168. return err
  169. }
  170. if err = tx.Exec("UPDATE version_ext SET deleted_at=? WHERE ver_id in (?)", xtime.Now().Format("2006-01-02 15:04:05"), verIDs).Error; err != nil {
  171. log.Error("删除banner ext版本失败:%s", err)
  172. tx.Rollback()
  173. return err
  174. }
  175. }
  176. //如果达到投放开始时间 还要更新bannerDistrict并直接上架
  177. var newVerStatus int32
  178. var newBannerStatus int32
  179. var districtIDs []string
  180. if decodedMainInfo.PubStart <= xtime.Now().Unix() {
  181. districtIDs = strings.Split(decodedMainInfo.Location, ",")
  182. for _, districtID := range districtIDs {
  183. newDistrictID, _ := strconv.ParseInt(districtID, 10, 64)
  184. if err = d.CreateOrUpdateBannerDistrict(c, tx, model.BannerDistrict{
  185. BannerID: bannerID,
  186. Position: decodedMainInfo.Position,
  187. SubPosition: decodedMainInfo.SubPosition,
  188. Order: decodedMainInfo.Order,
  189. DistrictID: newDistrictID,
  190. }); err != nil {
  191. return err
  192. }
  193. }
  194. newVerStatus = model.VerStatusOnShelf
  195. newBannerStatus = 1
  196. } else {
  197. newVerStatus = model.VerStatusReadyForSale
  198. newBannerStatus = 0
  199. }
  200. //更新banner表
  201. if err = tx.Model(&model.Banner{}).Where("id = ?", bannerID).Updates(
  202. map[string]interface{}{
  203. "pub_start": time.Time(decodedMainInfo.PubStart),
  204. "pub_end": time.Time(decodedMainInfo.PubEnd),
  205. "name": decodedMainInfo.Name,
  206. "pic": decodedMainInfo.Pic,
  207. "url": decodedMainInfo.Url,
  208. "from": decodedMainInfo.From,
  209. "status": newBannerStatus,
  210. "target_user": decodedMainInfo.TargetUser,
  211. }).Error; err != nil {
  212. log.Error("更新banner失败:%s", err)
  213. tx.Rollback()
  214. return err
  215. }
  216. //更新version状态为审核通过(待上架)或已上架
  217. if err = tx.Model(&model.Version{}).Where("ver_id = ?", verID).Updates(
  218. map[string]interface{}{
  219. "status": newVerStatus,
  220. }).Error; err != nil {
  221. log.Error("更新banner审核版本失败:%s", err)
  222. tx.Rollback()
  223. return err
  224. }
  225. tx.Commit()
  226. //如果新状态是上架状态 删除相关缓存
  227. if newVerStatus == model.VerStatusOnShelf {
  228. _, err = d.DelBannerCache(c, decodedMainInfo.Position, decodedMainInfo.SubPosition, decodedMainInfo.Order, districtIDs, bannerID)
  229. if err != nil {
  230. return
  231. }
  232. for _, v := range delCacheInfos {
  233. _, err = d.DelBannerCache(c, v.Position, v.SubPosition, v.Order, v.DistrictIDs, 0)
  234. if err != nil {
  235. return
  236. }
  237. }
  238. }
  239. return
  240. }
  241. // DelBannerCache 删除banner相关缓存
  242. func (d *Dao) DelBannerCache(c context.Context, position int32, subPosition int32, order int32, districtIDs []string, bannerID int64) (res bool, err error) {
  243. var (
  244. keys []interface{}
  245. )
  246. conn := d.redis.Get(c)
  247. defer func() {
  248. conn.Flush()
  249. conn.Close()
  250. }()
  251. for _, districtID := range districtIDs {
  252. // DEL bannerList
  253. keys = append(keys, keyBannerList(order, districtID, position, subPosition))
  254. }
  255. //删除bannerInfo缓存
  256. if bannerID != 0 {
  257. keys = append(keys, keyBannerInfo(bannerID))
  258. }
  259. log.Info("DEL %v", keys)
  260. //DEL bannerList
  261. if err = conn.Send("DEL", keys...); err != nil {
  262. log.Error("DEL %v, error(%v)", keys, err)
  263. }
  264. if err != nil {
  265. return false, err
  266. }
  267. return true, err
  268. }
  269. //DelBannerDistrictByVerID 删除版本详情内对应的关系表信息
  270. func (d *Dao) DelBannerDistrictByVerID(c context.Context, tx *gorm.DB, verID uint64, bannerID int64) (position int32, subPosition int32, order int32, districtIDs []string, err error) {
  271. var verExtInfo model.VersionExt
  272. var delDecodedInfo item.BannerEditRequest
  273. //获取该版本详情 删除对应bannerDistrict信息
  274. if err = tx.Where("ver_id = ?", verID).First(&verExtInfo).Error; err != nil {
  275. log.Error("获取需要删除版本详情失败:%s", err)
  276. tx.Rollback()
  277. return 0, 0, 0, nil, err
  278. }
  279. //解析mainInfo
  280. err = json.Unmarshal([]byte(verExtInfo.MainInfo), &delDecodedInfo)
  281. if err != nil {
  282. tx.Rollback()
  283. return 0, 0, 0, nil, err
  284. }
  285. districtIDs = strings.Split(delDecodedInfo.Location, ",")
  286. for _, districtID := range districtIDs {
  287. if err = tx.Exec("UPDATE banner_district SET is_deleted=1 WHERE banner_id = ? and district_id = ? and position = ? and sub_position = ? and `order` = ?",
  288. bannerID, districtID, delDecodedInfo.Position, delDecodedInfo.SubPosition, delDecodedInfo.Order).Error; err != nil {
  289. log.Error("删除bannerDistrict失败:%s", err)
  290. tx.Rollback()
  291. return 0, 0, 0, nil, err
  292. }
  293. }
  294. return delDecodedInfo.Position, delDecodedInfo.SubPosition, delDecodedInfo.Order, districtIDs, err
  295. }
  296. // CreateOrUpdateBannerDistrict 更新或新建bannerDistrict关系记录
  297. func (d *Dao) CreateOrUpdateBannerDistrict(c context.Context, tx *gorm.DB, info model.BannerDistrict) (err error) {
  298. var bannerDist model.BannerDistrict
  299. log.Info("bannerDist:%v", info)
  300. err = tx.Where("district_id = ? and position = ? and sub_position = ? and `order` = ?",
  301. info.DistrictID, info.Position, info.SubPosition, info.Order).First(&bannerDist).Error
  302. //除去没查找到记录的报错 其他直接抛错
  303. if err != nil && err != ecode.NothingFound {
  304. log.Error("获取banner dist信息失败:%s", err)
  305. tx.Rollback()
  306. return
  307. }
  308. if bannerDist.ID != 0 {
  309. //update
  310. log.Info("update bannerDistrict")
  311. if err = tx.Exec("UPDATE banner_district SET banner_id=?,is_deleted=0 WHERE district_id = ? and position = ? and sub_position = ? and `order` = ?",
  312. info.BannerID, info.DistrictID, info.Position, info.SubPosition, info.Order).Error; err != nil {
  313. log.Error("更新bannerDistrict失败:%s", err)
  314. tx.Rollback()
  315. return err
  316. }
  317. } else {
  318. //create
  319. log.Info("insert bannerDistrict")
  320. if err = tx.Create(&model.BannerDistrict{
  321. BannerID: info.BannerID,
  322. Position: info.Position,
  323. SubPosition: info.SubPosition,
  324. Order: info.Order,
  325. DistrictID: info.DistrictID,
  326. }).Error; err != nil {
  327. log.Error("创建bannerDistrict失败:%s", err)
  328. tx.Rollback()
  329. return err
  330. }
  331. }
  332. return nil
  333. }
  334. // DeleteBanner 删除banner
  335. func (d *Dao) DeleteBanner(c context.Context, verID uint64) (err error) {
  336. tx := d.db.Begin()
  337. if err = tx.Exec("UPDATE version SET deleted_at=? WHERE ver_id = ?", xtime.Now().Format("2006-01-02 15:04:05"), verID).Error; err != nil {
  338. tx.Rollback()
  339. log.Error("删除banner版本失败:%s", err)
  340. return err
  341. }
  342. if err = tx.Exec("UPDATE version_ext SET deleted_at=? WHERE ver_id=?", xtime.Now().Format("2006-01-02 15:04:05"), verID).Error; err != nil {
  343. tx.Rollback()
  344. log.Error("删除banner ext版本失败:%s", err)
  345. return err
  346. }
  347. tx.Commit()
  348. return
  349. }
  350. // UnpublishBannerManual 手动取消激活banner
  351. func (d *Dao) UnpublishBannerManual(c context.Context, verID uint64) (err error) {
  352. //取消激活banner
  353. //获取版本信息
  354. tx := d.db.Begin()
  355. verInfo, _, getErr := d.GetVersion(c, verID, true)
  356. if getErr != nil {
  357. return getErr
  358. }
  359. bannerID := verInfo.TargetItem
  360. if err = tx.Exec("UPDATE banner SET status = 0 WHERE id = ?", bannerID).Error; err != nil {
  361. tx.Rollback()
  362. log.Error("更新banner未激活状态失败:%s", err)
  363. return err
  364. }
  365. //更新版本为草稿状态
  366. if err = tx.Exec("UPDATE version SET status = ? WHERE ver_id = ?", model.VerStatusNotReviewed, verID).Error; err != nil {
  367. tx.Rollback()
  368. log.Error("更新banner版本为草稿状态失败:%s", err)
  369. return err
  370. }
  371. //删除此版本bannerDistrict信息
  372. var delPosition int32
  373. var delSubPosition int32
  374. var delOrder int32
  375. var delDistrictIDs []string
  376. if delPosition, delSubPosition, delOrder, delDistrictIDs, err = d.DelBannerDistrictByVerID(c, tx, verID, bannerID); err != nil {
  377. return
  378. }
  379. //如果存在除这个版本以外同个投放id的版本 删除版本
  380. var bannerVersions []model.Version
  381. if err = tx.Where("target_item = ? and ver_id != ? and deleted_at='0000-00-00 00:00:00'",
  382. bannerID, verID).Find(&bannerVersions).Error; err != nil {
  383. log.Error("获取banner所有其他版本失败:%s", err)
  384. tx.Rollback()
  385. return err
  386. }
  387. var verIDs []uint64
  388. for _, v := range bannerVersions {
  389. //获取该版本详情 删除对应bannerDistrict信息
  390. _, _, _, _, err = d.DelBannerDistrictByVerID(c, tx, v.VerID, bannerID)
  391. if err != nil {
  392. return
  393. }
  394. verIDs = append(verIDs, v.VerID)
  395. }
  396. if verIDs != nil {
  397. if err = tx.Exec("UPDATE version SET deleted_at=? WHERE ver_id in (?)", xtime.Now().Format("2006-01-02 15:04:05"), verIDs).Error; err != nil {
  398. log.Error("删除banner版本失败:%s", err)
  399. tx.Rollback()
  400. return err
  401. }
  402. if err = tx.Exec("UPDATE version_ext SET deleted_at=? WHERE ver_id in (?)", xtime.Now().Format("2006-01-02 15:04:05"), verIDs).Error; err != nil {
  403. log.Error("删除banner ext版本失败:%s", err)
  404. tx.Rollback()
  405. return err
  406. }
  407. }
  408. tx.Commit()
  409. //删除下架相关缓存
  410. _, err = d.DelBannerCache(c, delPosition, delSubPosition, delOrder, delDistrictIDs, bannerID)
  411. return
  412. }
  413. // UnpublishBannerForced 已过期自动下架操作
  414. func (d *Dao) UnpublishBannerForced(c context.Context, verID uint64) (err error) {
  415. //获取版本信息
  416. tx := d.db.Begin()
  417. verInfo, _, getErr := d.GetVersion(c, verID, true)
  418. if getErr != nil {
  419. return getErr
  420. }
  421. //取消激活banner
  422. bannerID := verInfo.TargetItem
  423. if err = tx.Exec("UPDATE banner SET status = 0 WHERE id = ?", bannerID).Error; err != nil {
  424. tx.Rollback()
  425. log.Error("更新banner未激活状态失败:%s", err)
  426. return err
  427. }
  428. //删除bannerDistrict信息
  429. var delPosition int32
  430. var delSubPosition int32
  431. var delOrder int32
  432. var delDistrictIDs []string
  433. if delPosition, delSubPosition, delOrder, delDistrictIDs, err = d.DelBannerDistrictByVerID(c, tx, verID, bannerID); err != nil {
  434. return
  435. }
  436. //更新版本为强制下架状态
  437. if err = tx.Exec("UPDATE version SET status = ? WHERE ver_id = ?", model.VerStatusOffShelfForced, verID).Error; err != nil {
  438. tx.Rollback()
  439. log.Error("更新banner版本为强制下架状态失败:%s", err)
  440. return err
  441. }
  442. tx.Commit()
  443. //删除下架相关缓存
  444. _, err = d.DelBannerCache(c, delPosition, delSubPosition, delOrder, delDistrictIDs, bannerID)
  445. return
  446. }
  447. // CgBannerStatus 更改banner版本状态
  448. func (d *Dao) CgBannerStatus(c context.Context, info *item.VersionStatusRequest) (err error) {
  449. switch info.OpType {
  450. case 0:
  451. //手动取消激活操作
  452. err = d.UnpublishBannerManual(c, info.VerId)
  453. case 1:
  454. //提交审核操作
  455. err = d.db.Exec("UPDATE version SET status = ? WHERE ver_id = ?", model.VerStatusReadyForReview, info.VerId).Error
  456. if err != nil {
  457. return err
  458. }
  459. //提交审核时 记入versionLog
  460. err = d.AddVersionLog(c, &model.VersionLog{
  461. VerID: info.VerId,
  462. Type: 2, //用户操作记录
  463. Log: "提交审核",
  464. Uname: info.Uname,
  465. })
  466. case 2:
  467. //删除操作
  468. err = d.DeleteBanner(c, info.VerId)
  469. case 3:
  470. //上架操作
  471. err = d.PassOrPublishBanner(c, info.VerId)
  472. case 4:
  473. //已过期自动下架操作
  474. err = d.UnpublishBannerForced(c, info.VerId)
  475. default:
  476. return ecode.NothingFound
  477. }
  478. return
  479. }