project.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. package dao
  2. import (
  3. "context"
  4. "encoding/json"
  5. "go-common/app/service/openplatform/ticket-item/model"
  6. "go-common/library/ecode"
  7. "go-common/library/log"
  8. "strconv"
  9. "github.com/jinzhu/gorm"
  10. )
  11. // ProjectMainInfo 项目版本内容
  12. type ProjectMainInfo struct {
  13. Name string `json:"name"`
  14. Type string `json:"type"`
  15. Size string `json:"size"`
  16. ProvinceID string `json:"province_id"`
  17. CityID string `json:"city_id"`
  18. DistrictID string `json:"district_id"`
  19. VenueID string `json:"venue_id"`
  20. PlaceID string `json:"place_id"`
  21. StartTime int32 `json:"start_time"`
  22. EndTime int32 `json:"end_time"`
  23. Docs []ImgInfo `json:"docs"`
  24. Screens []Screen `json:"screens"`
  25. TicketsSingle []TicketSingle `json:"tickets_single"`
  26. TicketsPass []TicketPass `json:"tickets_pass"`
  27. TicketsAllPass []TicketPass `json:"tickets_allpass"`
  28. PerformanceImg PerformanceImg `json:"performance_image"`
  29. PerformanceDesc string `json:"performance_desc"`
  30. SellingProp string `json:"selling_prop"`
  31. TagIDs []string `json:"tag_ids"`
  32. GuestIDs []int64 `json:"guest_ids"`
  33. GuestImgs []GuestImg `json:"guest_imgs"`
  34. CompID string `json:"comp_id"`
  35. Label string `json:"label"`
  36. SponsorType string `json:"sponsor_type"`
  37. }
  38. // ImgInfo 图片信息
  39. type ImgInfo struct {
  40. URL string `json:"url"`
  41. Desc string `json:"desc"`
  42. }
  43. // GuestImg 嘉宾图片信息
  44. type GuestImg struct {
  45. ID int64 `json:"id"`
  46. ImgURL string `json:"img_url"`
  47. }
  48. // Screen 场次信息
  49. type Screen struct {
  50. ScreenName string `json:"screen_name"`
  51. ScreenStartTime int32 `json:"screen_start_time"`
  52. ScreenEndTime int32 `json:"screen_end_time"`
  53. ScreenType string `json:"screen_type"`
  54. PickSeat int32 `json:"pick_seat"`
  55. TicketType string `json:"ticket_type"`
  56. DeliveryType string `json:"delivery_type"`
  57. ScreenID string `json:"screen_id"`
  58. }
  59. // TicketSingle 单场票信息
  60. type TicketSingle struct {
  61. Name string `json:"name"`
  62. Type string `json:"type"`
  63. Color string `json:"color"`
  64. BuyLimit string `json:"buy_limit"`
  65. PayValue int64 `json:"pay_value"`
  66. PayMethod string `json:"pay_method"`
  67. Desc string `json:"descrp"`
  68. TicketID string `json:"ticket_sc_id"`
  69. BuyLimitNum []string `json:"buy_limit_num"`
  70. }
  71. // TicketPass 通票信息
  72. type TicketPass struct {
  73. Name string `json:"name"`
  74. LinkTicket int32 `json:"link_ticket"`
  75. LinkScreens []int32 `json:"link_screens"`
  76. Color string `json:"color"`
  77. BuyLimit string `json:"buy_limit"`
  78. PayValue int64 `json:"pay_value"`
  79. PayMethod string `json:"pay_method"`
  80. Desc string `json:"descrp"`
  81. TicketID string `json:"ticket_sc_id"`
  82. BuyLimitNum []string `json:"buy_limit_num"`
  83. }
  84. // PerformanceImg 项目图片信息
  85. type PerformanceImg struct {
  86. First ImgInfo `json:"first"`
  87. Banner ImgInfo `json:"banner"`
  88. }
  89. const (
  90. // BuyNumLimit 默认限购值
  91. BuyNumLimit = `{"per":8}`
  92. )
  93. // AddProject 项目初始化
  94. func (d *Dao) AddProject(c context.Context, verID uint64) (pid int64, err error) {
  95. var verExtInfo model.VersionExt
  96. if dbErr := d.db.Where("ver_id = ?", verID).First(&verExtInfo).Error; dbErr != nil {
  97. log.Error("获取项目版本详情失败:%s", dbErr)
  98. return 0, dbErr
  99. }
  100. decodedMainInfo := d.GetDefaultMainInfo()
  101. err = json.Unmarshal([]byte(verExtInfo.MainInfo), &decodedMainInfo)
  102. if err != nil {
  103. return
  104. }
  105. // 开启事务
  106. tx := d.db.Begin()
  107. // 创建新project
  108. var project model.Item
  109. if project, err = d.CreateProject(c, tx, verID, decodedMainInfo); err != nil {
  110. return
  111. }
  112. pid = project.ID
  113. if pid == 0 {
  114. tx.Rollback()
  115. log.Error("pid not initialized")
  116. return 0, ecode.TicketPidIsEmpty
  117. }
  118. // 创建新项目详情在project_extra表
  119. if err = d.CreateProjectExtInfo(c, tx, pid, decodedMainInfo.PerformanceDesc); err != nil {
  120. return
  121. }
  122. // 创建场次screen
  123. scIDList := make(map[int32]int64)
  124. scStartTimes := make(map[int32]int32)
  125. scEndTimes := make(map[int32]int32)
  126. var screen model.Screen
  127. for k, v := range decodedMainInfo.Screens {
  128. screenType, _ := strconv.ParseInt(v.ScreenType, 10, 64)
  129. ticketType, _ := strconv.ParseInt(v.TicketType, 10, 64)
  130. deliveryType, _ := strconv.ParseInt(v.DeliveryType, 10, 64)
  131. screen = model.Screen{
  132. ProjectID: pid,
  133. Name: v.ScreenName,
  134. StartTime: v.ScreenStartTime,
  135. EndTime: v.ScreenEndTime,
  136. Type: int32(screenType),
  137. TicketType: int32(ticketType),
  138. DeliveryType: int32(deliveryType),
  139. PickSeat: v.PickSeat,
  140. ScreenType: 1, // 单场票场次
  141. }
  142. if screen, err = d.CreateOrUpdateScreen(c, tx, screen); err != nil {
  143. return
  144. }
  145. // 获取的screen自增id复制到maininfo内
  146. decodedMainInfo.Screens[k].ScreenID = strconv.FormatInt(screen.ID, 10)
  147. scIDList[int32(k)] = screen.ID
  148. scStartTimes[int32(k)] = screen.StartTime
  149. scEndTimes[int32(k)] = screen.EndTime
  150. }
  151. // 创建票价
  152. TkSingleIDList := make(map[int32]int64)
  153. TkSingleTypeList := make(map[int32]int32)
  154. var tkPrice model.TicketPrice
  155. for k, v := range decodedMainInfo.TicketsSingle {
  156. saleType, _ := strconv.ParseInt(v.Type, 10, 64)
  157. buyLimit, _ := strconv.ParseInt(v.BuyLimit, 10, 64)
  158. payMethod, _ := strconv.ParseInt(v.PayMethod, 10, 64)
  159. ticketID, baseErr := model.GetTicketIDFromBase()
  160. if ticketID == 0 || baseErr != nil {
  161. tx.Rollback()
  162. log.Error("baseCenter获取ticketID失败 ticketid:%s,baseErr:%s", ticketID, baseErr)
  163. return 0, baseErr
  164. }
  165. tkPrice = model.TicketPrice{
  166. ID: ticketID,
  167. ProjectID: pid,
  168. Desc: v.Name,
  169. Type: 1, // 单场票
  170. SaleType: int32(saleType),
  171. Color: v.Color,
  172. BuyLimit: int32(buyLimit),
  173. PaymentMethod: int32(payMethod),
  174. PaymentValue: v.PayValue,
  175. DescDetail: v.Desc,
  176. IsSale: 1, // 可售
  177. IsRefund: -10, // 不可退
  178. OriginPrice: -1, // 未設置
  179. MarketPrice: -1,
  180. SaleStart: TimeNull, // 0000-00-00 00:00:00
  181. SaleEnd: TimeNull,
  182. }
  183. if tkPrice, err = d.CreateOrUpdateTkPrice(c, tx, tkPrice, 0); err != nil {
  184. return
  185. }
  186. //票价限购
  187. limitData := d.FormatByPrefix(v.BuyLimitNum, "buy_limit_")
  188. if err = d.CreateOrUpdateTkPriceExtra(c, tx, limitData, ticketID, pid); err != nil {
  189. return
  190. }
  191. // 获取的ticketPrice自增id复制到mainInfo内
  192. decodedMainInfo.TicketsSingle[k].TicketID = strconv.FormatInt(tkPrice.ID, 10)
  193. TkSingleIDList[int32(k)] = ticketID
  194. TkSingleTypeList[int32(k)] = int32(saleType)
  195. }
  196. var passScID, allPassScID int64
  197. // 创建通票场次
  198. passScID, err = d.GetOrUpdatePassSc(c, tx, pid, decodedMainInfo.TicketsPass, scStartTimes, scEndTimes, scTypePass, 0)
  199. if err != nil {
  200. return
  201. }
  202. decodedMainInfo.TicketsPass, err = d.InsertOrUpdateTkPass(c, tx, pid, passScID, decodedMainInfo.TicketsPass, TkTypePass, scIDList, TkSingleIDList, TkSingleTypeList)
  203. if err != nil {
  204. return
  205. }
  206. // 创建联票场次
  207. allPassScID, err = d.GetOrUpdatePassSc(c, tx, pid, decodedMainInfo.TicketsAllPass, scStartTimes, scEndTimes, scTypeAllPass, 0)
  208. if err != nil {
  209. return
  210. }
  211. decodedMainInfo.TicketsAllPass, err = d.InsertOrUpdateTkPass(c, tx, pid, allPassScID, decodedMainInfo.TicketsAllPass, TkTypeAllPass, scIDList, TkSingleIDList, TkSingleTypeList)
  212. if err != nil {
  213. return
  214. }
  215. // 创建标签
  216. for _, tagID := range decodedMainInfo.TagIDs {
  217. err = d.CreateTag(c, tx, pid, tagID)
  218. if err != nil {
  219. return
  220. }
  221. }
  222. // 创建嘉宾
  223. guestImgMap := make(map[int64]string)
  224. // 组合嘉宾对应头像map
  225. if decodedMainInfo.GuestIDs != nil {
  226. if decodedMainInfo.GuestImgs == nil {
  227. var guestInfoList []model.Guest
  228. if err = d.db.Select("id, guest_img").Where("id IN (?)", decodedMainInfo.GuestIDs).Find(&guestInfoList).Error; err != nil {
  229. log.Error("获取嘉宾信息失败:%s", err)
  230. tx.Rollback()
  231. return
  232. }
  233. for _, v := range guestInfoList {
  234. guestImgMap[v.ID] = v.GuestImg
  235. }
  236. } else {
  237. for _, v := range decodedMainInfo.GuestImgs {
  238. guestImgMap[v.ID] = v.ImgURL
  239. }
  240. }
  241. }
  242. var position int64
  243. for _, guestID := range decodedMainInfo.GuestIDs {
  244. if err = tx.Create(&model.ProjectGuest{
  245. ProjectID: pid,
  246. GuestID: guestID,
  247. Position: position,
  248. GuestImg: guestImgMap[guestID],
  249. }).Error; err != nil {
  250. log.Error("项目嘉宾添加失败:%s", err)
  251. tx.Rollback()
  252. return
  253. }
  254. position++
  255. }
  256. // 将有场次票价id的mainInfo更新到version_ext
  257. encodedMainInfo, jsonErr := json.Marshal(decodedMainInfo)
  258. if jsonErr != nil {
  259. log.Error("JSONEncode MainInfo失败")
  260. tx.Rollback()
  261. return pid, jsonErr
  262. }
  263. finalMainInfo := string(encodedMainInfo)
  264. if len(finalMainInfo) > 4000 {
  265. log.Error("信息量过大")
  266. tx.Rollback()
  267. return pid, ecode.TicketMainInfoTooLarge
  268. }
  269. // 编辑version_ext
  270. err = tx.Model(&model.VersionExt{}).Where("ver_id = ? and type = ?", verID, 1).Update("main_info", finalMainInfo).Error
  271. if err != nil {
  272. tx.Rollback()
  273. log.Error("更新versionext失败: %s", err)
  274. }
  275. // 提交事务
  276. tx.Commit()
  277. return pid, nil
  278. }
  279. // CreateProject 灌入项目表
  280. func (d *Dao) CreateProject(c context.Context, tx *gorm.DB, verID uint64, decodedMainInfo ProjectMainInfo) (project model.Item, err error) {
  281. // 创建新project
  282. venueID, _ := strconv.ParseInt(decodedMainInfo.VenueID, 10, 64)
  283. placeID, _ := strconv.ParseInt(decodedMainInfo.PlaceID, 10, 64)
  284. compID, _ := strconv.ParseInt(decodedMainInfo.CompID, 10, 64)
  285. projectType, _ := strconv.ParseInt(decodedMainInfo.Type, 10, 64)
  286. projectSponsorType, _ := strconv.ParseInt(decodedMainInfo.SponsorType, 10, 64)
  287. performanceImg, _ := json.Marshal(decodedMainInfo.PerformanceImg)
  288. projectInfo := model.Item{
  289. Name: decodedMainInfo.Name,
  290. StartTime: decodedMainInfo.StartTime,
  291. EndTime: decodedMainInfo.EndTime,
  292. VenueID: venueID,
  293. PlaceID: placeID,
  294. CompID: compID,
  295. PerformanceImage: string(performanceImg),
  296. TicketDesc: decodedMainInfo.SellingProp,
  297. Type: int32(projectType),
  298. VerID: verID,
  299. SponsorType: int32(projectSponsorType),
  300. Label: decodedMainInfo.Label,
  301. BuyNumLimit: BuyNumLimit,
  302. IsSale: 1, // 默认值可售
  303. ExpressFee: -2, //默认值
  304. }
  305. if err = tx.Create(&projectInfo).Error; err != nil {
  306. log.Error("新建项目失败:%s", err)
  307. tx.Rollback()
  308. return model.Item{}, err
  309. }
  310. return projectInfo, nil
  311. }
  312. // CreateProjectExtInfo 灌入项目详情表
  313. func (d *Dao) CreateProjectExtInfo(c context.Context, tx *gorm.DB, projectID int64, performanceDesc string) (err error) {
  314. projectExtInfo := model.ItemDetail{
  315. ProjectID: projectID,
  316. PerformanceDesc: performanceDesc,
  317. }
  318. if err = tx.Create(&projectExtInfo).Error; err != nil {
  319. log.Error("新建项目详情失败:%s", err)
  320. tx.Rollback()
  321. return err
  322. }
  323. return nil
  324. }
  325. // GetDefaultMainInfo 获取初始化数组的mainInfo
  326. func (d *Dao) GetDefaultMainInfo() ProjectMainInfo {
  327. return ProjectMainInfo{
  328. Docs: []ImgInfo{},
  329. Screens: []Screen{},
  330. TicketsSingle: []TicketSingle{},
  331. TicketsPass: []TicketPass{},
  332. TicketsAllPass: []TicketPass{},
  333. TagIDs: []string{},
  334. GuestIDs: []int64{},
  335. GuestImgs: []GuestImg{},
  336. }
  337. }