UserCoupon.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <?php
  2. namespace App\Models;
  3. use Illuminate\Database\Eloquent\Model;
  4. use Illuminate\Support\Facades\DB;
  5. /**
  6. * 用户优惠券模型
  7. *
  8. * 表: agent.dbo.user_coupons
  9. *
  10. * 状态常量:
  11. * STATUS_UNUSED = 0 未使用
  12. * STATUS_USED = 1 已使用
  13. * STATUS_EXPIRED = 2 已过期
  14. *
  15. * 类型常量:
  16. * TYPE_FIXED = 1 固定金额(单位:元)
  17. * TYPE_PERCENT = 2 充值百分比(单位:%)
  18. */
  19. class UserCoupon extends Model
  20. {
  21. const TABLE = 'agent.dbo.user_coupons';
  22. /** @var int 未使用 */
  23. const STATUS_UNUSED = 0;
  24. /** @var int 已使用 */
  25. const STATUS_USED = 1;
  26. /** @var int 已过期 */
  27. const STATUS_EXPIRED = 2;
  28. /** @var int 固定金额券 */
  29. const TYPE_FIXED = 1;
  30. /** @var int 百分比券 */
  31. const TYPE_PERCENT = 2;
  32. protected $table = self::TABLE;
  33. public $timestamps = false;
  34. protected $fillable = [
  35. 'user_id',
  36. 'coupon_name',
  37. 'coupon_type',
  38. 'coupon_value',
  39. 'min_recharge',
  40. 'max_bonus',
  41. 'bonus_coins',
  42. 'order_sn',
  43. 'status',
  44. 'issued_at',
  45. 'used_at',
  46. 'expire_at',
  47. ];
  48. /**
  49. * 获取用户当前可用的优惠券列表
  50. *
  51. * @param int $userId
  52. * @return \Illuminate\Support\Collection
  53. */
  54. public static function getAvailableList($userId)
  55. {
  56. $data = DB::connection('write')->table(self::TABLE)
  57. ->where('user_id', $userId)
  58. ->where('status', self::STATUS_UNUSED)
  59. ->where('expire_at', '>', date('Y-m-d H:i:s'))
  60. ->orderBy('expire_at', 'asc')
  61. ->get();
  62. // 过期时间改为距离当前秒数,前端展示更友好
  63. $data->transform(function ($item) {
  64. $item->expire_in_seconds = max(0, strtotime($item->expire_at) - time());
  65. return $item;
  66. });
  67. return $data;
  68. }
  69. /**
  70. * 根据 ID 获取单张优惠券,校验归属
  71. *
  72. * @param int $couponId
  73. * @param int $userId
  74. * @return object|null
  75. */
  76. public static function getUserCouponById($couponId, $userId)
  77. {
  78. return DB::connection('write')->table(self::TABLE)
  79. ->where('id', $couponId)
  80. ->where('user_id', $userId)
  81. ->first();
  82. }
  83. /**
  84. * 使用优惠券:标记已使用、绑定订单
  85. *
  86. * @param int $couponId
  87. * @param string $orderSn
  88. * @param int $bonusCoins 实际赠送金币数(分)
  89. * @return bool
  90. */
  91. public static function markUsed($couponId, $orderSn, $bonusCoins)
  92. {
  93. return DB::connection('write')->table(self::TABLE)
  94. ->where('id', $couponId)
  95. ->where('status', self::STATUS_UNUSED)
  96. ->update([
  97. 'status' => self::STATUS_USED,
  98. 'order_sn' => $orderSn,
  99. 'bonus_coins' => $bonusCoins,
  100. 'used_at' => date('Y-m-d H:i:s'),
  101. ]) > 0;
  102. }
  103. /**
  104. * 发放优惠券给用户
  105. *
  106. * @param array $data 优惠券数据
  107. * @return int 插入ID
  108. */
  109. public static function issueToUser(array $data)
  110. {
  111. return DB::connection('write')->table(self::TABLE)->insertGetId($data);
  112. }
  113. /**
  114. * 检查用户是否已持有同类型有效优惠券(防重复发放)
  115. *
  116. * @param int $userId
  117. * @param string $couponName
  118. * @return bool
  119. */
  120. public static function hasSameCoupon($userId, $couponName)
  121. {
  122. return DB::connection('write')->table(self::TABLE)
  123. ->where('user_id', $userId)
  124. ->where('coupon_name', $couponName)
  125. ->where('status', self::STATUS_UNUSED)
  126. ->where('expire_at', '>', date('Y-m-d H:i:s'))
  127. ->exists();
  128. }
  129. /**
  130. * 批量过期更新:将已过期但状态仍为未使用的优惠券标记为过期
  131. *
  132. * @param int $userId
  133. * @return int 影响行数
  134. */
  135. public static function expireByUser($userId)
  136. {
  137. return DB::connection('write')->table(self::TABLE)
  138. ->where('user_id', $userId)
  139. ->where('status', self::STATUS_UNUSED)
  140. ->where('expire_at', '<=', date('Y-m-d H:i:s'))
  141. ->update(['status' => self::STATUS_EXPIRED]);
  142. }
  143. /**
  144. * 绑定优惠券到订单(订单创建时调用)
  145. *
  146. * @param int $couponId
  147. * @param string $orderSn
  148. * @return bool
  149. */
  150. public static function bindOrderSn($couponId, $orderSn)
  151. {
  152. return DB::connection('write')->table(self::TABLE)
  153. ->where('id', $couponId)
  154. ->where('status', self::STATUS_UNUSED)
  155. ->update(['order_sn' => $orderSn]) > 0;
  156. }
  157. /**
  158. * 根据订单号查找关联的优惠券
  159. *
  160. * @param string $orderSn
  161. * @return object|null
  162. */
  163. public static function findByOrderSn($orderSn)
  164. {
  165. return DB::connection('write')->table(self::TABLE)
  166. ->where('order_sn', $orderSn)
  167. ->first();
  168. }
  169. }