You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

362 lines
10 KiB

  1. package couponusers
  2. import (
  3. "CouponBackendGo/api/v1/couponusers"
  4. "CouponBackendGo/internal/dao"
  5. "CouponBackendGo/internal/service"
  6. "context"
  7. "database/sql"
  8. "encoding/json"
  9. "errors"
  10. "github.com/gogf/gf/v2/frame/g"
  11. "github.com/gogf/gf/v2/os/gtime"
  12. "github.com/xuri/excelize/v2"
  13. "mime/multipart"
  14. "strconv"
  15. "strings"
  16. )
  17. type sCouponUsers struct{}
  18. func init() {
  19. service.RegisterCouponUsers(&sCouponUsers{})
  20. }
  21. // 根据优惠券id查看拥有优惠券的用户
  22. func (s *sCouponUsers) GetCouponUsersByCondition(ctx context.Context, couponId, jwcode int, name string, pageNo, pageSize int) (users []couponusers.GetCouponUsersRes, err error) {
  23. //没有条件查询时,分页
  24. if jwcode == 0 && name == "" {
  25. /*查询所有数据*/
  26. //在coupon_users中查询出对应的jwcode
  27. err = dao.CouponUsers.Ctx(ctx).Fields("jwcode").
  28. Where("coupon_id = ", couponId).Page(pageNo, pageSize).Scan(&users)
  29. if err != nil {
  30. return nil, errors.New("根据卡券id搜索jwcode失败")
  31. }
  32. //根据jwcode查询用户信息
  33. for i, userInfo := range users {
  34. err = dao.MemberInfo.Ctx(ctx).Fields("jwcode", "name", "deptName", "shopName").
  35. Where("jwcode = ?", userInfo.Jwcode).Scan(&users[i])
  36. if err != nil {
  37. return nil, errors.New("根据jwcode搜索用户信息失败")
  38. }
  39. }
  40. /*查询所有数据*/
  41. return users, err
  42. } else { //有条件查询时,不在分页,全查后筛选
  43. /*查询所有数据*/
  44. //在coupon_users中查询出对应的jwcode
  45. err = dao.CouponUsers.Ctx(ctx).Fields("jwcode").
  46. Where("coupon_id = ", couponId).Scan(&users)
  47. if err != nil {
  48. return nil, errors.New("根据卡券id搜索jwcode失败")
  49. }
  50. //根据jwcode查询用户信息
  51. for i, userInfo := range users {
  52. err = dao.MemberInfo.Ctx(ctx).Fields("jwcode", "name", "deptName", "shopName").
  53. Where("jwcode = ?", userInfo.Jwcode).Scan(&users[i])
  54. if err != nil {
  55. return nil, errors.New("根据jwcode搜索用户信息失败")
  56. }
  57. }
  58. /*查询所有数据*/
  59. //条件查询
  60. if jwcode != 0 && name == "" {
  61. var result []couponusers.GetCouponUsersRes
  62. for _, user := range users {
  63. if user.Jwcode == jwcode {
  64. result = append(result, user)
  65. }
  66. }
  67. return result, err
  68. } else if jwcode == 0 && name != "" {
  69. var result []couponusers.GetCouponUsersRes
  70. for _, user := range users {
  71. if strings.Contains(user.Name, name) {
  72. result = append(result, user)
  73. }
  74. }
  75. return result, err
  76. } else if jwcode != 0 && name != "" {
  77. var result []couponusers.GetCouponUsersRes
  78. for _, user := range users {
  79. if user.Jwcode == jwcode && strings.Contains(user.Name, name) {
  80. result = append(result, user)
  81. }
  82. }
  83. return result, err
  84. }
  85. return users, err
  86. }
  87. }
  88. // 根据jwcode,优惠券id删除用户
  89. func (s *sCouponUsers) DeleteCouponUserByJwcode(ctx context.Context, couponId, jwcode int) (result sql.Result, err error) {
  90. if jwcode == 0 {
  91. return nil, errors.New("jwcode不能为空")
  92. }
  93. if couponId == 0 {
  94. return nil, errors.New("couponId不能为空")
  95. }
  96. result, err = dao.CouponUsers.Ctx(ctx).Where("coupon_id = ?", couponId).Where("jwcode = ?", jwcode).Delete()
  97. if err != nil {
  98. return nil, errors.New("删除用户失败")
  99. }
  100. return result, err
  101. }
  102. // 通过excel导入精网号
  103. func (s *sCouponUsers) InsertJwcodeByExcel(file multipart.File) (jwcodes []int, err error) {
  104. //打开文件并返回一个excelize.File对象,用于读取和操作Excel文件的内容
  105. f, err := excelize.OpenReader(file)
  106. if err != nil {
  107. return nil, errors.New("打开文件失败")
  108. }
  109. // 延时关闭文件
  110. defer func(f *excelize.File) {
  111. err := f.Close()
  112. if err != nil {
  113. return // 返回错误
  114. }
  115. }(f)
  116. //读取所有工作表名称
  117. GetSheetMap := f.GetSheetMap()
  118. if len(GetSheetMap) == 0 {
  119. return nil, errors.New("没有工作表")
  120. }
  121. rows, err := f.GetRows("Sheet1")
  122. if err != nil {
  123. return nil, err
  124. }
  125. // 将每行的第一列转换为int,并添加到切片中
  126. for i, row := range rows {
  127. //跳过第一行
  128. if i == 0 {
  129. continue
  130. }
  131. // 假设jwcode在每行的第一列
  132. /*参数校验*/
  133. //参数校验,检查每行是否有足够数据
  134. if len(row) == 0 {
  135. continue // 跳过空行
  136. }
  137. //参数校验,检查jwcode是否为非空字符串
  138. jwcodeStr := row[0]
  139. if jwcodeStr == "" {
  140. continue // 跳过空行
  141. }
  142. //将字符串转换为整数
  143. jwcode, err := strconv.Atoi(jwcodeStr)
  144. if err != nil {
  145. return nil, errors.New("参数转换失败")
  146. }
  147. jwcodes = append(jwcodes, jwcode)
  148. /*参数校验*/
  149. }
  150. return //返回jwcodes切片
  151. }
  152. // 根据精网号发放用户优惠券
  153. func (s *sCouponUsers) InsertCouponUsersByJwcodes(ctx context.Context, jwcodes []int, couponId int) (num int, err error) {
  154. //去重
  155. m := make(map[int]bool)
  156. var uniqueJwcodes []int //存放去重后的精网号
  157. for _, jwcode := range jwcodes {
  158. if _, exist := m[jwcode]; !exist {
  159. m[jwcode] = true
  160. uniqueJwcodes = append(uniqueJwcodes, jwcode)
  161. }
  162. }
  163. //插入数据
  164. for _, jwcode := range uniqueJwcodes {
  165. //检查数据库中是否存在
  166. count, err := dao.CouponUsers.Ctx(ctx).Where("jwcode = ?", jwcode).Where("coupon_id = ?", couponId).Count()
  167. if err != nil {
  168. return num, errors.New("检索数据库中是否已存在数据失败")
  169. }
  170. //不存在,可以插入
  171. if count == 0 {
  172. result, err := dao.CouponUsers.Ctx(ctx).Insert(g.Map{
  173. "jwcode": jwcode,
  174. "coupon_id": couponId,
  175. "time": gtime.Now().Unix(),
  176. })
  177. if err != nil {
  178. return num, errors.New("插入数据库失败")
  179. }
  180. //获取受影响的行数
  181. affected, err := result.RowsAffected()
  182. num += int(affected)
  183. }
  184. }
  185. return num, err //返回受影响的行数,即新增的条数
  186. }
  187. // 导入满足条件的用户jwcode到redis
  188. func (s *sCouponUsers) InsertJwcodesToRedisByExcel(file multipart.File) (err error) {
  189. var ctx g.Ctx
  190. //打开文件并返回一个excelize.File对象,用于读取和操作Excel文件的内容
  191. f, err := excelize.OpenReader(file)
  192. if err != nil {
  193. return errors.New("打开文件失败")
  194. }
  195. // 延时关闭文件
  196. defer func(f *excelize.File) {
  197. err := f.Close()
  198. if err != nil {
  199. // 处理关闭文件时的错误
  200. return
  201. }
  202. }(f)
  203. //读取所有工作表名称
  204. GetSheetMap := f.GetSheetMap()
  205. if len(GetSheetMap) == 0 {
  206. return errors.New("没有工作表")
  207. }
  208. // 读取第一个工作表
  209. rows, err := f.GetRows("Sheet1")
  210. if err != nil {
  211. return err
  212. }
  213. // 将每行的第一列转换为int,并添加到切片中
  214. var jwcodes []int
  215. for i, row := range rows {
  216. //跳过第一行
  217. if i == 0 {
  218. continue
  219. }
  220. // 假设jwcode在每行的第一列
  221. /*参数校验*/
  222. //参数校验,检查每行是否有足够数据
  223. if len(row) == 0 {
  224. continue // 跳过空行
  225. }
  226. //参数校验,检查jwcode是否为非空字符串
  227. jwcodeStr := row[0]
  228. if jwcodeStr == "" {
  229. continue // 跳过空行
  230. }
  231. //将字符串转换为整数
  232. jwcode, err := strconv.Atoi(jwcodeStr)
  233. if err != nil {
  234. return errors.New("参数转换失败")
  235. }
  236. jwcodes = append(jwcodes, jwcode)
  237. /*参数校验*/
  238. }
  239. //将jwcodes存入redis
  240. MarshalJwcodes, _ := json.Marshal(jwcodes)
  241. _, err = g.Redis().Set(ctx, "EligibleJwcodes", MarshalJwcodes)
  242. if err != nil {
  243. return errors.New("存入redis失败")
  244. }
  245. return //返回nil表示成功
  246. }
  247. // 判断某用户能否抽到卡券
  248. func (s *sCouponUsers) IsEligibleUser(ctx context.Context, jwcode int, couponIds []int) (img string, err error) {
  249. /*从redis中获取符合条件的精网号EligibleJwcodes*/
  250. redisResult, err := g.Redis().Get(ctx, "EligibleJwcodes")
  251. if err != nil {
  252. return "", errors.New("从redis中获取数据失败")
  253. }
  254. var EligibleJwcodes []int
  255. err = json.Unmarshal(redisResult.Bytes(), &EligibleJwcodes)
  256. if err != nil {
  257. return "", errors.New("redis中数据解析失败")
  258. }
  259. if len(EligibleJwcodes) == 0 {
  260. return "", errors.New("redis中数据为空")
  261. }
  262. /*从redis中获取符合条件的精网号EligibleJwcodes*/
  263. //检查jwcode是否在EligibleJwcodes中
  264. for _, EligibleJwcode := range EligibleJwcodes {
  265. if EligibleJwcode == jwcode {
  266. //存在,有资格,判断是否抽取过
  267. for _, couponId := range couponIds {
  268. count, err := dao.CouponUsers.Ctx(ctx).Where("jwcode = ?", jwcode).Where("coupon_id = ?", couponId).Count()
  269. if err != nil {
  270. return "", errors.New("检索数据库中是否已存在数据失败")
  271. }
  272. //有记录,抽取过
  273. if count > 0 {
  274. err = dao.CouponUsers.Ctx(ctx).Fields("img_url").Where("jwcode = ?", jwcode).Where("coupon_id = ?", couponId).Scan(&img)
  275. return img, errors.New("该用户已领取过该卡券")
  276. }
  277. }
  278. //所有的都没有记录,没有抽取过
  279. return "", nil
  280. }
  281. }
  282. return "", errors.New("该用户不满足领取条件")
  283. }
  284. // 给单个用户发放卡券
  285. func (s *sCouponUsers) IssueCouponToUser(ctx context.Context, jwcode, couponId int) (err error) {
  286. //查看库中是否已经存在
  287. count, err := dao.CouponUsers.Ctx(ctx).Where("jwcode = ?", jwcode).Where("coupon_id = ?", couponId).Count()
  288. if err != nil {
  289. return errors.New("检索数据库中是否已存在数据失败")
  290. }
  291. //已存在 不添加,直接返回
  292. if count > 0 {
  293. return errors.New("该用户已领取该卡券")
  294. }
  295. //不存在 查看是否满足条件,满足就添加,不满足就返回
  296. /*从redis中获取符合条件的精网号EligibleJwcodes*/
  297. redisResult, err := g.Redis().Get(ctx, "EligibleJwcodes")
  298. if err != nil {
  299. return errors.New("从redis中获取数据失败")
  300. }
  301. var EligibleJwcodes []int
  302. err = json.Unmarshal(redisResult.Bytes(), &EligibleJwcodes)
  303. if err != nil {
  304. return errors.New("redis中数据解析失败")
  305. }
  306. if len(EligibleJwcodes) == 0 {
  307. return errors.New("redis中数据为空")
  308. }
  309. /*从redis中获取符合条件的精网号EligibleJwcodes*/
  310. //检查jwcode是否在EligibleJwcodes中
  311. for _, EligibleJwcode := range EligibleJwcodes {
  312. if EligibleJwcode == jwcode {
  313. //存在,可以插入
  314. _, err := dao.CouponUsers.Ctx(ctx).Insert(g.Map{
  315. "jwcode": jwcode,
  316. "coupon_id": couponId,
  317. "time": gtime.Now().Unix(),
  318. })
  319. if err != nil {
  320. return errors.New("插入数据库失败")
  321. }
  322. return err
  323. }
  324. }
  325. return errors.New("该用户精网号不符合领取条件") //遍历完了所有满足条件的用户,发现不在其中,不符合条件
  326. }
  327. /*未编写*/
  328. // 导出拥有卡券的用户列表
  329. func (s *sCouponUsers) ExportCouponUsers() {
  330. }