ticket.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. package dao
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "go-common/app/service/openplatform/ticket-item/model"
  7. "go-common/library/cache/redis"
  8. "go-common/library/ecode"
  9. "go-common/library/log"
  10. "strconv"
  11. "strings"
  12. "time"
  13. "github.com/jinzhu/gorm"
  14. )
  15. const (
  16. // TkTypeSingle 单场票
  17. TkTypeSingle = 1
  18. // TkTypePass 通票
  19. TkTypePass = 2
  20. // TkTypeAllPass 联票
  21. TkTypeAllPass = 3
  22. // TimeNull 空时间:0000-00-00 00:00:00
  23. TimeNull = -62135596800
  24. )
  25. // RawTkListByItem 批量取项目票价
  26. func (d *Dao) RawTkListByItem(c context.Context, ids []int64) (info map[int64][]*model.TicketInfo, err error) {
  27. info = make(map[int64][]*model.TicketInfo)
  28. tkExt := make(map[int64]map[string]*model.TicketPriceExtra)
  29. rows, err := d.db.Model(&model.TicketPrice{}).Where("project_id in (?) and deleted_at = 0", ids).Rows()
  30. extRows, err := d.db.Model(&model.TicketPriceExtra{}).Where("project_id in (?) and is_deleted = 0", ids).Rows()
  31. if err != nil {
  32. log.Error("RawListByItem(%v) error(%v)", model.JSONEncode(ids), err)
  33. return
  34. }
  35. defer rows.Close()
  36. defer extRows.Close()
  37. for extRows.Next() {
  38. var ext model.TicketPriceExtra
  39. err = d.db.ScanRows(extRows, &ext)
  40. if err != nil {
  41. log.Error("RawListByItem(%v) error(%v)", model.JSONEncode(ids), err)
  42. return
  43. }
  44. if _, ok := tkExt[ext.SkuID]; !ok {
  45. tkExt[ext.SkuID] = make(map[string]*model.TicketPriceExtra)
  46. }
  47. if _, ok := tkExt[ext.SkuID][ext.Attrib]; !ok {
  48. tkExt[ext.SkuID][ext.Attrib] = new(model.TicketPriceExtra)
  49. }
  50. tkExt[ext.SkuID][ext.Attrib] = &ext
  51. }
  52. for rows.Next() {
  53. var tk model.TicketInfo
  54. err = d.db.ScanRows(rows, &tk)
  55. if err != nil {
  56. log.Error("RawListByItem(%v) error(%v)", model.JSONEncode(ids), err)
  57. return
  58. }
  59. if _, ok := tkExt[tk.ID]; ok {
  60. tk.BuyNumLimit = tkExt[tk.ID]
  61. }
  62. info[tk.ProjectID] = append(info[tk.ProjectID], &tk)
  63. }
  64. return
  65. }
  66. // CacheTkListByItem 缓存取项目票价
  67. func (d *Dao) CacheTkListByItem(c context.Context, ids []int64) (info map[int64][]*model.TicketInfo, err error) {
  68. var keys []interface{}
  69. keyPidMap := make(map[string]int64, len(ids))
  70. for _, id := range ids {
  71. key := keyItemTicket(id)
  72. if _, ok := keyPidMap[key]; !ok {
  73. // duplicate mid
  74. keyPidMap[key] = id
  75. keys = append(keys, key)
  76. }
  77. }
  78. conn := d.redis.Get(c)
  79. defer conn.Close()
  80. var data [][]byte
  81. log.Info("MGET %v", model.JSONEncode(keys))
  82. if data, err = redis.ByteSlices(conn.Do("mget", keys...)); err != nil {
  83. log.Error("TkList MGET %v ERR: %v", model.JSONEncode(keys), err)
  84. return
  85. }
  86. info = make(map[int64][]*model.TicketInfo)
  87. for _, d := range data {
  88. if d != nil {
  89. var tks []*model.TicketInfo
  90. json.Unmarshal(d, &tks)
  91. info[tks[0].ProjectID] = tks
  92. }
  93. }
  94. return
  95. }
  96. // AddCacheTkListByItem 取项目票价添加缓存
  97. func (d *Dao) AddCacheTkListByItem(c context.Context, info map[int64][]*model.TicketInfo) (err error) {
  98. conn := d.redis.Get(c)
  99. defer func() {
  100. conn.Flush()
  101. conn.Close()
  102. }()
  103. var data []interface{}
  104. var keys []string
  105. for k, v := range info {
  106. b, _ := json.Marshal(v)
  107. key := keyItemTicket(k)
  108. keys = append(keys, key)
  109. data = append(data, key, b)
  110. }
  111. log.Info("MSET %v", keys)
  112. if err = conn.Send("MSET", data...); err != nil {
  113. return
  114. }
  115. for i := 0; i < len(data); i += 2 {
  116. conn.Send("EXPIRE", data[i], CacheTimeout)
  117. }
  118. return
  119. }
  120. // RawTkList 批量取票价
  121. func (d *Dao) RawTkList(c context.Context, ids []int64) (list map[int64]*model.TicketInfo, err error) {
  122. list = make(map[int64]*model.TicketInfo)
  123. tkExt := make(map[int64]map[string]*model.TicketPriceExtra)
  124. rows, err := d.db.Model(&model.TicketPrice{}).Where("id in (?) and deleted_at = 0", ids).Rows()
  125. extRows, err := d.db.Model(&model.TicketPriceExtra{}).Where("sku_id in (?) and is_deleted = 0", ids).Rows()
  126. if err != nil {
  127. log.Error("RawTkList(%v) error(%v)", model.JSONEncode(ids), err)
  128. return
  129. }
  130. defer rows.Close()
  131. defer extRows.Close()
  132. for extRows.Next() {
  133. var ext model.TicketPriceExtra
  134. err = d.db.ScanRows(extRows, &ext)
  135. if err != nil {
  136. log.Error("RawListByItem(%v) error(%v)", model.JSONEncode(ids), err)
  137. return
  138. }
  139. if _, ok := tkExt[ext.SkuID]; !ok {
  140. tkExt[ext.SkuID] = make(map[string]*model.TicketPriceExtra)
  141. }
  142. if _, ok := tkExt[ext.SkuID][ext.Attrib]; !ok {
  143. tkExt[ext.SkuID][ext.Attrib] = new(model.TicketPriceExtra)
  144. }
  145. tkExt[ext.SkuID][ext.Attrib] = &ext
  146. }
  147. for rows.Next() {
  148. var tk model.TicketInfo
  149. err = d.db.ScanRows(rows, &tk)
  150. if err != nil {
  151. log.Error("RawTkList(%v) error(%v)", model.JSONEncode(ids), err)
  152. return
  153. }
  154. if _, ok := tkExt[tk.ID]; ok {
  155. tk.BuyNumLimit = tkExt[tk.ID]
  156. }
  157. list[tk.ID] = &tk
  158. }
  159. return
  160. }
  161. // CacheTkList 缓存取项目票价
  162. func (d *Dao) CacheTkList(c context.Context, ids []int64) (list map[int64]*model.TicketInfo, err error) {
  163. var keys []interface{}
  164. keyPidMap := make(map[string]int64, len(ids))
  165. for _, id := range ids {
  166. key := keyTicket(id)
  167. if _, ok := keyPidMap[key]; !ok {
  168. // duplicate mid
  169. keyPidMap[key] = id
  170. keys = append(keys, key)
  171. }
  172. }
  173. conn := d.redis.Get(c)
  174. defer conn.Close()
  175. var data [][]byte
  176. log.Info("MGET %v", model.JSONEncode(keys))
  177. if data, err = redis.ByteSlices(conn.Do("mget", keys...)); err != nil {
  178. log.Error("TkList MGET %v ERR: %v", model.JSONEncode(keys), err)
  179. return
  180. }
  181. list = make(map[int64]*model.TicketInfo)
  182. for _, d := range data {
  183. if d != nil {
  184. var tk *model.TicketInfo
  185. json.Unmarshal(d, &tk)
  186. list[tk.ID] = tk
  187. }
  188. }
  189. return
  190. }
  191. // AddCacheTkList 取项目票价添加缓存
  192. func (d *Dao) AddCacheTkList(c context.Context, list map[int64]*model.TicketInfo) (err error) {
  193. conn := d.redis.Get(c)
  194. defer func() {
  195. conn.Flush()
  196. conn.Close()
  197. }()
  198. var data []interface{}
  199. var keys []string
  200. for k, v := range list {
  201. b, _ := json.Marshal(v)
  202. key := keyTicket(k)
  203. keys = append(keys, key)
  204. data = append(data, key, b)
  205. }
  206. log.Info("MSET %v", keys)
  207. if err = conn.Send("MSET", data...); err != nil {
  208. return
  209. }
  210. for i := 0; i < len(data); i += 2 {
  211. conn.Send("EXPIRE", data[i], CacheTimeout)
  212. }
  213. return
  214. }
  215. // CreateOrUpdateTkPrice 创建或更新票种
  216. func (d *Dao) CreateOrUpdateTkPrice(c context.Context, tx *gorm.DB, priceInfo model.TicketPrice, opType int32) (model.TicketPrice, error) {
  217. if opType == 0 {
  218. // create
  219. if err := tx.Create(&priceInfo).Error; err != nil {
  220. log.Error("创建票种失败:%s", err)
  221. tx.Rollback()
  222. return model.TicketPrice{}, err
  223. }
  224. } else {
  225. // update
  226. if err := tx.Model(&model.TicketPrice{}).Where("id = ?", priceInfo.ID).Updates(
  227. map[string]interface{}{
  228. "project_id": priceInfo.ProjectID,
  229. "desc": priceInfo.Desc,
  230. "type": priceInfo.Type,
  231. "sale_type": priceInfo.SaleType,
  232. "color": priceInfo.Color,
  233. "buy_limit": priceInfo.BuyLimit,
  234. "payment_method": priceInfo.PaymentMethod,
  235. "payment_value": priceInfo.PaymentValue,
  236. "desc_detail": priceInfo.DescDetail,
  237. }).Error; err != nil {
  238. log.Error("更新票种失败:%s", err)
  239. tx.Rollback()
  240. return model.TicketPrice{}, err
  241. }
  242. }
  243. return priceInfo, nil
  244. }
  245. // InsertOrUpdateTkPass 新建或更新通票联票票价
  246. func (d *Dao) InsertOrUpdateTkPass(c context.Context, tx *gorm.DB, pid int64, scID int64, tksPass []TicketPass, tkType int32,
  247. scIDList map[int32]int64, TkSingleIDList map[int32]int64, TkSingleTypeList map[int32]int32) ([]TicketPass, error) {
  248. alphabetTable := model.AlphabetTable()
  249. for k, v := range tksPass {
  250. if _, ok := TkSingleIDList[v.LinkTicket]; !ok {
  251. tx.Rollback()
  252. log.Error("关联票种不存在")
  253. return nil, ecode.TicketLkTkNotFound
  254. }
  255. if _, ok := TkSingleTypeList[v.LinkTicket]; !ok {
  256. tx.Rollback()
  257. log.Error("关联票种类型不存在")
  258. return nil, ecode.TicketLkTkTypeNotFound
  259. }
  260. var linkScIDs []int64
  261. for _, linkScID := range v.LinkScreens {
  262. if _, ok := scIDList[linkScID]; !ok {
  263. tx.Rollback()
  264. log.Error("关联场次不存在")
  265. return nil, ecode.TicketLkScNotFound
  266. }
  267. linkScIDs = append(linkScIDs, scIDList[linkScID])
  268. }
  269. tkID, _ := strconv.ParseInt(v.TicketID, 10, 64)
  270. symbol := alphabetTable[k]
  271. if tkID == 0 {
  272. // create
  273. newTkID, err := model.GetTicketIDFromBase()
  274. if err != nil {
  275. tx.Rollback()
  276. log.Error("basecenter获取通票票价id失败:%s", err)
  277. return nil, err
  278. }
  279. buyLimit, _ := strconv.ParseInt(v.BuyLimit, 10, 64)
  280. payMethod, _ := strconv.ParseInt(v.PayMethod, 10, 64)
  281. if err = tx.Create(&model.TicketPrice{
  282. ID: newTkID,
  283. ProjectID: pid,
  284. ScreenID: scID,
  285. Desc: v.Name,
  286. BuyLimit: int32(buyLimit),
  287. ParentID: TkSingleIDList[v.LinkTicket],
  288. Color: v.Color,
  289. DescDetail: v.Desc,
  290. PaymentMethod: int32(payMethod),
  291. PaymentValue: v.PayValue,
  292. Type: tkType,
  293. SaleType: TkSingleTypeList[v.LinkTicket],
  294. Symbol: symbol,
  295. LinkSc: model.Implode(",", linkScIDs),
  296. IsSale: 0, // 不可售
  297. IsRefund: -10, // 不可退
  298. OriginPrice: -1, // 未設置
  299. MarketPrice: -1,
  300. SaleStart: TimeNull, // 0000-00-00 00:00:00
  301. SaleEnd: TimeNull,
  302. }).Error; err != nil {
  303. log.Error("通票或联票创建失败:%s", err)
  304. tx.Rollback()
  305. return nil, err
  306. }
  307. //票价限购
  308. limitData := d.FormatByPrefix(v.BuyLimitNum, "buy_limit_")
  309. if err = d.CreateOrUpdateTkPriceExtra(c, tx, limitData, newTkID, pid); err != nil {
  310. return nil, err
  311. }
  312. tksPass[k].TicketID = strconv.FormatInt(newTkID, 10)
  313. } else {
  314. // update
  315. if err := tx.Model(&model.TicketPrice{}).Where("id = ?", tkID).Updates(map[string]interface{}{
  316. "screen_id": scID,
  317. "desc": v.Name,
  318. "buy_limit": v.BuyLimit,
  319. "parent_id": TkSingleIDList[v.LinkTicket],
  320. "color": v.Color,
  321. "desc_detail": v.Desc,
  322. "payment_method": v.PayMethod,
  323. "payment_value": v.PayValue,
  324. "type": tkType,
  325. "sale_type": TkSingleTypeList[v.LinkTicket],
  326. "symbol": symbol,
  327. "link_sc": model.Implode(",", linkScIDs),
  328. }).Error; err != nil {
  329. log.Error("通票或联票票价信息更新失败:%s", err)
  330. tx.Rollback()
  331. return nil, err
  332. }
  333. //票价限购
  334. limitData := d.FormatByPrefix(v.BuyLimitNum, "buy_limit_")
  335. if err := d.CreateOrUpdateTkPriceExtra(c, tx, limitData, tkID, pid); err != nil {
  336. return nil, err
  337. }
  338. }
  339. }
  340. return tksPass, nil
  341. }
  342. // DelTicket 根据id删除票种或票价
  343. func (d *Dao) DelTicket(c context.Context, tx *gorm.DB, oldIDs []int64, newIDs []int64, pid int64, isPrice bool) error {
  344. delIDs, _ := model.ClassifyIDs(oldIDs, newIDs)
  345. for _, delID := range delIDs {
  346. if !d.CanDelTicket(delID, isPrice) {
  347. tx.Rollback()
  348. return ecode.TicketCannotDelTk
  349. }
  350. if isPrice {
  351. // TODO 存在需要删除的票价时 检查票价是否在坐票可选座场次下 是的话需要删除对应的座位图
  352. // 删除票价
  353. if err := tx.Exec("UPDATE ticket_price SET deleted_at=? WHERE id = ? AND project_id = ?", time.Now().Format("2006-01-02 15:04:05"), delID, pid).Error; err != nil {
  354. log.Error("删除票价失败:%s", err)
  355. tx.Rollback()
  356. return ecode.TicketDelTkFailed
  357. }
  358. // 删除票价额外信息表
  359. if err := tx.Model(&model.TicketPriceExtra{}).Where("sku_id = ? project_id = ?", delID, pid).Update("is_deleted", 1).Error; err != nil {
  360. log.Error("删除票种额外信息记录失败:%s", err)
  361. tx.Rollback()
  362. return ecode.TicketDelTkExFailed
  363. }
  364. } else {
  365. // 票种 需要获取 所有票价id
  366. priceIDs, err := d.GetPriceIDs(delID, 2)
  367. if err != nil {
  368. tx.Rollback()
  369. return err
  370. }
  371. // TODO 存在需要删除的票价时 检查票价是否在坐票可选座场次下 是的话需要删除对应的座位图
  372. // 将票种id加到需要删除的票价array里
  373. priceIDs = append(priceIDs, delID)
  374. // 删除票种票价
  375. if err := tx.Exec("UPDATE ticket_price SET deleted_at=? WHERE id IN (?) AND project_id = ?", time.Now().Format("2006-01-02 15:04:05"), priceIDs, pid).Error; err != nil {
  376. log.Error("删除票种及其票价失败:%s", err)
  377. tx.Rollback()
  378. return ecode.TicketDelTkFailed
  379. }
  380. //删除票价额外信息表
  381. if err := tx.Model(&model.TicketPriceExtra{}).Where("sku_id IN (?) AND project_id = ?", priceIDs, pid).Update("is_deleted", 1).Error; err != nil {
  382. log.Error("删除票种及票价额外信息记录失败:%s", err)
  383. tx.Rollback()
  384. return ecode.TicketDelTkExFailed
  385. }
  386. }
  387. }
  388. return nil
  389. }
  390. // CanDelTicket 检查是否可以删除票价或票种
  391. func (d *Dao) CanDelTicket(id int64, isPrice bool) bool {
  392. var priceIDs []int64
  393. if isPrice {
  394. // 票价
  395. priceIDs = append(priceIDs, id)
  396. } else {
  397. // 票种 需要获取 所有票价id
  398. ids, err := d.GetPriceIDs(id, 2)
  399. if err != nil {
  400. return false
  401. }
  402. priceIDs = ids
  403. }
  404. if d.HasPromotion(priceIDs, 2) || d.StockChanged(priceIDs) {
  405. log.Error("票价下存在拼团或者库存有变动:%d", id)
  406. return false
  407. }
  408. return true
  409. }
  410. // GetPriceIDs 获取场次或票种下所有票价id inputType 1-场次id 2-票种id
  411. func (d *Dao) GetPriceIDs(id int64, inputType int32) ([]int64, error) {
  412. var priceIDs []int64
  413. var prices []model.TicketPrice
  414. var whereStr string
  415. if inputType == 1 {
  416. // id = screenID
  417. whereStr = "screen_id = ? and deleted_at = 0"
  418. } else {
  419. // id = skuID
  420. whereStr = "parent_id = ? and deleted_at = 0"
  421. }
  422. if err := d.db.Select("id").Where(whereStr, id).Find(&prices).Error; err != nil {
  423. log.Error("获取场次或票种下所有票价id失败:%s", err)
  424. return nil, err
  425. }
  426. for _, v := range prices {
  427. priceIDs = append(priceIDs, v.ID)
  428. }
  429. return priceIDs, nil
  430. }
  431. // ticket_price表同时包含票价和票种,票种的parent_id为0,票价的parent_id为票种ID
  432. // 票种不直接使用于场次,票价继承自票种,指定某一场次
  433. // 以此实现“票种可以在一个项目下多个场次通用”
  434. // 坐票只存在单场票
  435. // TxGetTicketPrice 获取票价的价格标志和场次(事务)
  436. func (d *Dao) TxGetTicketPrice(c context.Context, tx *gorm.DB, id int64) (ticketPrice *model.TicketPrice, err error) {
  437. ticketPrice = new(model.TicketPrice)
  438. if err = tx.Select("symbol, screen_id").Where("id = ? AND parent_id <> 0 AND deleted_at = 0", id).First(ticketPrice).Error; err != nil {
  439. log.Error("TxGetTicketPrice error(%v)", err)
  440. }
  441. return
  442. }
  443. // TxGetPriceSymbols 获取场次下的所有票价的父票种ID、价格和标志(事务)
  444. func (d *Dao) TxGetPriceSymbols(c context.Context, tx *gorm.DB, screen int64) (ticketPrices []*model.TicketPrice, err error) {
  445. if err = tx.Select("parent_id, price, symbol").Where("screen_id = ? AND type = ? AND parent_id <> 0 AND deleted_at = 0", screen, TkTypeSingle).Find(&ticketPrices).Error; err != nil {
  446. log.Error("TxGetPriceSymbols error(%v)", err)
  447. }
  448. return
  449. }
  450. // TxGetParentTicketPrice 获取票种-单场票(事务)
  451. func (d *Dao) TxGetParentTicketPrice(c context.Context, tx *gorm.DB, id int64) (ticketPrice *model.TicketPrice, err error) {
  452. ticketPrice = new(model.TicketPrice)
  453. if err = tx.Where("id = ? AND type = ? AND deleted_at = 0", id, TkTypeSingle).First(ticketPrice).Error; err != nil {
  454. log.Error("TxGetParentTicketPrice error(%v)", err)
  455. }
  456. return
  457. }
  458. // TxBatchAddTicketPrice 批量添加票价(事务)
  459. func (d *Dao) TxBatchAddTicketPrice(c context.Context, tx *gorm.DB, ticketPrices []*model.TicketPrice) (err error) {
  460. if len(ticketPrices) == 0 {
  461. return
  462. }
  463. var values = make([]string, len(ticketPrices))
  464. for i, tp := range ticketPrices {
  465. values[i] = fmt.Sprintf("(%d,%d,%d,%d,%d,'%s','%s',%d,'%s',%d,%d,%d,%d,%d,%d,%d,'%s',%d,'%s',%d,'%s',%d,%d,%d)", tp.ID, tp.ProjectID, tp.ScreenID, tp.Price, tp.BuyLimit, tp.Desc, tp.Color, tp.ParentID, tp.Symbol, tp.IsSale, tp.OriginPrice, tp.PaymentMethod, tp.PaymentValue, tp.Type, tp.IsRefund, tp.IsVisible, tp.DescDetail, tp.SaleType, tp.SaleTime, tp.LinkTicketID, tp.LinkSc, tp.SaleStart, tp.SaleEnd, tp.MarketPrice)
  466. }
  467. var sql = fmt.Sprintf("INSERT INTO `ticket_price` (`id`, `project_id`, `screen_id`, `price`, `buy_limit`, `desc`, `color`, `parent_id`, `symbol`, `is_sale`, `origin_price`, `payment_method`, `payment_value`, `type`, `is_refund`, `is_visible`, `desc_detail`, `sale_type`, `sale_time`, `link_ticket_id`, `link_sc`, `sale_start`, `sale_end`, `market_price`) VALUES %s;", strings.Join(values, ","))
  468. if err = tx.Exec(sql).Error; err != nil {
  469. log.Error("批量添加票种(%s)失败:%s", sql, err)
  470. err = ecode.NotModified
  471. return
  472. }
  473. return
  474. }
  475. // CreateOrUpdateTkPriceExtra 创建票价额外信息记录
  476. func (d *Dao) CreateOrUpdateTkPriceExtra(c context.Context, tx *gorm.DB, input map[string]string, skuID int64, pid int64) (err error) {
  477. data := d.FormatInputData(input, skuID, pid)
  478. var tmpTkExtra model.TicketPriceExtra
  479. for attrib, val := range data {
  480. if err = tx.Where("sku_id = ? and project_id = ? and attrib = ? and is_deleted=0", skuID, pid, attrib).First(&tmpTkExtra).Error; err != nil {
  481. //除去没查找到记录的报错 其他直接抛错
  482. if err != ecode.NothingFound {
  483. log.Error("获取票价%s额外信息失败:%s", skuID, err)
  484. tx.Rollback()
  485. return
  486. }
  487. }
  488. if tmpTkExtra.ID == 0 {
  489. // create
  490. if err = tx.Create(&val).Error; err != nil {
  491. log.Error("创建票价额外信息记录失败:%s", err)
  492. tx.Rollback()
  493. return
  494. }
  495. } else {
  496. // update
  497. if err = tx.Model(&model.TicketPriceExtra{}).Where("sku_id = ? and project_id = ? and attrib = ?", skuID, pid, attrib).Update("value", val).Error; err != nil {
  498. log.Error("更新票价额外信息记录失败:%s", err)
  499. tx.Rollback()
  500. return
  501. }
  502. }
  503. }
  504. return
  505. }
  506. // FormatInputData 格式化input数据
  507. func (d *Dao) FormatInputData(input map[string]string, skuID int64, pid int64) (res []model.TicketPriceExtra) {
  508. for key, value := range input {
  509. res = append(res, model.TicketPriceExtra{
  510. Attrib: key,
  511. Value: value,
  512. SkuID: skuID,
  513. ProjectID: pid,
  514. })
  515. }
  516. return
  517. }
  518. // FormatByPrefix 给键值加前缀
  519. func (d *Dao) FormatByPrefix(input []string, prefix string) map[string]string {
  520. result := make(map[string]string)
  521. for k, v := range input {
  522. result[prefix+strconv.Itoa(k)] = v
  523. }
  524. return result
  525. }