PayTemplateController.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. <?php
  2. namespace Modules\Channel\Http\Controllers;
  3. use Carbon\Carbon;
  4. use Catch\Base\CatchController;
  5. use Illuminate\Foundation\Validation\ValidatesRequests;
  6. use Illuminate\Http\Request;
  7. use Illuminate\Support\Facades\DB;
  8. use Modules\Channel\Exceptions\ChannelBusinessException;
  9. use Modules\Channel\Models\PayProduct;
  10. use Modules\Channel\Models\PayTemplate;
  11. use Modules\Channel\Models\PayTemplateItem;
  12. use Modules\Channel\Services\User\UserService;
  13. use Modules\Common\Errors\Errors;
  14. class PayTemplateController extends CatchController
  15. {
  16. use ValidatesRequests;
  17. public function __construct(protected readonly PayTemplate $payTemplate,protected readonly PayTemplateItem $payTemplateItem,protected readonly PayProduct $payProduct)
  18. {
  19. }
  20. private $sequence_map = [
  21. '','位置一','位置二','位置三','位置四','位置五','位置六','位置七','位置八'
  22. ];
  23. /**
  24. * 充值模板列表
  25. *
  26. * @param Request $request
  27. * @return void
  28. */
  29. public function index(Request $request)
  30. {
  31. $uid = $this->getLoginUser()->id;
  32. if(UserService::userHasRole($uid,'administrator')){
  33. $uid = 0;
  34. }
  35. if($uid) {
  36. $this->initPayTemplate($uid);
  37. }
  38. $name = $request->get('name');
  39. // 1-首充模板,2-非首充模板
  40. $type = $request->input('type');
  41. $where = [['uid','=',$uid,], ['type', '=', $type,]];
  42. if($name){
  43. $where[] = ['name','like','%'.$name.'%'];
  44. }
  45. $result = $this->payTemplate->orderBy('id','desc')->where($where)->paginate($request->input('limit', 20));
  46. foreach ($result as $item) {
  47. $item->status_str = $item->status ? '默认模板': '非默认模板';
  48. $item->type_str = 1 == $item->type ? '首充模板' : '非首充模板';
  49. }
  50. return $result;
  51. }
  52. /**
  53. * 如果优化是没有设置充值模板,那么就是用官方模板进行初始化
  54. * @param $uid
  55. */
  56. private function initPayTemplate($uid) {
  57. if(!$this->payTemplate->where('uid', $uid)->count()) {
  58. $systemPayTemplates = $this->payTemplate->where('uid', 0)->get();
  59. $now = date('Y-m-d H:i:s');
  60. foreach ($systemPayTemplates as $systemPayTemplate) {
  61. $payTemplate = $this->payTemplate->create([
  62. 'uid' => $uid,
  63. 'name' => $systemPayTemplate->name,
  64. 'status' => $systemPayTemplate->status,
  65. 'type' => $systemPayTemplate->type,
  66. ]);
  67. $payTemplateItems = $this->payTemplateItem->where([
  68. 'pay_template_id' => $systemPayTemplate->id, 'status' => 1,
  69. ])->get();
  70. $payTemplateItemDatas = [];
  71. foreach ($payTemplateItems as $item) {
  72. $payTemplateItemDatas[] = [
  73. 'pay_template_id' => $payTemplate->id,
  74. 'pay_product_id' => $item->pay_product_id,
  75. 'is_default' => $item->is_default,
  76. 'status' => $item->status,
  77. 'sequence' => $item->sequence,
  78. 'created_at' => $now,
  79. 'updated_at' => $now,
  80. ];
  81. }
  82. $this->payTemplateItem->insert($payTemplateItemDatas);
  83. }
  84. }
  85. }
  86. /**
  87. * 添加模板
  88. *
  89. * @param Request $request
  90. * @return void
  91. */
  92. public function store(Request $request)
  93. {
  94. $this->validate($request, [
  95. 'name' => 'required',
  96. 'options' => 'required',
  97. 'status' => 'required|in:0,1',
  98. 'type' => 'required|in:1,2'
  99. ]);
  100. $uid = $this->getLoginUser()->id;
  101. $name = $request->post('name');
  102. // 0-非默认模板,1-默认模板
  103. $status = $request->post('status');
  104. $options = $request->post('options');
  105. // 1-首充模板,2-非首充模板
  106. $type = $request->input('type');
  107. if(UserService::userHasRole($uid,'administrator')){
  108. $uid = 0;
  109. }
  110. $option_list = json_decode($options,1);
  111. $data = [];
  112. $default_optioin = 0;
  113. $option_cache = [];
  114. $type_list = collect($this->optionTypeList())->pluck('value');
  115. foreach($option_list as $option){
  116. if(!is_numeric($option['price']) || !is_numeric($option['given'])){
  117. ChannelBusinessException::throwError(Errors::PARAM_ERROR);
  118. }
  119. if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
  120. if($option['given'] > 3*$option['price']*100){
  121. ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_GIVEN_TOO_MUCH);
  122. break;
  123. }
  124. }
  125. if(!$type_list->contains($option['type'])){
  126. ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_OPTIONS_ERROR);
  127. }
  128. if(in_array($option['price'],$option_cache)){
  129. ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_CONFLICT);
  130. }
  131. $option_cache[] = $option['price'];
  132. if(!$default_optioin && $option['is_default']){
  133. $default_optioin = $option['price'];
  134. }
  135. }
  136. $default_optioin = $default_optioin>0?$default_optioin:$option_list[0]['price'];
  137. if($status == 1 && 0 == $uid){
  138. $this->payTemplate->where([
  139. 'uid' => $uid, 'type' => $type
  140. ])->update(['status'=>0]);
  141. }
  142. $pay_template_info = $this->payTemplate->create(['name'=>$name,'uid'=>$uid,
  143. 'type' => $type, 'status' => $status]);
  144. foreach($option_list as $option){
  145. $type = $option['type'];
  146. if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
  147. $type = 'COIN';
  148. }
  149. $product_info = $this->getPayProduct($option['price'], $type,$option['given']);
  150. $data[] = [
  151. 'pay_template_id'=>$pay_template_info->id,'pay_product_id'=>$product_info->id,
  152. 'is_first_pay'=>$option['type'] == 'FIRST_COIN' ?1:0,'is_default'=>$option['price'] == $default_optioin ?1:0,
  153. 'status'=>1,'sequence'=>$option['sequence'],'created_at'=>Carbon::now(),'updated_at'=>Carbon::now()
  154. ];
  155. }
  156. $this->payTemplateItem->insert($data);
  157. return [];
  158. }
  159. /**
  160. * 模板详情
  161. *
  162. * @param int $id
  163. * @return void
  164. */
  165. public function show($id)
  166. {
  167. $uid = $this->getLoginUser()->id;
  168. if(UserService::userHasRole($uid,'administrator')){
  169. $uid = 0;
  170. }
  171. $exists = $this->payTemplate->where('uid',$uid)->where('id',$id)->first();
  172. if(!$exists){
  173. ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_NOT_EXISTS_ERROR);
  174. }
  175. $pay_template_item = $this->payTemplateItem->join('pay_products','pay_products.id','=','pay_template_items.pay_product_id')
  176. ->where('pay_template_id',$id)
  177. ->select('pay_products.price','pay_products.type','pay_products.given','pay_template_id','pay_product_id','is_first_pay','is_default','sequence','pay_template_items.id as pay_template_item_id')
  178. ->where('pay_template_items.status',1)
  179. ->orderBy('pay_template_items.sequence')
  180. ->get();
  181. $type_list = collect($this->optionTypeList());
  182. foreach($pay_template_item as $item){
  183. if($item->type == 'COIN' && $item->is_first_pay == 1){
  184. $item->type == 'FIRST_COIN';
  185. }
  186. $item->type_name = $type_list->where('value',$item->type)->first()['name'];
  187. if($item->type == 'COIN' || $item->type == 'FIRST_COIN'){
  188. $item->charge_coin = (int)($item->price*100);
  189. }else{
  190. $item->charge_coin = $item->type_name;
  191. }
  192. $item->sequence_text = $this->sequence_map[$item->sequence];
  193. $item->default_text = $item->is_default? '默认项':"非默认项";
  194. }
  195. return [
  196. 'template_info'=>$exists,
  197. 'template_item_list'=>$pay_template_item
  198. ];
  199. }
  200. /**
  201. * 更新模板
  202. *
  203. * @param [type] $id
  204. * @param Request $request
  205. * @return void
  206. */
  207. public function update($id, Request $request)
  208. {
  209. $name = $request->post('name');
  210. $status = $request->post('status',-1);
  211. $options = $request->post('options');
  212. // 1-首充模板,2-非首充模板
  213. $type = $request->input('type');
  214. $uid = $this->getLoginUser()->id;
  215. if(UserService::userHasRole($uid,'administrator')){
  216. $uid = 0;
  217. }
  218. $exists = $this->payTemplate->where('uid',$uid)->where('id',$id)->first();
  219. if(!$exists){
  220. ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_NOT_EXISTS_ERROR);
  221. }
  222. $template_info_update = false;
  223. if($name){
  224. $template_info_update = true;
  225. $exists->name = $name;
  226. }
  227. if($status != -1 && in_array($status,[1,0])){
  228. $template_info_update = true;
  229. $exists->status = $status;
  230. }
  231. if($status == 1){
  232. $this->payTemplate->where('uid',$uid)->where('type', $type)->update(['status'=>0]);
  233. $this->payTemplate->where('id',$id)->update(['status'=>1]);
  234. }
  235. if($template_info_update){
  236. $exists->save();
  237. }
  238. if($options){
  239. $option_list = json_decode($options,1);
  240. $default_optioin = 0;
  241. $option_cache = [];
  242. $type_list = collect($this->optionTypeList())->pluck('value');
  243. foreach($option_list as $option){
  244. if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
  245. if($option['given'] > 3*$option['price']*100){
  246. ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_GIVEN_TOO_MUCH);
  247. break;
  248. }
  249. }
  250. if(!$type_list->contains($option['type'])){
  251. ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_OPTIONS_ERROR);
  252. }
  253. if(in_array($option['price'],$option_cache)){
  254. ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_CONFLICT);
  255. }
  256. $option_cache[] = $option['price'];
  257. if(!$default_optioin && $option['is_default']){
  258. $default_optioin = $option['price'];
  259. }
  260. }
  261. $this->payTemplateItem->where('pay_template_id',$id)->update(['status'=>0]);
  262. $default_optioin = $default_optioin>0?$default_optioin:$option_list[0]['price'];
  263. foreach($option_list as $option){
  264. $type = $option['type'];
  265. if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
  266. $type = 'COIN';
  267. }
  268. $product_info = $this->getPayProduct($option['price'], $type,$option['given']);
  269. $pay_template_item = $this->payTemplateItem->where('pay_template_id',$id)->where('pay_product_id',$product_info->id)->first();
  270. if($pay_template_item){
  271. $pay_template_item->status = 1;
  272. $pay_template_item->sequence = $option['sequence'];
  273. $pay_template_item->is_first_pay = $option['type'] == 'FIRST_COIN' ?1:0;
  274. $pay_template_item->is_default = $option['price'] == $default_optioin ?1:0;
  275. $pay_template_item->save();
  276. }else{
  277. $data = [
  278. 'pay_template_id'=>$id,'pay_product_id'=>$product_info->id,
  279. 'is_first_pay'=>$option['type'] == 'FIRST_COIN' ?1:0,'is_default'=>$option['price'] == $default_optioin ?1:0,
  280. 'status'=>1,'sequence'=>$option['sequence'],'created_at'=>Carbon::now(),'updated_at'=>Carbon::now()
  281. ];
  282. $this->payTemplateItem->insert($data);
  283. }
  284. }
  285. }
  286. return [];
  287. }
  288. /**
  289. * 编辑单条选项
  290. *
  291. * @param [type] $id
  292. * @param Request $request
  293. * @return void
  294. */
  295. public function updatePayTemplateItem($id,Request $request){
  296. $info = $this->payTemplateItem->find($id);
  297. $price = $request->post('price');
  298. $type = $request->post('type');
  299. if(empty($price) || empty($type)){
  300. ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
  301. }
  302. $given = $request->post('given',0);
  303. if($given > 3*$price*100){
  304. ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_GIVEN_TOO_MUCH);
  305. }
  306. $sequence = $request->post('sequence',0);
  307. $is_default = $request->post('is_default',0);
  308. $is_first_pay = 0;
  309. if($type == 'FIRST_COIN'){
  310. $type = 'COIN';
  311. $is_first_pay = 1;
  312. }
  313. $product_info = $this->getPayProduct($price,$type,$given);
  314. if($info->pay_product_id == $product_info->id){
  315. $info->is_first_pay = $is_first_pay;
  316. $info->is_default = $is_default;
  317. $info->save();
  318. }else{
  319. $info->status = 0;
  320. $info->save();
  321. $data = [
  322. 'pay_template_id'=>$info->pay_template_id,'pay_product_id'=>$product_info->id,
  323. 'is_first_pay'=>$is_first_pay,'is_default'=>$is_default,
  324. 'status'=>1,'sequence'=>$sequence,'created_at'=>Carbon::now(),'updated_at'=>Carbon::now()
  325. ];
  326. $this->payTemplateItem->insert($data);
  327. }
  328. return [];
  329. }
  330. /**
  331. * 删除单条选项
  332. *
  333. * @param [type] $id
  334. * @return void
  335. */
  336. public function deleteOneItem($id){
  337. $info = $this->payTemplateItem->find($id);
  338. $info->status = 0;
  339. $info->save();
  340. return [];
  341. }
  342. /**
  343. * 更新模板状态
  344. *
  345. * @param int $id
  346. * @param Request $request
  347. * @return void
  348. */
  349. public function updateStatus($id,Request $request){
  350. $uid = $this->getLoginUser()->id;
  351. if(UserService::userHasRole($uid,'administrator')){
  352. $uid = 0;
  353. }
  354. $exists = $this->payTemplate->where('uid',$uid)->where('id',$id)->first();
  355. $status = $request->post('status');
  356. if(!in_array($status,[1,0])){
  357. ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
  358. }
  359. if(!$exists){
  360. ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_NOT_EXISTS_ERROR);
  361. }
  362. if($status == 1){
  363. $this->payTemplate->where('uid',$uid)->update(['status'=>0]);
  364. }
  365. $exists->status = $status;
  366. $exists->save();
  367. return [];
  368. }
  369. private function getPayProduct($price,$type,$given){
  370. $where = [
  371. ['price','=',$price],
  372. ['type','=',$type],
  373. ['given','=',$given],
  374. ];
  375. $product_info = $this->payProduct->where($where)->first();
  376. if($product_info){
  377. return $product_info ;
  378. }
  379. return $this->payProduct->create(compact('price','type','given'));
  380. }
  381. public function optionTypeList(){
  382. return [
  383. ['name'=>'普通充值','value'=>'COIN'],
  384. ['name'=>'包月','value'=>'MONTH'],
  385. ['name'=>'包季','value'=>'QUARTER'],
  386. ['name'=>'包年','value'=>'YEAR']
  387. ];
  388. }
  389. public function optionTypeListOutPut(){
  390. return collect($this->optionTypeList())->map(function($item){
  391. return [
  392. 'type'=>$item['value'],'type_name'=>$item['name']
  393. ];
  394. })->all();
  395. }
  396. public function optionSequence(){
  397. return [
  398. ['sequence_text'=>'位置一','sequence'=>1],
  399. ['sequence_text'=>'位置二','sequence'=>2],
  400. ['sequence_text'=>'位置三','sequence'=>3],
  401. ['sequence_text'=>'位置四','sequence'=>4],
  402. ['sequence_text'=>'位置五','sequence'=>5],
  403. ['sequence_text'=>'位置六','sequence'=>6]
  404. ];
  405. }
  406. }