merchant_product.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package merchant
  2. import (
  3. "errors"
  4. "eta/eta_mini_ht_api/models"
  5. "fmt"
  6. "github.com/shopspring/decimal"
  7. "sort"
  8. "sync/atomic"
  9. "time"
  10. )
  11. type SaleStatus string
  12. type MerchantProductType string
  13. const (
  14. detailColumns = "id,title,price,is_permanent,valid_days,type,sale_status,cover_src,cover_url,description,source_id,created_time,updated_time"
  15. sourceIdColumn = "id,source_id"
  16. )
  17. const (
  18. OnSale SaleStatus = "on_sale" //上架
  19. OffSale SaleStatus = "off_sale" //下架
  20. Package MerchantProductType = "package"
  21. Report MerchantProductType = "report"
  22. Video MerchantProductType = "video"
  23. Audio MerchantProductType = "audio"
  24. )
  25. // MerchantProduct 商户产品信息结构体
  26. type MerchantProduct struct {
  27. ID int `gorm:"column:id;primary_key;autoIncrement;comment:主键"`
  28. SourceID int `gorm:"column:source_id;type:int(11);comment:单品或者套餐对应的主键"`
  29. Title string `gorm:"column:title;type:varchar(255);comment:标题"`
  30. CoverSrc int `gorm:"column:cover_src;type:int(11);comment:封面图片资源库id"`
  31. CoverUrl string `gorm:"column:cover_url;type:varchar(255);comment:封面图片url"`
  32. Description string `gorm:"column:description;type:varchar(255);comment:描述"`
  33. Price decimal.Decimal `gorm:"column:price;type:decimal(10,2);comment:价格"`
  34. RiskLevel string `gorm:"-"`
  35. Type MerchantProductType `gorm:"column:type;type:enum('report','video','audio','package');not null;comment:类型"`
  36. IsPermanent bool `gorm:"column:is_permanent;type:int(1);not null;default:0;comment:是否永久"`
  37. ValidDays int `gorm:"column:valid_days;type:int(11);comment:有效期天数"`
  38. SaleStatus SaleStatus `gorm:"column:sale_status;type:enum('on_sale','off_sale');not null;default:'on_sale';comment:上架/下架状态"`
  39. Deleted bool `gorm:"column:deleted;type:tinyint(1);not null;default:0;comment:是否删除"`
  40. CreatedTime time.Time `gorm:"column:created_time;type:datetime;comment:创建时间"`
  41. UpdatedTime time.Time `gorm:"column:updated_time;type:datetime;comment:更新时间;default:CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP"`
  42. }
  43. // TableName 指定表名
  44. func (MerchantProduct) TableName() string {
  45. return "merchant_products"
  46. }
  47. func GetMerchantProductById(id int) (product MerchantProduct, err error) {
  48. db := models.Main()
  49. err = db.Select(detailColumns).Where("id = ? and deleted =?", id, false).First(&product).Error
  50. return
  51. }
  52. func GetMerchantProductBySourceId(sourceId int, productType ...MerchantProductType) (product MerchantProduct, err error) {
  53. db := models.Main()
  54. if len(productType) > 0 {
  55. if len(productType) == 1 {
  56. err = db.Select(detailColumns).Where("source_id =? and type = ? and deleted =?", sourceId, productType[0], false).First(&product).Error
  57. } else {
  58. err = db.Select(detailColumns).Where("source_id =? and type in (?) and deleted =?", sourceId, productType, false).First(&product).Error
  59. }
  60. } else {
  61. err = db.Select(detailColumns).Where("source_id =? and deleted =?", sourceId, false).First(&product).Error
  62. }
  63. return
  64. }
  65. func GetProductListBySourceIds(ids []int, detail bool, productType ...MerchantProductType) (productList []MerchantProduct, err error) {
  66. db := models.Main()
  67. var columns string
  68. if productType == nil {
  69. err = errors.New("productType参数不能为空")
  70. return
  71. }
  72. if detail {
  73. columns = detailColumns
  74. } else {
  75. columns = sourceIdColumn
  76. }
  77. if len(productType) > 0 {
  78. if len(productType) == 1 {
  79. err = db.Select(columns).Where("source_id in ? and type = ? and deleted =? order by created_time desc", ids, productType[0], false).Find(&productList).Error
  80. } else {
  81. err = db.Select(columns).Where("source_id in ? and type in (?) and deleted =? by created_time desc", ids, productType, false).Find(&productList).Error
  82. }
  83. } else {
  84. err = db.Select(columns).Where("source_id in ? and deleted =? by created_time desc", ids, productType, false).Find(&productList).Error
  85. }
  86. return
  87. }
  88. func GetTotalPageCountByProductType(productType MerchantProductType) (total int64, latestId int64) {
  89. db := models.Main()
  90. _ = db.Model(&MerchantProduct{}).Select("count(*)").Where("type=? and deleted =?", productType, false).Scan(&total).Error
  91. _ = db.Model(&MerchantProduct{}).Select("max(id)").Where("type=? and deleted =?", productType, false).Scan(&latestId).Error
  92. return
  93. }
  94. func GetProductPageByProductType(productIds []int, id int64, offset int, limit int) (list []MerchantProduct, err error) {
  95. db := models.Main()
  96. err = db.Select(detailColumns).Where("id <= ? and deleted =? and id in ? order by created_time desc limit ?,? ", id, false, productIds, offset, limit).Find(&list).Error
  97. return
  98. }
  99. func GetProductListByProductType(productType MerchantProductType, detail bool) (list []MerchantProduct, err error) {
  100. db := models.Main()
  101. var columns string
  102. if detail {
  103. columns = detailColumns
  104. } else {
  105. columns = sourceIdColumn
  106. }
  107. if productType == "" {
  108. err = errors.New("productType参数不能为空")
  109. return
  110. }
  111. err = db.Select(columns).Where(" type = ? and deleted =? order by created_time desc", productType, false).Find(&list).Error
  112. return
  113. }
  114. func CountProductList(isSignal bool) (total, latestId int64, ids []int) {
  115. db := models.Main()
  116. var condition string
  117. if isSignal {
  118. condition = "type !=?"
  119. } else {
  120. condition = "type =?"
  121. }
  122. _ = db.Select("count(*)").Where(" ? and deleted =? order by id desc ", condition, Package, false).Scan(&total).Error
  123. _ = db.Select("max(id)").Where(" ? and deleted =? order by id desc ", condition, Package, false).Scan(&total).Error
  124. _ = db.Select("id").Where(" ? and deleted =? order by id desc ", condition, Package, false).Scan(&ids).Error
  125. return
  126. }
  127. type MerchantProductIdMap struct {
  128. Type string
  129. ProductId string
  130. }
  131. func GetProductByProductType() (productIds map[string]string, err error) {
  132. db := models.Main()
  133. var productIdMap []MerchantProductIdMap
  134. sql := `SELECT type,GROUP_CONCAT(source_id ORDER BY source_id SEPARATOR ',') as source_id FROM merchant_products GROUP BY type`
  135. err = db.Raw(sql).Find(&productIdMap).Error
  136. productIds = make(map[string]string, len(productIdMap))
  137. for _, v := range productIdMap {
  138. productIds[v.Type] = v.ProductId
  139. }
  140. return
  141. }
  142. func generateSignalPdSql(idMap map[string][]int) (condition string, pars []interface{}) {
  143. for k, v := range idMap {
  144. if condition == "" {
  145. condition = "(" + fmt.Sprintf("(type =? and source_id in ?)")
  146. } else {
  147. condition = condition + fmt.Sprintf(" or (type =? and source_id in ?)")
  148. }
  149. pars = append(pars, k, v)
  150. }
  151. condition = condition + ")"
  152. return
  153. }
  154. func LatestId() (latestId int64) {
  155. db := models.Main()
  156. _ = db.Select("max(id)").Where("deleted=?", false).Scan(&latestId).Error
  157. return
  158. }
  159. type ProductDTO struct {
  160. SourceId int
  161. SourceType string
  162. Score float64
  163. }
  164. func ProductListBySort(list []ProductDTO, id int64, offset int, size int) (productList []MerchantProduct, err error) {
  165. var productMap map[string][]int
  166. sort.Slice(list, func(i, j int) bool {
  167. return list[i].Score > list[j].Score
  168. })
  169. var idSort []int
  170. for _, v := range list {
  171. idSort = append(idSort, v.SourceId)
  172. }
  173. for _, v := range list {
  174. ids := productMap[v.SourceType]
  175. ids = append(ids, v.SourceId)
  176. productMap[v.SourceType] = ids
  177. }
  178. sql, pars := generateSignalPdSql(productMap)
  179. db := models.Main()
  180. err = db.Select(detailColumns).Where(fmt.Sprintf("id <= ? and deleted =? and %s order by Field(id,?) desc limit ?,? ", sql), id, false, pars, idSort, offset, size).Find(&productList).Error
  181. return
  182. }
  183. type packageStruct struct {
  184. SourceId int
  185. Weight int32
  186. }
  187. func PackageListBySort(weightMap map[int]*atomic.Int32, id int64, offset int, size int) (productList []MerchantProduct, err error) {
  188. var packageList []packageStruct
  189. for k, v := range weightMap {
  190. packageList = append(packageList, packageStruct{
  191. SourceId: k,
  192. Weight: v.Load(),
  193. })
  194. }
  195. sort.Slice(packageList, func(i, j int) bool {
  196. return packageList[i].Weight > packageList[j].Weight
  197. })
  198. var idSort []int
  199. for _, v := range packageList {
  200. idSort = append(idSort, v.SourceId)
  201. }
  202. db := models.Main()
  203. err = db.Select(detailColumns).Where("id <= ? and type =? and deleted =? and source_id in ? order by Field(id,?) desc limit ?,? ", id, Package, false, idSort, offset, size).Find(&productList).Error
  204. return
  205. }