panel.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. package service
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/json"
  6. "net/http"
  7. "strconv"
  8. "time"
  9. "go-common/app/admin/main/tv/model"
  10. "go-common/library/ecode"
  11. "go-common/library/log"
  12. "github.com/jinzhu/gorm"
  13. )
  14. const (
  15. _configTableName = "tv_price_config"
  16. _valid = 0
  17. _invalid = 1
  18. _noPid = 0
  19. _orderField = "ctime"
  20. _vip = 10
  21. _online = 0
  22. _delete = 2
  23. )
  24. // PanelInfo select panel info by id
  25. func (s *Service) PanelInfo(id int64) (panelInfo *model.TvPriceConfigResp, err error) {
  26. if panelInfo, err = s.dao.GetById(id); err != nil {
  27. if err == gorm.ErrRecordNotFound {
  28. return nil, nil
  29. }
  30. log.Error("PanelInfo (%v) error(%v)", panelInfo, err)
  31. return
  32. }
  33. if panelInfo != nil {
  34. panelInfo.OriginPrice = panelInfo.Price
  35. hasDiscount, price, discountInfos := s.hasDiscount(nil, panelInfo.ID)
  36. if hasDiscount {
  37. panelInfo.Price = price
  38. }
  39. panelInfo.Items = discountInfos
  40. }
  41. return
  42. }
  43. // PanelStatus change panel status by id
  44. func (s *Service) PanelStatus(id, status int64) (err error) {
  45. var (
  46. flag bool
  47. panelInfo *model.TvPriceConfigResp
  48. )
  49. if panelInfo, err = s.dao.GetById(id); err != nil {
  50. log.Error("PanelInfo (%v) error(%v)", panelInfo, err)
  51. }
  52. if status == _online && panelInfo.SuitType == _vip {
  53. if flag, err = s.hasOnlineUpgradeVipProduct(); err != nil {
  54. log.Error("GetValidUpgradeVipProduct Err %v", err)
  55. return
  56. }
  57. if flag {
  58. err = ecode.TVVipSuitTypeConflict
  59. return err
  60. }
  61. }
  62. if panelInfo.PID == 0 && status == _delete {
  63. if err = s.dao.DB.Table(_configTableName).Where("pid = ?", id).Update("status", _delete).Error; err != nil {
  64. log.Error("PanelStatus discount (%v) error(%v)", id, err)
  65. }
  66. }
  67. if err = s.dao.PanelStatus(id, status); err != nil {
  68. log.Error("PanelStatus (%v) error(%v)", id, err)
  69. }
  70. return
  71. }
  72. // SavePanel add or update panel info
  73. func (s *Service) SavePanel(c context.Context, panel *model.TvPriceConfig) (err error) {
  74. opType := s.c.YSTParam.Update
  75. //start tx
  76. tx := s.DB.Begin()
  77. if panel.PID != 0 {
  78. _, _, discounts := s.hasDiscount(nil, panel.PID)
  79. if flag := checkDisCountTime(discounts, panel); !flag {
  80. err = ecode.TvPriceTimeConflict
  81. return err
  82. }
  83. s.copyParentExtraField(panel)
  84. }
  85. if panel.ID != 0 && panel.PID == 0 {
  86. if err = tx.Table(_configTableName).Where("pid = ?", panel.ID).
  87. Update(map[string]interface{}{
  88. "suit_type": panel.SuitType,
  89. "sub_type": panel.SubType,
  90. "selected": panel.Selected,
  91. "superscript": panel.Superscript,
  92. "month": panel.Month,
  93. }).Error; err != nil {
  94. log.Error("Update discount failed while update panel, Err %v", err)
  95. tx.Rollback()
  96. return
  97. }
  98. _, _, discounts := s.hasDiscount(tx, panel.ID)
  99. for _, discount := range discounts {
  100. if err = s.syncPanels(c, opType, &discount); err != nil {
  101. err = ecode.TvVipProdSyncErr
  102. tx.Rollback()
  103. return err
  104. }
  105. }
  106. }
  107. if panel.ID == 0 {
  108. opType = s.c.YSTParam.Insert
  109. if panel.PID == 0 {
  110. panel.Status = _invalid
  111. } else {
  112. s.copyParentExtraField(panel)
  113. }
  114. if flag := s.dao.ExistProduct(panel.ProductID); flag {
  115. err = ecode.TvVipProductExit
  116. return err
  117. }
  118. }
  119. if err = tx.Save(panel).Error; err != nil {
  120. log.Error("SavePanel %s, Err %v", panel, err)
  121. return err
  122. }
  123. if err = s.syncPanels(c, opType, panel); err != nil {
  124. err = ecode.TvVipProdSyncErr
  125. tx.Rollback()
  126. return err
  127. }
  128. tx.Commit()
  129. return
  130. }
  131. // PanelList get panle list
  132. func (s *Service) PanelList(platform, month, subType, suitType int64) (panels []*model.TvPriceConfigListResp, err error) {
  133. var (
  134. db = s.dao.DB.Model(&model.TvPriceConfigListResp{}).Where("pid = ? and status in (?, ?)", _noPid, _valid, _invalid)
  135. )
  136. if platform != 0 {
  137. db = db.Where("platform = ?", platform)
  138. }
  139. if month != 0 {
  140. db = db.Where("month = ?", month)
  141. }
  142. if subType != -1 {
  143. db = db.Where("sub_type = ?", subType)
  144. }
  145. if suitType != -1 {
  146. db = db.Where("suit_type = ?", suitType)
  147. }
  148. if err = db.Order("suit_type, sub_type desc, month desc").Find(&panels).Error; err != nil {
  149. log.Error("OrderList %v, Err %v", panels, err)
  150. return panels, err
  151. }
  152. for _, panel := range panels {
  153. hasDiscount, price, _ := s.hasDiscount(nil, panel.ID)
  154. panel.OriginPrice = panel.Price
  155. if hasDiscount {
  156. panel.Price = price
  157. }
  158. }
  159. return
  160. }
  161. // HasDiscount Judge whether there is a discount
  162. func (s *Service) hasDiscount(tx *gorm.DB, id int64) (hasDiscount bool, price int64, panels []model.TvPriceConfig) {
  163. if tx == nil {
  164. tx = s.dao.DB
  165. }
  166. if err := tx.Table(_configTableName).Where("pid = ? and status = ?", id, _valid).Find(&panels).Error; err != nil {
  167. log.Error("HasDiscount %v, Err %v", id, err)
  168. return
  169. }
  170. nowTime := time.Now().Unix()
  171. for _, panel := range panels {
  172. if int64(panel.Stime) < nowTime && nowTime < int64(panel.Etime) {
  173. hasDiscount = true
  174. price = panel.Price
  175. return
  176. }
  177. }
  178. return
  179. }
  180. // checkDisCountTime check discount time conflict
  181. func checkDisCountTime(discounts []model.TvPriceConfig, panel *model.TvPriceConfig) (flag bool) {
  182. var (
  183. startTime = panel.Stime
  184. endTime = panel.Etime
  185. )
  186. for _, discount := range discounts {
  187. // do not compare with self
  188. if panel.ID != discount.ID {
  189. if discount.Stime < startTime && startTime < discount.Etime {
  190. return false
  191. }
  192. if discount.Stime < endTime && endTime < discount.Etime {
  193. return false
  194. }
  195. if discount.Stime > startTime && endTime > discount.Etime {
  196. return false
  197. }
  198. }
  199. }
  200. return true
  201. }
  202. // checkRemotePanel check YST panel
  203. func (s *Service) checkRemotePanel(c context.Context) {
  204. var (
  205. panels []*model.TvPriceConfigListResp
  206. )
  207. if err := s.dao.DB.Table(_configTableName).Order(_orderField).Find(&panels).Error; err != nil {
  208. log.Error("CheckRemotePanel Err %v", err)
  209. return
  210. }
  211. res, _ := s.getRemotePanels(c)
  212. remotePanels := res.Product
  213. panelMap := make(map[string]*model.TvPriceConfigListResp, len(panels))
  214. remotePaneMap := make(map[string]model.Product, len(remotePanels))
  215. for i := 0; i < len(panels); i++ {
  216. panelMap[panels[i].ProductID] = panels[i]
  217. }
  218. for i := 0; i < len(remotePanels); i++ {
  219. remotePaneMap[remotePanels[i].ID] = remotePanels[i]
  220. }
  221. for i := 0; i < len(panels); i++ {
  222. rp, exists := remotePaneMap[panels[i].ProductID]
  223. if exists {
  224. s.compareFiled(rp, panels[i])
  225. } else {
  226. log.Error("Our panel not exists in YST, panel id is (%v)", panels[i].ProductID)
  227. }
  228. }
  229. for i := 0; i < len(remotePanels); i++ {
  230. p, exists := panelMap[remotePanels[i].ID]
  231. if exists {
  232. s.compareFiled(remotePanels[i], p)
  233. } else {
  234. log.Error("YST panel not exists in our db, panel id is (%v)", remotePanels[i].ID)
  235. }
  236. }
  237. }
  238. // getRemotePanels get YST panel
  239. func (s *Service) getRemotePanels(c context.Context) (res *model.RemotePanel, err error) {
  240. var (
  241. req *http.Request
  242. )
  243. res = &model.RemotePanel{}
  244. params := map[string]string{
  245. "vod_type": s.c.YSTParam.QueryPanelType,
  246. "source": s.c.YSTParam.Source,
  247. }
  248. reqBody, _ := json.Marshal(params)
  249. getRemotePanelUrl := s.c.URLConf.GetRemotePanelUrl
  250. if req, err = http.NewRequest(http.MethodPost, getRemotePanelUrl, bytes.NewReader(reqBody)); err != nil {
  251. log.Error("MerakNotify NewRequest Err %v, Url %v", err, getRemotePanelUrl)
  252. return
  253. }
  254. req.Header.Set("Content-Type", "application/json; charset=utf-8")
  255. if err = s.client.Do(c, req, &res); err != nil {
  256. log.Error("MergeUpInfo http req failed ,err:%v", err)
  257. return
  258. }
  259. return
  260. }
  261. // compareFiled compare our panel field with YST
  262. func (s *Service) compareFiled(remotePanel model.Product, panel *model.TvPriceConfigListResp) {
  263. rpid := remotePanel.ID
  264. prodiuctId := panel.ProductID
  265. if rpid != prodiuctId {
  266. log.Error("PanelInfo id different, Remote panel prodiuctId is (%v), Our panel prodiuctId is (%v)", rpid, prodiuctId)
  267. }
  268. if remotePanel.Price != panel.Price {
  269. log.Error("PanelInfo price different, Remote panel prodiuctId is (%v), Our panel prodiuctId is (%v)", rpid, prodiuctId)
  270. }
  271. if remotePanel.Contract != strconv.Itoa(int(panel.SubType)) {
  272. log.Error("PanelInfo subType different, Remote panel prodiuctId is (%v), Our panel prodiuctId is (%v)", rpid, prodiuctId)
  273. }
  274. if remotePanel.SuitType != panel.SuitType {
  275. log.Error("PanelInfo suitType different, Remote panel id is (%v), Our panel id is (%v)", rpid, prodiuctId)
  276. }
  277. if remotePanel.ProductDuration != strconv.FormatInt(panel.Month*31, 10) {
  278. log.Error("PanelInfo months different, Remote panel prodiuctId is (%v), Our panel prodiuctId is (%v)", rpid, prodiuctId)
  279. }
  280. if remotePanel.Title != panel.ProductName {
  281. log.Error("PanelInfo productName different, Remote panel prodiuctId is (%v), Our panel id prodiuctId (%v)", rpid, prodiuctId)
  282. }
  283. if panel.PID != 0 {
  284. parentPanel, err := s.dao.GetById(panel.PID)
  285. if err != nil {
  286. log.Error("PanelInfo (%v) error(%v)", parentPanel, err)
  287. }
  288. if remotePanel.ComboPkgID != parentPanel.ProductID {
  289. log.Error("PanelInfo pid different, Remote panel prodiuctId is (%v), Our panel prodiuctId is (%v)", rpid, prodiuctId)
  290. }
  291. }
  292. }
  293. // syncPanels send our panel to YST
  294. func (s *Service) syncPanels(c context.Context, opType string, panel *model.TvPriceConfig) (err error) {
  295. var (
  296. req *http.Request
  297. res struct {
  298. Result string `json:"result"`
  299. Message string `json:"message"`
  300. }
  301. params struct {
  302. OpType string `json:"optype"`
  303. Source string `json:"source"`
  304. Product model.Product `json:"product"`
  305. }
  306. )
  307. params.OpType = opType
  308. params.Source = s.c.YSTParam.Source
  309. params.Product.ID = panel.ProductID
  310. params.Product.VodType = s.c.YSTParam.InsertPanelType
  311. params.Product.Title = panel.ProductName
  312. params.Product.ProductDuration = strconv.FormatInt(31*panel.Month, 10)
  313. params.Product.Description = panel.Remark
  314. params.Product.Contract = strconv.Itoa(int(panel.SubType))
  315. if panel.PID != 0 {
  316. parentPanel, _ := s.dao.GetById(panel.PID)
  317. if parentPanel != nil {
  318. params.Product.ComboPkgID = parentPanel.ProductID
  319. params.Product.ComboDes = parentPanel.Remark
  320. } else {
  321. log.Error("Prarent PanelInfo not found, pid =(%v)", panel.PID)
  322. err = ecode.NothingFound
  323. return err
  324. }
  325. }
  326. params.Product.Price = panel.Price
  327. params.Product.SuitType = panel.SuitType
  328. reqBody, _ := json.Marshal(params)
  329. SyncPanelUrl := s.c.URLConf.SyncPanelUrl
  330. if req, err = http.NewRequest(http.MethodPost, SyncPanelUrl, bytes.NewReader(reqBody)); err != nil {
  331. log.Error("MerakNotify NewRequest Err %v, Url %v", err, SyncPanelUrl)
  332. return err
  333. }
  334. req.Header.Set("Content-Type", "application/json; charset=utf-8")
  335. if err = s.client.Do(c, req, &res); err != nil {
  336. log.Error("MergeUpInfo http req failed ,err:%v", err)
  337. return err
  338. }
  339. if res.Result != "SUCCESS" {
  340. err = ecode.TvVipProdSyncErr
  341. log.Info("Sync panel To YST Fail,err:%v", res.Message)
  342. return err
  343. }
  344. return
  345. }
  346. func (s *Service) hasOnlineUpgradeVipProduct() (flag bool, err error) {
  347. var (
  348. panels []*model.TvPriceConfig
  349. )
  350. if err = s.dao.DB.Table(_configTableName).Where("suit_type = ? and status = ? and pid = ?", _vip, _valid, _noPid).Find(&panels).Error; err != nil {
  351. log.Error("GetValidUpgradeVipProduct Err %v", err)
  352. return
  353. }
  354. flag = !(len(panels) == 0)
  355. return
  356. }
  357. func (s *Service) copyParentExtraField(panel *model.TvPriceConfig) {
  358. parentPanel, _ := s.dao.GetById(panel.PID)
  359. if parentPanel != nil {
  360. panel.SuitType = parentPanel.SuitType
  361. panel.SubType = parentPanel.SubType
  362. panel.Selected = parentPanel.Selected
  363. panel.Superscript = parentPanel.Superscript
  364. panel.Month = parentPanel.Month
  365. }
  366. }