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.

368 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. "fmt"
  11. "github.com/gogf/gf/v2/frame/g"
  12. "github.com/gogf/gf/v2/os/gtime"
  13. "github.com/xuri/excelize/v2"
  14. "mime/multipart"
  15. "strconv"
  16. "strings"
  17. )
  18. type sCouponUsers struct{}
  19. func init() {
  20. service.RegisterCouponUsers(&sCouponUsers{})
  21. }
  22. // 根据优惠券id查看拥有优惠券的用户
  23. func (s *sCouponUsers) GetCouponUsersByCondition(ctx context.Context, couponId, jwcode int, name string) (users []couponusers.GetCouponUsersRes, err error) { //待解释
  24. //从redis中获取所有数据但暂时不返回, 用于条件查询
  25. value, _ := g.Redis().Get(ctx, fmt.Sprintf("%d CouponUsers", couponId))
  26. //redis中有数据
  27. if value.String() != "" {
  28. err = json.Unmarshal(value.Bytes(), &users)
  29. if err != nil {
  30. return nil, errors.New("redis中数据解析失败")
  31. }
  32. } else { //redis中没有数据
  33. //没有从redis中获取成功,从数据库中查询,并存储到redis中
  34. /*查询所有数据*/
  35. //在coupon_users中查询出对应的jwcode
  36. err = dao.CouponUsers.Ctx(ctx).Fields("jwcode").
  37. Where("coupon_id = ", couponId).Scan(&users)
  38. if err != nil {
  39. return nil, errors.New("根据卡券id搜索jwcode失败")
  40. }
  41. //根据jwcode查询用户信息
  42. for i, userInfo := range users {
  43. err = dao.MemberInfo.Ctx(ctx).Fields("jwcode", "name", "deptName", "shopName").
  44. Where("jwcode = ?", userInfo.Jwcode).Scan(&users[i])
  45. if err != nil {
  46. return nil, errors.New("根据jwcode搜索用户信息失败")
  47. }
  48. }
  49. /*查询所有数据*/
  50. //将数据存入redis
  51. UsersMarshal, _ := json.Marshal(users)
  52. _, err = g.Redis().Set(ctx, fmt.Sprintf("%d CouponUsers", couponId), UsersMarshal)
  53. if err != nil {
  54. return nil, errors.New("将数据存入redis失败")
  55. }
  56. }
  57. //条件查询
  58. if jwcode != 0 && name == "" {
  59. var result []couponusers.GetCouponUsersRes
  60. for _, user := range users {
  61. if user.Jwcode == jwcode {
  62. result = append(result, user)
  63. }
  64. }
  65. return result, err
  66. } else if jwcode == 0 && name != "" {
  67. var result []couponusers.GetCouponUsersRes
  68. for _, user := range users {
  69. if strings.Contains(user.Name, name) {
  70. result = append(result, user)
  71. }
  72. }
  73. return result, err
  74. } else if jwcode != 0 && name != "" {
  75. var result []couponusers.GetCouponUsersRes
  76. for _, user := range users {
  77. if user.Jwcode == jwcode && strings.Contains(user.Name, name) {
  78. result = append(result, user)
  79. }
  80. }
  81. return result, err
  82. }
  83. return users, err
  84. }
  85. // 根据jwcode,优惠券id删除用户
  86. func (s *sCouponUsers) DeleteCouponUserByJwcode(ctx context.Context, couponId, jwcode int) (result sql.Result, err error) {
  87. if jwcode == 0 {
  88. return nil, errors.New("jwcode不能为空")
  89. }
  90. if couponId == 0 {
  91. return nil, errors.New("couponId不能为空")
  92. }
  93. result, err = dao.CouponUsers.Ctx(ctx).Where("coupon_id = ?", couponId).Where("jwcode = ?", jwcode).Delete()
  94. if err != nil {
  95. return nil, errors.New("删除用户失败")
  96. }
  97. return result, err
  98. }
  99. // 通过excel导入精网号
  100. func (s *sCouponUsers) InsertJwcodeByExcel(file multipart.File) (jwcodes []int, err error) {
  101. //打开文件并返回一个excelize.File对象,用于读取和操作Excel文件的内容
  102. f, err := excelize.OpenReader(file)
  103. if err != nil {
  104. return nil, errors.New("打开文件失败")
  105. }
  106. // 延时关闭文件
  107. defer func(f *excelize.File) {
  108. err := f.Close()
  109. if err != nil {
  110. return // 返回错误
  111. }
  112. }(f)
  113. //读取所有工作表名称
  114. GetSheetMap := f.GetSheetMap()
  115. if len(GetSheetMap) == 0 {
  116. return nil, errors.New("没有工作表")
  117. }
  118. // 读取第一个工作表
  119. //sheetName := GetSheetMap[1]
  120. //rows, err := f.GetRows(f.GetSheetName(1))
  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. //sheetName := GetSheetMap[1]
  210. //rows, err := f.GetRows(f.GetSheetName(1))
  211. rows, err := f.GetRows("Sheet1")
  212. if err != nil {
  213. return err
  214. }
  215. // 将每行的第一列转换为int,并添加到切片中
  216. var jwcodes []int
  217. for i, row := range rows {
  218. //跳过第一行
  219. if i == 0 {
  220. continue
  221. }
  222. // 假设jwcode在每行的第一列
  223. /*参数校验*/
  224. //参数校验,检查每行是否有足够数据
  225. if len(row) == 0 {
  226. continue // 跳过空行
  227. }
  228. //参数校验,检查jwcode是否为非空字符串
  229. jwcodeStr := row[0]
  230. if jwcodeStr == "" {
  231. continue // 跳过空行
  232. }
  233. //将字符串转换为整数
  234. jwcode, err := strconv.Atoi(jwcodeStr)
  235. if err != nil {
  236. return errors.New("参数转换失败")
  237. }
  238. jwcodes = append(jwcodes, jwcode)
  239. /*参数校验*/
  240. }
  241. //将jwcodes存入redis
  242. MarshalJwcodes, _ := json.Marshal(jwcodes)
  243. _, err = g.Redis().Set(ctx, "EligibleJwcodes", MarshalJwcodes)
  244. if err != nil {
  245. return errors.New("存入redis失败")
  246. }
  247. return //返回nil表示成功
  248. }
  249. // 判断某用户能否抽到卡券
  250. func (s *sCouponUsers) IsEligibleUser(ctx context.Context, jwcode int, couponIds []int) (img string, err error) {
  251. /*从redis中获取符合条件的精网号EligibleJwcodes*/
  252. redisResult, err := g.Redis().Get(ctx, "EligibleJwcodes")
  253. if err != nil {
  254. return "", errors.New("从redis中获取数据失败")
  255. }
  256. var EligibleJwcodes []int
  257. err = json.Unmarshal(redisResult.Bytes(), &EligibleJwcodes)
  258. if err != nil {
  259. return "", errors.New("redis中数据解析失败")
  260. }
  261. if len(EligibleJwcodes) == 0 {
  262. return "", errors.New("redis中数据为空")
  263. }
  264. /*从redis中获取符合条件的精网号EligibleJwcodes*/
  265. //检查jwcode是否在EligibleJwcodes中
  266. for _, EligibleJwcode := range EligibleJwcodes {
  267. if EligibleJwcode == jwcode {
  268. //存在,有资格,判断是否抽取过
  269. for _, couponId := range couponIds {
  270. count, err := dao.CouponUsers.Ctx(ctx).Where("jwcode = ?", jwcode).Where("coupon_id = ?", couponId).Count()
  271. if err != nil {
  272. return "", errors.New("检索数据库中是否已存在数据失败")
  273. }
  274. //有记录,抽取过
  275. if count > 0 {
  276. err = dao.CouponUsers.Ctx(ctx).Fields("img_url").Where("jwcode = ?", jwcode).Where("coupon_id = ?", couponId).Scan(&img)
  277. return img, errors.New("该用户已领取过该卡券")
  278. }
  279. }
  280. //所有的都没有记录,没有抽取过
  281. return "", nil
  282. }
  283. }
  284. return "", errors.New("该用户不满足领取条件")
  285. }
  286. // 给单个用户发放卡券
  287. func (s *sCouponUsers) IssueCouponToUser(ctx context.Context, jwcode, couponId int) (err error) {
  288. //查看库中是否已经存在
  289. count, err := dao.CouponUsers.Ctx(ctx).Where("jwcode = ?", jwcode).Where("coupon_id = ?", couponId).Count()
  290. if err != nil {
  291. return errors.New("检索数据库中是否已存在数据失败")
  292. }
  293. //已存在 不添加,直接返回
  294. if count > 0 {
  295. return errors.New("该用户已领取该卡券")
  296. }
  297. //不存在 查看是否满足条件,满足就添加,不满足就返回
  298. /*从redis中获取符合条件的精网号EligibleJwcodes*/
  299. redisResult, err := g.Redis().Get(ctx, "EligibleJwcodes")
  300. if err != nil {
  301. return errors.New("从redis中获取数据失败")
  302. }
  303. var EligibleJwcodes []int
  304. err = json.Unmarshal(redisResult.Bytes(), &EligibleJwcodes)
  305. if err != nil {
  306. return errors.New("redis中数据解析失败")
  307. }
  308. if len(EligibleJwcodes) == 0 {
  309. return errors.New("redis中数据为空")
  310. }
  311. /*从redis中获取符合条件的精网号EligibleJwcodes*/
  312. //检查jwcode是否在EligibleJwcodes中
  313. for _, EligibleJwcode := range EligibleJwcodes {
  314. if EligibleJwcode == jwcode {
  315. //存在,可以插入
  316. _, err := dao.CouponUsers.Ctx(ctx).Insert(g.Map{
  317. "jwcode": jwcode,
  318. "coupon_id": couponId,
  319. "time": gtime.Now().Unix(),
  320. })
  321. if err != nil {
  322. return errors.New("插入数据库失败")
  323. }
  324. return err
  325. }
  326. }
  327. return errors.New("该用户精网号不符合领取条件") //遍历完了所有满足条件的用户,发现不在其中,不符合条件
  328. }
  329. // 添加用户选择武器记录
  330. func (s *sCouponUsers) AddRecord(ctx context.Context, jwcode int, id int, name string) (err error) {
  331. _, err = dao.CouponUsers.Ctx(ctx).Data(g.Map{
  332. "record": name,
  333. }).Where("jwcode = ? and coupon_id = ?", jwcode, id).Update()
  334. if err != nil {
  335. return errors.New("添加武器记录失败")
  336. }
  337. return
  338. }