merchant_repo.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package store
  2. import (
  3. "spider/internal/model"
  4. "spider/internal/plugin"
  5. "strings"
  6. "gorm.io/gorm"
  7. )
  8. // SaveRaw inserts a merchant into merchants_raw from plugin output.
  9. // Dedup: same tg_username + same source_url => skip.
  10. // Returns true if a new record was inserted.
  11. func (s *Store) SaveRaw(data plugin.MerchantData) (bool, error) {
  12. if strings.TrimSpace(data.TgUsername) == "" {
  13. return false, nil // no tg_username = don't insert
  14. }
  15. username := strings.TrimPrefix(strings.TrimSpace(data.TgUsername), "@")
  16. tgLink := data.TgLink
  17. if tgLink == "" && username != "" {
  18. tgLink = "https://t.me/" + username
  19. }
  20. raw := model.MerchantRaw{
  21. MerchantName: data.MerchantName,
  22. TgUsername: username,
  23. TgLink: tgLink,
  24. Website: data.Website,
  25. Email: data.Email,
  26. Phone: data.Phone,
  27. IndustryTag: data.IndustryTag,
  28. SourceType: data.SourceType,
  29. SourceName: data.SourceName,
  30. SourceURL: data.SourceURL,
  31. OriginalText: data.OriginalText,
  32. Status: "raw",
  33. }
  34. // Dedup: same tg_username + source_url => skip
  35. var count int64
  36. s.DB.Model(&model.MerchantRaw{}).
  37. Where("tg_username = ? AND source_url = ?", username, data.SourceURL).
  38. Count(&count)
  39. if count > 0 {
  40. return false, nil
  41. }
  42. if err := s.DB.Create(&raw).Error; err != nil {
  43. return false, err
  44. }
  45. return true, nil
  46. }
  47. // ListRawByStatus returns raw merchants with the given status.
  48. func (s *Store) ListRawByStatus(status string, limit int) ([]model.MerchantRaw, error) {
  49. var raws []model.MerchantRaw
  50. q := s.DB.Where("status = ?", status)
  51. if limit > 0 {
  52. q = q.Limit(limit)
  53. }
  54. err := q.Find(&raws).Error
  55. return raws, err
  56. }
  57. // UpdateRawStatus sets the status of a raw merchant.
  58. func (s *Store) UpdateRawStatus(id uint, status string) error {
  59. return s.DB.Model(&model.MerchantRaw{}).Where("id = ?", id).Update("status", status).Error
  60. }
  61. // SaveClean upserts a clean merchant by tg_username.
  62. func (s *Store) SaveClean(m *model.MerchantClean) error {
  63. var existing model.MerchantClean
  64. err := s.DB.Where("tg_username = ?", m.TgUsername).First(&existing).Error
  65. if err == gorm.ErrRecordNotFound {
  66. return s.DB.Create(m).Error
  67. }
  68. if err != nil {
  69. return err
  70. }
  71. m.ID = existing.ID
  72. return s.DB.Save(m).Error
  73. }
  74. // ListClean returns paginated clean merchants with optional filters.
  75. func (s *Store) ListClean(filters map[string]string, page, pageSize int) ([]model.MerchantClean, int64, error) {
  76. var merchants []model.MerchantClean
  77. var total int64
  78. q := s.DB.Model(&model.MerchantClean{})
  79. if v, ok := filters["status"]; ok && v != "" {
  80. q = q.Where("status = ?", v)
  81. }
  82. if v, ok := filters["level"]; ok && v != "" {
  83. q = q.Where("level = ?", v)
  84. }
  85. if v, ok := filters["industry_tag"]; ok && v != "" {
  86. q = q.Where("industry_tag = ?", v)
  87. }
  88. if v, ok := filters["search"]; ok && v != "" {
  89. like := "%" + v + "%"
  90. q = q.Where("tg_username LIKE ? OR merchant_name LIKE ?", like, like)
  91. }
  92. q.Count(&total)
  93. offset := (page - 1) * pageSize
  94. err := q.Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&merchants).Error
  95. return merchants, total, err
  96. }