StoreCouponRepository.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\common\repositories\store\coupon;
  12. use app\common\dao\store\coupon\StoreCouponDao;
  13. use app\common\dao\store\coupon\StoreCouponProductDao;
  14. use app\common\model\store\coupon\StoreCoupon;
  15. use app\common\repositories\BaseRepository;
  16. use app\common\repositories\store\product\ProductRepository;
  17. use FormBuilder\Exception\FormBuilderException;
  18. use FormBuilder\Factory\Elm;
  19. use FormBuilder\Form;
  20. use think\db\exception\DataNotFoundException;
  21. use think\db\exception\DbException;
  22. use think\db\exception\ModelNotFoundException;
  23. use think\exception\ValidateException;
  24. use think\facade\Db;
  25. use think\facade\Route;
  26. /**
  27. * Class StoreCouponIssueRepository
  28. * @package app\common\repositories\store\coupon
  29. * @author xaboy
  30. * @day 2020-05-13
  31. * @mixin StoreCouponDao
  32. */
  33. class StoreCouponRepository extends BaseRepository
  34. {
  35. /**
  36. * @var StoreCouponDao
  37. */
  38. protected $dao;
  39. /**
  40. * StoreCouponIssueRepository constructor.
  41. * @param StoreCouponDao $dao
  42. */
  43. public function __construct(StoreCouponDao $dao)
  44. {
  45. $this->dao = $dao;
  46. }
  47. /**
  48. * @param int $merId
  49. * @param array $where
  50. * @param $page
  51. * @param $limit
  52. * @return array
  53. * @throws DataNotFoundException
  54. * @throws DbException
  55. * @throws ModelNotFoundException
  56. * @author xaboy
  57. * @day 2020-05-14
  58. */
  59. public function getList(?int $merId, array $where, $page, $limit)
  60. {
  61. $baseQuery = $this->dao->search($merId, $where)->with(['merchant' => function ($query) {
  62. $query->field('mer_id,mer_name,is_trader');
  63. }]);
  64. $count = $baseQuery->count($this->dao->getPk());
  65. $list = $baseQuery->page($page, $limit)->select();
  66. foreach ($list as $item) {
  67. $item->append(['used_num', 'send_num']);
  68. }
  69. return compact('count', 'list');
  70. }
  71. /**
  72. * @param array $data
  73. * @author xaboy
  74. * @day 2020/5/26
  75. */
  76. public function create(array $data)
  77. {
  78. if (isset($data['total_count'])) $data['remain_count'] = $data['total_count'];
  79. Db::transaction(function () use ($data) {
  80. $products = array_column((array)$data['product_id'], 'id');
  81. unset($data['product_id']);
  82. if ($data['type'] == 1 && !count($products))
  83. throw new ValidateException('请选择产品');
  84. $coupon = $this->dao->create($data);
  85. if (!count($products)) return $coupon;
  86. $lst = [];
  87. foreach ($products as $product) {
  88. $lst[] = [
  89. 'product_id' => (int)$product,
  90. 'coupon_id' => $coupon->coupon_id
  91. ];
  92. }
  93. app()->make(StoreCouponProductDao::class)->insertAll($lst);
  94. });
  95. }
  96. /**
  97. * @param $id
  98. * @return Form
  99. * @throws DataNotFoundException
  100. * @throws DbException
  101. * @throws FormBuilderException
  102. * @throws ModelNotFoundException
  103. * @author xaboy
  104. * @day 2020/5/26
  105. */
  106. public function cloneCouponForm($id)
  107. {
  108. $couponInfo = $this->dao->getWith($id, ['product'])->toArray();
  109. if ($couponInfo['is_timeout']) {
  110. $couponInfo['range_date'] = [$couponInfo['start_time'], $couponInfo['end_time']];
  111. }
  112. if ($couponInfo['coupon_type']) {
  113. $couponInfo['use_start_time'] = [$couponInfo['use_start_time'], $couponInfo['use_end_time']];
  114. }
  115. $couponInfo['product_id'] = [];
  116. if (count($couponInfo['product'])) {
  117. $productIds = array_column($couponInfo['product'], 'product_id');
  118. /** @var ProductRepository $make */
  119. $make = app()->make(ProductRepository::class);
  120. $products = $make->productIdByImage($couponInfo['mer_id'], $productIds);
  121. foreach ($products as $product) {
  122. $couponInfo['product_id'][] = ['id' => $product['product_id'], 'src' => $product['image']];
  123. }
  124. }
  125. $couponInfo['use_type'] = $couponInfo['use_min_price'] > 0 ? 1 : 0;
  126. return $this->form()->formData($couponInfo)->setTitle('复制优惠券');
  127. }
  128. /**
  129. * @return Form
  130. * @throws FormBuilderException
  131. * @author xaboy
  132. * @day 2020/5/20
  133. */
  134. public function form()
  135. {
  136. return Elm::createForm(Route::buildUrl('merchantCouponCreate')->build(), [
  137. Elm::input('title', '优惠券名称')->required(),
  138. Elm::radio('type', '优惠券类型', 0)
  139. ->setOptions([
  140. ['value' => 0, 'label' => '店铺券'],
  141. ['value' => 1, 'label' => '商品券'],
  142. ])->control([
  143. [
  144. 'value' => 1,
  145. 'rule' => [
  146. Elm::frameImages('product_id', '商品', '/' . config('admin.merchant_prefix') . '/setting/storeProduct?field=product_id')
  147. ->width('680px')->height('480px')->modal(['modal' => false])->prop('srcKey', 'src')->required(),
  148. ]
  149. ],
  150. ]),
  151. Elm::number('coupon_price', '优惠券面值')->min(0)->precision(1)->required(),
  152. Elm::radio('use_type', ' 使用门槛', 0)
  153. ->setOptions([
  154. ['value' => 0, 'label' => '无门槛'],
  155. ['value' => 1, 'label' => '有门槛'],
  156. ])->appendControl(0, [
  157. Elm::hidden('use_min_price', 0)
  158. ])->appendControl(1, [
  159. Elm::number('use_min_price', '优惠券最低消费')->min(0)->required(),
  160. ]),
  161. Elm::radio('coupon_type', '使用有效期', 0)
  162. ->setOptions([
  163. ['value' => 0, 'label' => '天数'],
  164. ['value' => 1, 'label' => '时间段'],
  165. ])->control([
  166. [
  167. 'value' => 0,
  168. 'rule' => [
  169. Elm::number('coupon_time', ' ', 0)->min(0)->required(),
  170. ]
  171. ],
  172. [
  173. 'value' => 1,
  174. 'rule' => [
  175. Elm::dateTimeRange('use_start_time', ' ')->required(),
  176. ]
  177. ],
  178. ]),
  179. Elm::radio('is_timeout', '领取时间', 0)->options([['label' => '限时', 'value' => 1], ['label' => '不限时', 'value' => 0]])
  180. ->appendControl(1, [Elm::dateTimeRange('range_date', ' ')->placeholder('不填为永久有效')]),
  181. Elm::radio('send_type', '类型', 0)->setOptions([
  182. ['value' => 0, 'label' => '领取'],
  183. // ['value' => 1, 'label' => '消费满赠'],
  184. ['value' => 2, 'label' => '新人券'],
  185. ['value' => 3, 'label' => '赠送券']
  186. ])->appendControl(1, [Elm::number('full_reduction', '满赠金额', 0)->min(0)->placeholder('赠送优惠券的最低消费金额')]),
  187. Elm::radio('is_limited', '是否限量', 0)->options([['label' => '限量', 'value' => 1], ['label' => '不限量', 'value' => 0]])
  188. ->appendControl(1, [Elm::number('total_count', '发布数量', 0)->min(0)]),
  189. Elm::number('sort', '排序', 0),
  190. Elm::radio('status', '状态', 1)->options([['label' => '开启', 'value' => 1], ['label' => '关闭', 'value' => 0]]),
  191. ])->setTitle('发布优惠券');
  192. }
  193. public function receiveCoupon($id, $uid)
  194. {
  195. $coupon = $this->dao->validCoupon($id, $uid);
  196. if (!$coupon)
  197. throw new ValidateException('优惠券失效');
  198. if (!is_null($coupon['issue']))
  199. throw new ValidateException('优惠券已领取');
  200. $this->sendCoupon($coupon, $uid);
  201. }
  202. public function sendCoupon(StoreCoupon $coupon, $uid, $type = 'receive')
  203. {
  204. Db::transaction(function () use ($uid, $type, $coupon) {
  205. $this->preSendCoupon($coupon, $uid, $type);
  206. app()->make(StoreCouponIssueUserRepository::class)->issue($coupon['coupon_id'], $uid);
  207. if ($coupon->is_limited) {
  208. $coupon->remain_count--;
  209. $coupon->save();
  210. }
  211. });
  212. }
  213. public function preSendCoupon(StoreCoupon $coupon, $uid, $type = 'send')
  214. {
  215. $data = $this->createData($coupon, $uid, $type);
  216. return app()->make(StoreCouponUserRepository::class)->create($data);
  217. }
  218. public function createData(StoreCoupon $coupon, $uid, $type = 'send')
  219. {
  220. $data = [
  221. 'uid' => $uid,
  222. 'coupon_title' => $coupon['title'],
  223. 'coupon_price' => $coupon['coupon_price'],
  224. 'use_min_price' => $coupon['use_min_price'],
  225. 'type' => $type,
  226. 'coupon_id' => $coupon['coupon_id'],
  227. 'mer_id' => $coupon['mer_id']
  228. ];
  229. if ($coupon['coupon_type'] == 1) {
  230. $data['start_time'] = $coupon['use_start_time'];
  231. $data['end_time'] = $coupon['use_end_time'];
  232. } else {
  233. $data['start_time'] = date('Y-m-d H:i:s');
  234. $data['end_time'] = date('Y-m-d H:i:s', strtotime("+ {$coupon['coupon_time']}day"));
  235. }
  236. return $data;
  237. }
  238. /**
  239. * TODO 优惠券发送费多用户
  240. * @param $uid
  241. * @param $id
  242. * @author Qinii
  243. * @day 2020-06-19
  244. */
  245. public function sendCouponByUser($uid, $id)
  246. {
  247. foreach ($uid as $item) {
  248. $coupon = $this->dao->validCoupon($id, $item);
  249. if (!$coupon || !is_null($coupon['issue']))
  250. continue;
  251. if ($coupon->is_limited && 0 == $coupon->remain_count)
  252. continue;
  253. $this->sendCoupon($coupon, $item);
  254. }
  255. }
  256. }