MemberCouponController.php 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. <?php
  2. namespace app\frontend\modules\coupon\controllers;
  3. use app\common\components\ApiController;
  4. use app\common\exceptions\AppException;
  5. use app\common\facades\Setting;
  6. use app\common\models\coupon\CouponSlideShow;
  7. use app\common\modules\coupon\models\PreMemberCoupon;
  8. use app\framework\Http\Request;
  9. use app\frontend\models\Goods;
  10. use app\frontend\models\Member;
  11. use app\frontend\modules\coupon\models\Coupon;
  12. use app\frontend\modules\coupon\models\MemberCoupon;
  13. use app\common\models\MemberShopInfo;
  14. use app\frontend\modules\coupon\services\CouponConditionService;
  15. use Carbon\Carbon;
  16. use Yunshop\Hotel\common\models\CouponHotel;
  17. use Yunshop\Integral\Common\Services\SetService;
  18. use Yunshop\StoreCashier\common\models\Store;
  19. class MemberCouponController extends ApiController
  20. {
  21. //"优惠券中心"的优惠券
  22. const IS_AVAILABLE = 1; //可领取
  23. const ALREADY_GOT = 2; //已经领取
  24. const EXHAUST = 3; //已经被抢光
  25. //"个人拥有的优惠券"的状态
  26. const NOT_USED = 1; //未使用
  27. const OVERDUE = 2; //优惠券已经过期
  28. const IS_USED = 3; //已经使用
  29. const NO_LIMIT = -1; //没有限制 (比如对会员等级没有限制, 对领取总数没有限制)
  30. const TEMPLATEID = 'OPENTM200605630'; //成功发放优惠券时, 发送的模板消息的 ID
  31. // const TEMPLATEID = 'tqsXWjFgDGrlUmiOy0ci6VmVtjYxR7s-4BWtJX6jgeQ'; //临时调试用
  32. public function couponsOfMemberByStatusV2()
  33. {
  34. $status = \YunShop::request()->get('status_request');
  35. $uid = \YunShop::app()->getMemberId();
  36. $search_array = [];
  37. $now = strtotime('now');
  38. $coupons = [];
  39. switch ($status) {
  40. case self::NOT_USED:
  41. $coupons = self::getAvailableCoupons($uid, $now);
  42. $search_array = array_merge(Coupon::$typeComment,[ Coupon::TYPE_OVERDUE =>'快过期']);
  43. break;
  44. case self::OVERDUE:
  45. $coupons = self::getOverdueCoupons($uid, $now);
  46. $search_array = Coupon::$typeComment;
  47. break;
  48. case self::IS_USED:
  49. $coupons = self::getUsedCoupons($uid);
  50. $search_array = Coupon::$typeComment;
  51. break;
  52. }
  53. $data = [
  54. 'set' => [
  55. 'transfer' => Setting::get('coupon.transfer') ? true : false,
  56. ],
  57. 'data' => $coupons,
  58. 'search_array' => $this->getSearchArray($search_array)
  59. ];
  60. if (app('plugins')->isEnabled('share-coupons')) {
  61. $set = \Setting::get('share-coupons.is_open');
  62. if ($set == 1) {
  63. $data = array_merge($data,['share_coupon' => true]);
  64. }
  65. }
  66. if (app('plugins')->isEnabled('write-off-coupons')) {
  67. $set = \Setting::get('write-off-coupons.is_open');
  68. if ($set == 1) {
  69. $data = array_merge($data,['write_off_coupon' => true]);
  70. }
  71. }
  72. $coupon_set = \Setting::getByGroup('coupon');
  73. if($coupon_set['coupon_show'] == 1)
  74. {
  75. $data = array_merge($data,['combine_show' => true]);
  76. };
  77. return $this->successJson('ok', $data);
  78. }
  79. /**
  80. * 获取用户所拥有的优惠券的数据接口
  81. * @return \Illuminate\Http\JsonResponse
  82. */
  83. public function couponsOfMember()
  84. {
  85. $uid = \YunShop::app()->getMemberId();
  86. $pageSize = \YunShop::request()->get('pagesize');
  87. $pageSize = $pageSize ? $pageSize : 10;
  88. $coupons = MemberCoupon::getCouponsOfMember($uid)->paginate($pageSize)->toArray();
  89. if (empty($coupons['data'])) {
  90. return $this->errorJson('没有找到记录', []);
  91. }
  92. //添加 "是否可用" & "是否已经使用" & "是否过期" 的标识
  93. // $now = strtotime('now');
  94. foreach ($coupons['data'] as $k => &$v) {
  95. $v = $this->getTimeLimit($v);
  96. // if ($v['used'] == MemberCoupon::USED) { //已使用
  97. // $coupons['data'][$k]['api_status'] = self::IS_USED;
  98. // } elseif ($v['used'] == MemberCoupon::NOT_USED) { //未使用
  99. // if ($v['belongs_to_coupon']['time_limit'] == Coupon::COUPON_SINCE_RECEIVE) { //时间限制类型是"领取后几天有效"
  100. // $end = strtotime($v['get_time']) + $v['belongs_to_coupon']['time_days'] * 3600;
  101. // if ($now < $end) { //优惠券在有效期内
  102. // $coupons['data'][$k]['api_status'] = self::NOT_USED;
  103. // $coupons['data'][$k]['start'] = substr($v['get_time'], 0, 10); //前端需要起止时间
  104. // $coupons['data'][$k]['end'] = date('Y-m-d', $end); //前端需要起止时间
  105. // } else { //优惠券在有效期外
  106. // $coupons['data'][$k]['api_status'] = self::OVERDUE;
  107. // }
  108. // } elseif ($v['belongs_to_coupon']['time_limit'] == Coupon::COUPON_DATE_TIME_RANGE) { //时间限制类型是"时间范围"
  109. // if (($now > $v['belongs_to_coupon']['time_end'])) { //优惠券在有效期外
  110. // $coupons['data'][$k]['api_status'] = self::OVERDUE;
  111. // $coupons['data'][$k]['start'] = $coupons['data'][$k]['time_start']; //为了和前面保持一致
  112. // $coupons['data'][$k]['end'] = $coupons['data'][$k]['time_end']; //为了和前面保持一致
  113. // } else { //优惠券在有效期内
  114. // $coupons['data'][$k]['api_status'] = self::NOT_USED;
  115. // }
  116. // }
  117. // } else {
  118. // $coupons['data'][$k]['api_availability'] = self::IS_AVAILABLE;
  119. // }
  120. }
  121. return $this->successJson('ok', $coupons);
  122. }
  123. /**
  124. * @param $v
  125. * @return mixed
  126. * 获取优惠券有效时间
  127. */
  128. protected function getTimeLimit($v){
  129. $now = strtotime('now');
  130. if ($v['used'] == MemberCoupon::USED) { //已使用
  131. $v['api_status'] = self::IS_USED;
  132. } elseif ($v['used'] == MemberCoupon::NOT_USED) { //未使用
  133. if ($v['belongs_to_coupon']['time_limit'] == Coupon::COUPON_SINCE_RECEIVE) { //时间限制类型是"领取后几天有效"
  134. $end = strtotime($v['get_time']) + $v['belongs_to_coupon']['time_days'] * 3600;
  135. if ($now < $end) { //优惠券在有效期内
  136. $v['api_status'] = self::NOT_USED;
  137. $v['start'] = substr($v['get_time'], 0, 10); //前端需要起止时间
  138. $v['end'] = date('Y-m-d', $end); //前端需要起止时间
  139. } else { //优惠券在有效期外
  140. $v['api_status'] = self::OVERDUE;
  141. }
  142. } elseif ($v['belongs_to_coupon']['time_limit'] == Coupon::COUPON_DATE_TIME_RANGE) { //时间限制类型是"时间范围"
  143. if (($now > $v['belongs_to_coupon']['time_end'])) { //优惠券在有效期外
  144. $v['api_status'] = self::OVERDUE;
  145. $v['start'] = $v['time_start']; //为了和前面保持一致
  146. $v['end'] = $v['time_end']; //为了和前面保持一致
  147. } else { //优惠券在有效期内
  148. $v['api_status'] = self::NOT_USED;
  149. }
  150. }
  151. } else {
  152. $v['api_availability'] = self::IS_AVAILABLE;
  153. }
  154. return $v;
  155. }
  156. /**
  157. * 提供给用户的"优惠券中心"的数据接口
  158. * @return \Illuminate\Http\JsonResponse
  159. */
  160. public function couponsForMember()
  161. {
  162. $pageSize = \YunShop::request()->get('pagesize');
  163. $pageSize = $pageSize ? $pageSize : 10;
  164. $uid = \YunShop::app()->getMemberId();
  165. $member = MemberShopInfo::getMemberShopInfo($uid);
  166. if (empty($member)) {
  167. return $this->errorJson('没有找到该用户', []);
  168. }
  169. $memberLevel = $member->level_id;
  170. $now = strtotime('now');
  171. $coupons = Coupon::centerCouponsForMember($uid, $memberLevel, null, $now,\YunShop::request()->coupon_type?:'')
  172. ->orderBy('yz_coupon.display_order', 'desc')
  173. ->orderBy('yz_coupon.updated_at', 'desc');
  174. $coupons = $coupons->paginate($pageSize)->toArray();
  175. foreach ($coupons['data'] as &$item) {
  176. $item['has_many_member_coupon_count'] = MemberCoupon::uniacid()->select('uid')->where('coupon_id' ,$item['id'])->distinct()->get()->count();
  177. }
  178. //添加"是否可领取" & "是否已抢光" & "是否已领取"的标识
  179. $couponsData = self::getCouponData($coupons, $memberLevel);
  180. $slideShows = CouponSlideShow::uniacid()
  181. ->where('is_show',1)
  182. ->orderBy('sort','asc')
  183. ->orderBy('id','asc')
  184. ->limit(10)
  185. ->get();
  186. if (app('plugins')->isEnabled('integral')) {
  187. $integral_plugin_name = SetService::getIntegralName();
  188. }
  189. $data = [
  190. 'data' => $couponsData,
  191. 'search_array' => $this->getSearchArray(Coupon::$typeComment),//Coupon::$typeComment
  192. 'slide_shows' => $slideShows,
  193. 'integral_plugin_name' => $integral_plugin_name ?? '消费积分',//消费积分自定义名称
  194. ];
  195. //领券中心表单
  196. if (!is_null(\app\common\modules\shop\ShopConfig::current()->get('coupon_form'))) {
  197. $class = array_get(\app\common\modules\shop\ShopConfig::current()->get('coupon_form'), 'class');
  198. $function = array_get(\app\common\modules\shop\ShopConfig::current()->get('coupon_form'), 'function');
  199. $form = $class::$function($uid);
  200. if($form && $form != -1)
  201. {
  202. $data = array_merge($data,['coupon_form' => $form]);
  203. }
  204. }
  205. return $this->successJson('ok', $data);
  206. }
  207. /**
  208. * 提供给店铺装修的"优惠券中心"的数据接口
  209. * @return \Illuminate\Http\JsonResponse
  210. */
  211. public function couponsForDesigner(Request $request, $integrated = null)
  212. {
  213. $uid = \YunShop::app()->getMemberId();
  214. $member = MemberShopInfo::getMemberShopInfo($uid);
  215. if (empty($member)) {
  216. if(is_null($integrated)){
  217. return $this->errorJson('没有找到该用户', []);
  218. }else{
  219. return show_json(0,'没有找到该用户');
  220. }
  221. }
  222. $memberLevel = $member->level_id;
  223. $now = strtotime('now');
  224. $coupons = Coupon::getCouponsForMember($uid, $memberLevel, null, $now)
  225. ->orderBy('display_order', 'desc')
  226. ->orderBy('updated_at', 'desc');
  227. if ($coupons->get()->isEmpty()) {
  228. if(is_null($integrated)){
  229. return $this->errorJson('没有找到记录', []);
  230. }else{
  231. return show_json(0,'没有找到记录');
  232. }
  233. }
  234. $coupons_data['data'] = $coupons->get()->toArray();
  235. //添加"是否可领取" & "是否已抢光" & "是否已领取"的标识
  236. foreach ($coupons_data['data'] as $k => $v) {
  237. $coupons_data['data'][$k]['coupon_id'] = $coupons_data['data'][$k]['id'];
  238. if (($v['total'] != self::NO_LIMIT) && ($v['has_many_member_coupon_count'] >= $v['total'])) {
  239. $coupons_data['data'][$k]['api_availability'] = self::EXHAUST;
  240. } elseif ($v['get_max'] > 0 && $v['member_got_count'] >= $v['get_max']) {
  241. $coupons_data['data'][$k]['api_availability'] = self::ALREADY_GOT;
  242. } else {
  243. $coupons_data['data'][$k]['api_availability'] = self::IS_AVAILABLE;
  244. }
  245. //增加属性 - 对于该优惠券,用户可领取的数量
  246. if ($v['get_max'] != self::NO_LIMIT) {
  247. $coupons_data['data'][$k]['api_remaining'] = $v['get_max'] - $v['member_got_count'];
  248. if ($coupons_data['data'][$k]['api_remaining'] < 0) { //考虑到优惠券设置会变更,比如原来允许领取6张,之后修改为3张,那么可领取张数可能会变成负数
  249. $coupons_data['data'][$k]['api_remaining'] = 0;
  250. }
  251. } elseif ($v['get_max'] == self::NO_LIMIT) {
  252. $coupons_data['data'][$k]['api_remaining'] = -1;
  253. }
  254. //添加优惠券使用范围描述
  255. switch ($v['use_type']) {
  256. case Coupon::COUPON_SHOP_USE:
  257. $coupons_data['data'][$k]['api_limit'] = '商城通用';
  258. break;
  259. case Coupon::COUPON_CATEGORY_USE:
  260. $coupons_data['data'][$k]['api_limit'] = '适用于下列分类: ';
  261. $coupons_data['data'][$k]['api_limit'] = implode(',', $v['categorynames']);
  262. break;
  263. case Coupon::COUPON_GOODS_USE:
  264. $coupons_data['data'][$k]['api_limit'] = '适用于下列商品: ';
  265. $coupons_data['data'][$k]['api_limit'] = implode(',', $v['goods_names']);
  266. break;
  267. case 8:
  268. $coupons_data['data'][$k]['api_limit'] = '适用于下列商品: ';
  269. $coupons_data['data'][$k]['api_limit'] = implode(',', $v['goods_names']);
  270. break;
  271. case 9:
  272. $coupons_data['data'][$k]['api_limit'] = '适用范围: ';
  273. $use_condition = unserialize($v['use_conditions']);
  274. if (empty($use_condition)) {
  275. $coupons_data['data'][$k]['api_limit'] .= '无适用范围';
  276. }
  277. if (app('plugins')->isEnabled('store-cashier')) {
  278. if ($use_condition['is_all_store'] == 1) {
  279. $coupons_data['data'][$k]['api_limit'] .= "全部门店";
  280. } else {
  281. $coupons_data['data'][$k]['api_limit'] .= '门店:'.implode(',', Store::uniacid()->whereIn('id', $use_condition['store_ids'])->pluck('store_name')->all());
  282. }
  283. }
  284. if ($use_condition['is_all_good'] == 1) {
  285. $coupons_data['data'][$k]['api_limit'] .= "平台自营商品";
  286. } else {
  287. $coupons_data['data'][$k]['api_limit'] .= '商品:'.implode(',', Goods::uniacid()->whereIn('id', $use_condition['good_ids'])->pluck('title')->all());
  288. }
  289. break;
  290. }
  291. }
  292. if(is_null($integrated)){
  293. return $this->successJson('ok', $coupons_data);
  294. }else{
  295. return show_json(1,$coupons_data);
  296. }
  297. }
  298. //添加"是否可领取" & "是否已抢光" & "是否已领取"的标识
  299. public static function getCouponData($coupons, $memberLevel)
  300. {
  301. foreach ($coupons['data'] as $k => $v) {
  302. if (($v['total'] != self::NO_LIMIT) && ($v['has_many_member_coupon_count'] >= $v['total'])) {
  303. $coupons['data'][$k]['api_availability'] = self::EXHAUST;
  304. } elseif ($v['get_max'] > 0 && $v['member_got_count'] >= $v['get_max']) {
  305. $coupons['data'][$k]['api_availability'] = self::ALREADY_GOT;
  306. } else {
  307. $coupons['data'][$k]['api_availability'] = self::IS_AVAILABLE;
  308. }
  309. //增加属性 - 对于该优惠券,用户可领取的数量
  310. if ($v['get_max'] != self::NO_LIMIT) {
  311. $coupons['data'][$k]['api_remaining'] = $v['get_max'] - $v['member_got_count'];
  312. if ($coupons['data'][$k]['api_remaining'] < 0) { //考虑到优惠券设置会变更,比如原来允许领取6张,之后修改为3张,那么可领取张数可能会变成负数
  313. $coupons['data'][$k]['api_remaining'] = 0;
  314. }
  315. } elseif ($v['get_max'] == self::NO_LIMIT) {
  316. $coupons['data'][$k]['api_remaining'] = -1;
  317. }
  318. //添加优惠券使用范围描述
  319. switch ($v['use_type']) {
  320. case Coupon::COUPON_SHOP_USE:
  321. $coupons['data'][$k]['api_limit'] = '商城通用';
  322. break;
  323. case Coupon::COUPON_CATEGORY_USE:
  324. $coupons['data'][$k]['api_limit'] = '适用于下列分类: ';
  325. $coupons['data'][$k]['api_limit'] = implode(',', $v['categorynames']);
  326. break;
  327. case Coupon::COUPON_GOODS_USE:
  328. $coupons['data'][$k]['api_limit'] = '适用于下列商品: ';
  329. $coupons['data'][$k]['api_limit'] = implode(',', $v['goods_names']);
  330. break;
  331. case 8:
  332. $coupons['data'][$k]['api_limit'] = '适用于下列商品: ';
  333. $coupons['data'][$k]['api_limit'] = implode(',', $v['goods_names']);
  334. break;
  335. case 9:
  336. $coupons_data['data'][$k]['api_limit'] = '适用范围: ';
  337. $use_condition = unserialize($v['use_conditions']);
  338. if (empty($use_condition)) {
  339. $coupons_data['data'][$k]['api_limit'] .= '无适用范围';
  340. }
  341. if (app('plugins')->isEnabled('store-cashier')) {
  342. if ($use_condition['is_all_store'] == 1) {
  343. $coupons_data['data'][$k]['api_limit'] .= "全部门店";
  344. } else {
  345. $coupons_data['data'][$k]['api_limit'] .= '门店:'.implode(',', Store::uniacid()->whereIn('id', $use_condition['store_ids'])->pluck('store_name')->all());
  346. }
  347. }
  348. if ($use_condition['is_all_good'] == 1) {
  349. $coupons_data['data'][$k]['api_limit'] .= "平台自营商品";
  350. } else {
  351. $coupons_data['data'][$k]['api_limit'] .= '商品:'.implode(',', Goods::uniacid()->whereIn('id', $use_condition['good_ids'])->pluck('title')->all());
  352. }
  353. break;
  354. }
  355. }
  356. return $coupons;
  357. }
  358. //获取用户所拥有的不同状态的优惠券 - 待使用(NOT_USED) & 已过期(OVERDUE) & 已使用(IS_USED)
  359. public function couponsOfMemberByStatus()
  360. {
  361. $status = \YunShop::request()->get('status_request');
  362. $uid = \YunShop::app()->getMemberId();
  363. $now = strtotime('now');
  364. switch ($status) {
  365. case self::NOT_USED:
  366. $coupons = self::getAvailableCoupons($uid, $now);
  367. break;
  368. case self::OVERDUE:
  369. $coupons = self::getOverdueCoupons($uid, $now);
  370. break;
  371. case self::IS_USED:
  372. $coupons = self::getUsedCoupons($uid);
  373. break;
  374. }
  375. if (empty($coupons)) {
  376. return $this->errorJson('没有找到记录', []);
  377. } else {
  378. return $this->successJson('ok', $coupons);
  379. }
  380. }
  381. //用户所拥有的可使用的优惠券
  382. public static function getAvailableCoupons($uid, $time)
  383. {
  384. $coupons = MemberCoupon::getCouponsOfMember($uid,\YunShop::request()->coupon_type?:'')
  385. ->where('used', '=', 0)
  386. ->where('is_member_deleted', 0)
  387. ->where('is_expired', 0)
  388. ->get()->toArray();
  389. $availableCoupons = array();
  390. foreach ($coupons as $k => $v) {
  391. if(app('plugins')->isEnabled('hotel')){
  392. if($v['belongs_to_coupon']['use_type'] == Coupon::COUPON_ONE_HOTEL_USE){
  393. $find = CouponHotel::where('coupon_id',$v['belongs_to_coupon']['id'])->first();
  394. $coupons[$k]['belongs_to_coupon']['hotel_ids'] = $find->hotel_id;
  395. }elseif ($v['belongs_to_coupon']['use_type'] == Coupon::COUPON_MORE_HOTEL_USE){
  396. $finds = CouponHotel::where('coupon_id',$v['belongs_to_coupon']['id'])->get();
  397. $findsArr = [];
  398. foreach ($finds as $find_v){
  399. $findsArr[] = $find_v->hotel_id;
  400. }
  401. $coupons[$k]['belongs_to_coupon']['hotel_ids'] = $findsArr;
  402. }
  403. }
  404. if($v['time_end'] != '不限时间') {
  405. $coupons[$k]['time_end'] = $v['timestamp_end'];
  406. }
  407. $usageLimit = array('api_limit' => self::usageLimitDescription($v['belongs_to_coupon'])); //增加属性 - 优惠券的适用范围
  408. $availableCoupons[] = array_merge($coupons[$k], $usageLimit);
  409. }
  410. $coupon_set = \Setting::getByGroup('coupon');
  411. if($coupon_set['coupon_show'] == 1) {
  412. return self::handleAvailableCoupons($availableCoupons);//多张折叠
  413. }
  414. return $availableCoupons;
  415. }
  416. public static function handleAvailableCoupons($coupons)
  417. {
  418. $newArr = [];
  419. $arr = [];
  420. foreach ($coupons as $v)
  421. {
  422. if($v['belongs_to_coupon']['time_limit'] == Coupon::COUPON_DATE_TIME_RANGE)
  423. {
  424. if($newArr[$v['belongs_to_coupon']['id']])
  425. {
  426. $newArr[$v['belongs_to_coupon']['id']] += 1;
  427. }else{
  428. $newArr[$v['belongs_to_coupon']['id']] = 1;
  429. }
  430. }
  431. }
  432. $combineArr = [];
  433. $markArr = [];
  434. foreach ($coupons as $v)
  435. {
  436. if($v['belongs_to_coupon']['time_limit'] == Coupon::COUPON_DATE_TIME_RANGE)
  437. {
  438. if(!in_array($v['belongs_to_coupon']['id'],$markArr))
  439. {
  440. $combineArr[] = array_merge($v, ['combine'=>true,'num'=>$newArr[$v['belongs_to_coupon']['id']]]);
  441. }
  442. $markArr[] = $v['belongs_to_coupon']['id'];
  443. }else{
  444. $combineArr[] = array_merge($v, ['combine'=>false,'num'=>1]);
  445. }
  446. }
  447. return $combineArr;
  448. }
  449. //用户所拥有的已过期的优惠券
  450. public static function getOverdueCoupons($uid, $time)
  451. {
  452. $coupons = MemberCoupon::getCouponsOfMember($uid,\YunShop::request()->coupon_type?:'')->where('used', '=', 0)->where('is_member_deleted', 0)->where('is_expired', 1)->get()->toArray();
  453. $overdueCoupons = array();
  454. //获取已经过期的优惠券
  455. foreach ($coupons as $k => $v) {
  456. // $coupons[$k]['belongs_to_coupon']['deduct'] = intval($coupons[$k]['belongs_to_coupon']['deduct']);
  457. // $coupons[$k]['belongs_to_coupon']['discount'] = intval($coupons[$k]['belongs_to_coupon']['discount']);
  458. if(app('plugins')->isEnabled('hotel')){
  459. if($v['belongs_to_coupon']['use_type'] == Coupon::COUPON_ONE_HOTEL_USE){
  460. $find = CouponHotel::where('coupon_id',$v['belongs_to_coupon']['id'])->first();
  461. $coupons[$k]['belongs_to_coupon']['hotel_ids'] = $find->hotel_id;
  462. }elseif ($v['belongs_to_coupon']['use_type'] == Coupon::COUPON_MORE_HOTEL_USE){
  463. $finds = CouponHotel::where('coupon_id',$v['belongs_to_coupon']['id'])->get();
  464. $findsArr = [];
  465. foreach ($finds as $find_v){
  466. $findsArr[] = $find_v->hotel_id;
  467. }
  468. $coupons[$k]['belongs_to_coupon']['hotel_ids'] = $findsArr;
  469. }
  470. }
  471. $usageLimit = array('api_limit' => self::usageLimitDescription($v['belongs_to_coupon']));
  472. $overdueCoupons[] = array_merge($coupons[$k], $usageLimit);
  473. }
  474. return $overdueCoupons;
  475. }
  476. //用户所拥有的已使用的优惠券
  477. public static function getUsedCoupons($uid)
  478. {
  479. $coupons = MemberCoupon::getCouponsOfMember($uid,\YunShop::request()->coupon_type?:'')->where('used', '=', 1)->where('is_member_deleted', 0)->get()->toArray();
  480. $usedCoupons = array();
  481. //增加属性 - 优惠券的适用范围
  482. foreach ($coupons as $k => $v) {
  483. // $coupons[$k]['belongs_to_coupon']['deduct'] = intval($coupons[$k]['belongs_to_coupon']['deduct']);
  484. // $coupons[$k]['belongs_to_coupon']['discount'] = intval($coupons[$k]['belongs_to_coupon']['discount']);
  485. if(app('plugins')->isEnabled('hotel')){
  486. if($v['belongs_to_coupon']['use_type'] == Coupon::COUPON_ONE_HOTEL_USE){
  487. $find = CouponHotel::where('coupon_id',$v['belongs_to_coupon']['id'])->first();
  488. $coupons[$k]['belongs_to_coupon']['hotel_ids'] = $find->hotel_id;
  489. }elseif ($v['belongs_to_coupon']['use_type'] == Coupon::COUPON_MORE_HOTEL_USE){
  490. $finds = CouponHotel::where('coupon_id',$v['belongs_to_coupon']['id'])->get();
  491. $findsArr = [];
  492. foreach ($finds as $find_v){
  493. $findsArr[] = $find_v->hotel_id;
  494. }
  495. $coupons[$k]['belongs_to_coupon']['hotel_ids'] = $findsArr;
  496. }
  497. }
  498. $usageLimit = array('api_limit' => self::usageLimitDescription($v['belongs_to_coupon']));
  499. $usedCoupons[] = array_merge($coupons[$k], $usageLimit);
  500. }
  501. return $usedCoupons;
  502. }
  503. /**
  504. * @param $couponInArrayFormat array
  505. * @return string 优惠券适用范围的描述
  506. */
  507. public static function usageLimitDescription($couponInArrayFormat)
  508. {
  509. switch ($couponInArrayFormat['use_type']) {
  510. case 0:
  511. return ('商城通用');
  512. break;
  513. case 1:
  514. $res = '适用于下列分类: ';
  515. $res .= implode(',', $couponInArrayFormat['categorynames']);
  516. return $res;
  517. break;
  518. case 2:
  519. $res = '适用于下列商品: ';
  520. $res .= implode(',', $couponInArrayFormat['goods_names']);
  521. return $res;
  522. break;
  523. case 3:
  524. $res = '适用于下列供应商: ';
  525. $res .= implode(',', $couponInArrayFormat['suppliernames']);
  526. return $res;
  527. break;
  528. case 4:
  529. case 5:
  530. $res = '适用于下列门店: ';
  531. $res .= implode(',', $couponInArrayFormat['storenames']);
  532. return $res;
  533. break;
  534. case Coupon::COUPON_ONE_HOTEL_USE:
  535. $res = '适用于酒店 :';
  536. if(app('plugins')->isEnabled('hotel')){
  537. $coupon_hotel = CouponHotel::where('coupon_id',$couponInArrayFormat['id'])->with(['hotel' => function ($query){
  538. $query->select('hotel_name');
  539. }])->first();
  540. $res .= $coupon_hotel->hotel->hotel_name;
  541. }
  542. return $res;
  543. break;
  544. case Coupon::COUPON_MORE_HOTEL_USE:
  545. $res = '适用于下列酒店: ';
  546. if(app('plugins')->isEnabled('hotel')){
  547. $hotel_arr = [];
  548. $coupon_hotels = CouponHotel::where('coupon_id',$couponInArrayFormat['id'])->with(['hotel' => function ($query){
  549. $query->select('hotel_name');
  550. }])->get();
  551. foreach ($coupon_hotels as $v){
  552. $hotel_arr[] = $v->hotel->hotel_name;
  553. }
  554. $res .= implode(',', $hotel_arr);
  555. }
  556. return $res;
  557. break;
  558. case 8:
  559. $res = '适用于下列商品: ';
  560. $res .= implode(',', $couponInArrayFormat['goods_names']);
  561. return $res;
  562. break;
  563. case Coupon::COUPON_GOODS_AND_STORE_USE:
  564. $res = '';
  565. $use_condition = unserialize($couponInArrayFormat['use_conditions']);
  566. if (empty($use_condition)) {
  567. return '无适用范围';
  568. }
  569. if (app('plugins')->isEnabled('store-cashier')) {
  570. if ($use_condition['is_all_store'] == 1) {
  571. $res .= "全部门店、";
  572. } else {
  573. $res .= '门店:'.implode(',', Store::uniacid()->whereIn('id', $use_condition['store_ids'])->pluck('store_name')->all()).'、';
  574. }
  575. }
  576. if ($use_condition['is_all_good'] == 1) {
  577. $res .= "平台自营商品";
  578. } else {
  579. $res .= '商品:'.implode(',', Goods::uniacid()->whereIn('id', $use_condition['good_ids'])->pluck('title')->all());
  580. }
  581. return $res;
  582. break;
  583. default:
  584. return ('Enjoy shopping');
  585. }
  586. }
  587. //用户删除其拥有的优惠券
  588. public function delete()
  589. {
  590. $id = \YunShop::request()->id;
  591. if (empty($id)) {
  592. return $this->errorJson('缺少 ID 参数', '');
  593. }
  594. $model = MemberCoupon::find($id);
  595. if (!$model) {
  596. return $this->errorJson('找不到记录', '');
  597. }
  598. $res = $model->update(['is_member_deleted' => 1]);
  599. if ($res) {
  600. return $this->successJson('ok', '');
  601. } else {
  602. return $this->errorJson('删除优惠券失败', '');
  603. }
  604. }
  605. /**
  606. * 在"优惠券中心"点击领取优惠券
  607. * @return \Illuminate\Http\JsonResponse
  608. * @throws AppException
  609. * @throws \app\common\exceptions\MemberNotLoginException
  610. */
  611. public function getCoupon()
  612. {
  613. $this->validate([
  614. 'coupon_id' => 'required|integer'
  615. ]);
  616. $memberId = \YunShop::app()->getMemberId();
  617. $couponId = request('coupon_id');
  618. $total = request('exchange_total') ?: 1;
  619. /**
  620. * @var $couponModel Coupon
  621. */
  622. $couponModel = Coupon::find($couponId);
  623. $memberCoupon = (new PreMemberCoupon);
  624. $memberCoupon->init(Member::current(), $couponModel, $total);
  625. $memberCoupon->generate();
  626. $member = Member::current()->yzMember;
  627. //按前端要求, 需要返回和 couponsForMember() 方法完全一致的数据
  628. $coupon = Coupon::centerCouponsForMember($memberId, $member->level_id, $couponId)->get()->toArray();
  629. foreach ($coupon as &$item) {
  630. $item['has_many_member_coupon_count'] = MemberCoupon::uniacid()->select('uid')->where('coupon_id' ,$item['id'])->distinct()->get()->count();
  631. }
  632. $res = self::getCouponData(['data' => $coupon], $member->level_id);
  633. $res['data'][0]['coupon_id'] = $res['data'][0]['id'];
  634. return $this->successJson('ok', $res['data'][0]);
  635. }
  636. /**
  637. * 获取指定商品的优惠券详情
  638. */
  639. public function getGoodsCouponByCouponId()
  640. {
  641. $coupon_id = $id = \YunShop::request()->coupon_id;
  642. $coupon = \app\common\models\Coupon::getCouponById($coupon_id);
  643. if ($coupon['use_type'] == !2 && !\request()->bind_coupon_sn) {
  644. throw new AppException('优惠券类型错误');
  645. }
  646. //优惠券标识
  647. if (($coupon['total'] != self::NO_LIMIT) && ($coupon['has_many_member_coupon_count'] >= $coupon['total'])) {
  648. $coupon['api_availability'] = self::EXHAUST;
  649. } elseif ($coupon['member_got_count'] > 0) {
  650. $coupon['api_availability'] = self::ALREADY_GOT;
  651. } else {
  652. $coupon['api_availability'] = self::IS_AVAILABLE;
  653. }
  654. $coupon['goods'] = Goods::getGoodsByIds($coupon['goods_ids']);
  655. foreach ($coupon['goods'] as &$value) {
  656. $value['thumb'] = replace_yunshop(yz_tomedia($value['thumb']));
  657. if($coupon['coupon_method'] == 1){
  658. $value['deduct_price'] = $value['price'] - $coupon['deduct'];
  659. $value['deduct_price'] = $value['deduct_price']>=0?$value['deduct_price']:0;
  660. }elseif($coupon['coupon_method'] == 2){
  661. $value['deduct_price'] = $value['price'] * $coupon['discount']/10;
  662. }
  663. }
  664. $shop = \Setting::get('shop.shop');
  665. $coupon['icon'] = replace_yunshop(yz_tomedia($shop['logo'])); //商城logo
  666. $coupon['description'] = htmlspecialchars_decode(\Setting::getByGroup('coupon')['description']); //领券说明
  667. if (!$coupon['description']) {
  668. $coupon['description'] = $coupon->content;
  669. }
  670. if ($coupon['time_limit'] != 1) {
  671. $coupon['time_start'] = date('Y-m-d H:i:s',time());
  672. if ($coupon['time_days'] == 0) {
  673. $times = 86400*36500;
  674. $coupon['time_end'] = date('Y-m-d H:i:s',time()+$times);
  675. } else {
  676. $times = 86400*$coupon['time_days'];
  677. $coupon['time_end'] = date('Y-m-d H:i:s',time()+$times);
  678. }
  679. }
  680. $coupon['bind_coupon_wait_get'] = 0;
  681. if (\request()->bind_coupon_sn && app('plugins')->isEnabled('bind-coupon')) {
  682. $bind_coupon = \Yunshop\BindCoupon\models\BindCouponLog::uniacid()
  683. ->where('coupon_sn', \request()->bind_coupon_sn)->first();
  684. if (!$bind_coupon) {
  685. return $this->errorJson('绑定优惠券不存在');
  686. }
  687. $coupon['bind_coupon_wait_get'] = $bind_coupon->status == 0 ? 1 : -1;
  688. }
  689. return $this->successJson('', $coupon);
  690. }
  691. public function getDetail()
  692. {
  693. $id = \YunShop::request()->record_id;
  694. $record = MemberCoupon::uniacid()->with(['member', 'belongsToCommonCoupon' => function ($query) {
  695. return $query->select(['id', 'name', 'coupon_method', 'deduct', 'discount', 'enough', 'use_type', 'category_ids', 'categorynames',
  696. 'goods_ids', 'goods_names', 'storeids', 'storenames', 'time_limit', 'time_days', 'time_start', 'time_end', 'total',
  697. 'money', 'credit', 'plugin_id', 'content','is_complex']);
  698. }])->find($id);
  699. if (!$record) {
  700. throw new AppException('无此条记录');
  701. }
  702. $coupon_set = \Setting::getByGroup('coupon');
  703. if ($coupon_set['is_singleton'] == 1) {
  704. $rule = '每个订单仅限使用一张优惠券,不可与其它优惠券叠加使用';
  705. }
  706. if ($coupon_set['is_singleton'] == 0) {
  707. if ($record->belongsToCommonCoupon->is_complex == 0) {
  708. $rule = '每个订单本张优惠券仅限使用一张,若还满足其他优惠券使用条件,可叠加使用';
  709. } else{
  710. $rule = '每个订单本张优惠券可使用多张,若还满足其他优惠券使用条件,可叠加使用';
  711. }
  712. }
  713. $coupons_num = MemberCoupon::uniacid()
  714. ->where(['used'=>0,'is_member_deleted'=>0,'is_expired'=>0,'uid'=>$record->uid,'coupon_id'=>$record->coupon_id])
  715. ->count();
  716. $data = [
  717. 'img_url' => $record->member->avatar_image ?: '',
  718. 'rule' => $rule,
  719. 'coupon' => $record->belongsToCommonCoupon,
  720. 'is_complex' => $record->belongsToCommonCoupon->is_complex,
  721. 'multiple_use' => ['is_open'=>$coupon_set['transfer_num'] == 1?true:false,'nums'=>$coupons_num]
  722. ];
  723. $data["coupon_fee_plugin"] = \app\common\modules\shop\ShopConfig::current()
  724. ->get('couponFee_plugin');
  725. if (app('plugins')->isEnabled('share-coupons')) {
  726. $data['share_coupon'] = \Setting::get('share-coupons.is_open') == 1 ? true : false;
  727. }
  728. if (app('plugins')->isEnabled('write-off-coupons')) {
  729. $data['write_off_coupon'] = \Setting::get('write-off-coupons.is_open') == 1 ? true : false;
  730. }
  731. $data = array_merge($data,[
  732. 'transfer' => Setting::get('coupon.transfer') ? true : false,
  733. 'combine_show' => $coupon_set['coupon_show'] == 1 ? true : false,
  734. ]);
  735. $member_coupon = $record ? $record->toArray() : [];
  736. if ($member_coupon) {
  737. $data['coupon'] = $data['coupon'] ? $data['coupon']->toArray() : [];
  738. if ($data['coupon']) {
  739. $data['coupon']['time_start'] = $member_coupon['time_start'];
  740. $data['coupon']['time_end'] = $member_coupon['time_end'];
  741. }
  742. }
  743. $data['bind_coupon_url'] = '';
  744. if (app('plugins')->isEnabled('bind-coupon') && $data['coupon']['id'] && ($coupons_num > 0)) {
  745. if ($bind_coupon = \Yunshop\BindCoupon\models\BindCoupon::uniacid()
  746. ->where('coupon_id',$data['coupon']['id'])
  747. ->where('status', 0)
  748. ->whereHas('hasOneCoupon', function ($query) {
  749. $query->where('time_limit', 0)->orWhere('time_end', '>', time());
  750. })->first()){
  751. $data['bind_coupon_url'] = \Yunshop\BindCoupon\services\SettingService::shareUrl($bind_coupon->id, \YunShop::app()->getMemberId());
  752. }
  753. }
  754. return $this->successJson('ok', $data);
  755. }
  756. private function getSearchArray($arr)
  757. {
  758. if (!app('plugins')->isEnabled('store-cashier')) {
  759. unset($arr[Coupon::TYPE_STORE]);
  760. }
  761. if (!app('plugins')->isEnabled('hotel')) {
  762. unset($arr[Coupon::TYPE_HOTEL]);
  763. }
  764. return $arr;
  765. }
  766. /**
  767. * 获取优惠卷的指定的商品和门店
  768. * @param CouponConditionService $conditionService
  769. * @return array
  770. * @throws AppException
  771. */
  772. public function getStoreAndGoods (CouponConditionService $conditionService)
  773. {
  774. $this->validate([
  775. 'coupon_id' => 'required|integer|exists:app\frontend\modules\coupon\models\Coupon,id',
  776. ]);
  777. $coupon_id = request()->coupon_id;
  778. $coupon = Coupon::select(['storeids', 'use_type', 'use_conditions', 'plugin_id'])->find($coupon_id);
  779. $condition_list = $conditionService->getCondition($coupon);
  780. return $this->successJson('成功', $condition_list);
  781. }
  782. }