merchant_product.go 8.6 KB

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