TradeService.php 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2017~2021 LARAVEL研发中心
  6. // +----------------------------------------------------------------------
  7. // | 官方网站: http://www.laravel.cn
  8. // +----------------------------------------------------------------------
  9. // | Author: laravel开发员 <laravel.qq.com>
  10. // +----------------------------------------------------------------------
  11. namespace App\Services\Common;
  12. use App\Models\AccountModel;
  13. use App\Models\GoodsModel;
  14. use App\Models\MemberModel;
  15. use App\Models\ShopModel;
  16. use App\Models\TradeModel;
  17. use App\Services\BaseService;
  18. use App\Services\ConfigService;
  19. use App\Services\RedisService;
  20. use Illuminate\Support\Facades\DB;
  21. /**
  22. * 交易管理-服务类
  23. * @author laravel开发员
  24. * @since 2020/11/11
  25. * Class TradeService
  26. * @package App\Services\Common
  27. */
  28. class TradeService extends BaseService
  29. {
  30. // 静态对象
  31. protected static $instance = null;
  32. /**
  33. * 构造函数
  34. * @author laravel开发员
  35. * @since 2020/11/11
  36. * TradeService constructor.
  37. */
  38. public function __construct()
  39. {
  40. $this->model = new TradeModel();
  41. }
  42. /**
  43. * 静态入口
  44. * @return static|null
  45. */
  46. public static function make()
  47. {
  48. if (!self::$instance) {
  49. self::$instance = (new static());
  50. }
  51. return self::$instance;
  52. }
  53. /**
  54. * @param $params
  55. * @param int $pageSize
  56. * @return array
  57. */
  58. public function getDataList($params, $pageSize = 15)
  59. {
  60. $where = ['a.mark' => 1];
  61. $status = isset($params['status']) ? $params['status'] : 0;
  62. $userId = isset($params['user_id']) ? $params['user_id'] : 0;
  63. $shopId = isset($params['shop_id']) ? $params['shop_id'] : 0;
  64. $parentId = isset($params['parent_id']) ? $params['parent_id'] : 0;
  65. $isAppeal = isset($params['is_appeal']) ? $params['is_appeal'] : 0;
  66. $sellUid = isset($params['sell_uid']) ? $params['sell_uid'] : 0;
  67. $type = isset($params['type']) ? $params['type'] : 0;
  68. $goodsStatus = isset($params['goods_status']) ? $params['goods_status'] : 0;
  69. if ($shopId > 0) {
  70. $where['a.shop_id'] = $shopId;
  71. }
  72. if ($parentId > 0) {
  73. $where['b.parent_id'] = $parentId;
  74. }
  75. if ($isAppeal > 0) {
  76. $where['a.is_appeal'] = $isAppeal;
  77. }
  78. if ($goodsStatus > 0) {
  79. $where['g.status'] = $goodsStatus;
  80. }
  81. $model = $this->model->from('trade as a')
  82. ->leftJoin('member as b', 'a.user_id', '=', 'b.id')
  83. ->leftJoin('member as c', 'c.id', '=', 'a.sell_uid')
  84. ->leftJoin('goods as g', 'g.id', '=', 'a.goods_id')
  85. ->leftJoin('shop as s', 's.id', '=', 'g.shop_id')
  86. ->where($where)
  87. ->where('a.status', '>', 0)
  88. ->where(function ($query) use ($type, $status, $isAppeal) {
  89. if($type == 1 && $status == 2){
  90. $query->whereIn('a.status',[1,2,3])->orWhere(function($query) {
  91. $query->where(['a.status'=>4])->where('a.is_sell','<=', 1);
  92. });
  93. }else if($status>0 && !$isAppeal){
  94. $query->where(['a.status'=> $status]);
  95. }
  96. })
  97. ->where(function ($query) use ($params) {
  98. $keyword = isset($params['keyword']) ? $params['keyword'] : '';
  99. if ($keyword) {
  100. $query->where('b.nickname', 'like', "%{$keyword}%")->orWhere('b.mobile', 'like', "%{$keyword}%")
  101. ->orWhere('s.name', 'like', "%{$keyword}%")
  102. ->orWhere('s.code', 'like', "%{$keyword}%")
  103. ->orWhere('g.goods_name', 'like', "%{$keyword}%");
  104. }
  105. })
  106. ->where(function ($query) use ($params) {
  107. $time = isset($params['time']) ? $params['time'] : 0;
  108. if ($time) {
  109. $query->where('a.pay_time', '>=', $time)->orWhere('a.create_time', '>=', $time);
  110. }
  111. })
  112. ->where(function ($query) use ($type, $userId, $sellUid, $status) {
  113. if ($type == 1) {
  114. $query->whereIn('a.status',[1,2,3,4]);
  115. if ($status == 0) {
  116. $query->where(['a.user_id' => $userId, 'a.is_out' => 0]);
  117. $query->whereNotIn('a.sell_uid', [$userId]);
  118. } else if ($status == 2) {
  119. $query->where('a.sell_uid', '=', $userId);
  120. $query->whereNotIn('a.user_id', [$userId]);
  121. } else {
  122. $query->where(['a.user_id' => $userId, 'a.is_out' => 0]);
  123. }
  124. } else if($type == 3){
  125. $query->whereIn('a.status',[1,2,3,4]);
  126. } else {
  127. if ($userId) {
  128. $query->where(['a.user_id' => $userId, 'a.is_out' => 0]);
  129. } else if ($sellUid) {
  130. $query->where('a.sell_uid', '=', $sellUid);
  131. }
  132. }
  133. })
  134. ->select(['a.*', 'b.nickname', 'b.mobile as buy_mobile', 's.name as shop_name', 's.code as shop_code', 'c.nickname as sell_nickname', 'c.mobile as sell_mobile', 'g.goods_name', 'g.code', 'g.thumb']);
  135. // 店长排序
  136. if ($type == 1) {
  137. $model = $model->orderBy('a.status', 'asc');
  138. } else if ($type == 3) {
  139. $model = $model->orderBy('a.status', 'asc')->orderBy('a.is_sell', 'asc');
  140. }
  141. $model = $model->orderBy('s.id', 'asc')
  142. ->orderBy('a.create_time', 'desc')
  143. ->orderBy('a.id', 'desc');
  144. // 统计
  145. $totalModdel = clone $model;
  146. $totalModdel = $totalModdel->whereIn('a.status', [2, 3, 4]);
  147. $counts = ['total' => 0, 'service_fee' => 0, 'bonus' => 0, 'fee' => 0];
  148. $total = $totalModdel->sum('a.real_price');
  149. $fee = $totalModdel->sum('a.fee');
  150. $counts['fee'] = intval($fee);
  151. $countModel = clone $model;
  152. $countModel = $countModel->whereIn('a.status', [3, 4]);
  153. $counts['total'] = intval($total);
  154. $bonus = $countModel->sum('a.bonus');
  155. $counts['bonus'] = intval($bonus);
  156. $serviceFee = $countModel->sum('a.service_fee');
  157. $counts['service_fee'] = intval($serviceFee);
  158. $profit = $countModel->sum('a.profit');
  159. $counts['profit'] = intval($profit);
  160. $list = $model->paginate($pageSize > 0 ? $pageSize : 9999999);
  161. $list = $list ? $list->toArray() : [];
  162. if ($list) {
  163. foreach ($list['data'] as &$item) {
  164. $item['create_time'] = $item['create_time'] ? datetime($item['create_time'], 'Y-m-d H:i:s') : '';
  165. $item['pay_time'] = $item['pay_time'] ? datetime($item['pay_time'], 'Y-m-d H:i:s') : '';
  166. $item['confirm_time'] = $item['confirm_time'] ? datetime($item['confirm_time'], 'Y-m-d H:i:s') : '';
  167. $item['thumb'] = isset($item['thumb']) && $item['thumb'] ? get_image_url($item['thumb']) : '';
  168. $item['pay_img'] = isset($item['pay_img']) && $item['pay_img'] ? get_image_url($item['pay_img']) : '';
  169. $item['price'] = intval($item['price']);
  170. $item['real_price'] = intval($item['real_price']);
  171. $item['fee'] = intval($item['fee']);
  172. }
  173. }
  174. return [
  175. 'pageSize' => $pageSize,
  176. 'total' => isset($list['total']) ? $list['total'] : 0,
  177. 'counts' => $counts,
  178. 'list' => isset($list['data']) ? $list['data'] : []
  179. ];
  180. }
  181. /**
  182. * 转商品列表数据
  183. * @param $params
  184. * @param int $pageSize
  185. * @return array
  186. */
  187. public function getSwitchGoods($params, $pageSize = 15)
  188. {
  189. $where = ['a.mark' => 1, 'a.status' => 1, 'a.is_pay' => 2];
  190. $status = isset($params['status']) ? $params['status'] : 0;
  191. if ($status > 0) {
  192. $where['a.status'] = $status;
  193. }
  194. $isTrade = isset($params['is_trade']) ? $params['is_trade'] : 0;
  195. if ($isTrade > 0) {
  196. $where['a.is_trade'] = $isTrade;
  197. }
  198. $shopId = isset($params['shop_id']) ? $params['shop_id'] : 0;
  199. if ($shopId > 0) {
  200. $where['a.shop_id'] = $shopId;
  201. }
  202. $userId = isset($params['user_id']) ? $params['user_id'] : 0;
  203. if ($userId > 0) {
  204. $where['a.user_id'] = $userId;
  205. }
  206. $list = $this->model->from('trade as a')
  207. ->leftJoin('member as b', 'b.id', '=', 'a.sell_uid')
  208. ->leftJoin('shop as c', 'c.id', '=', 'a.shop_id')
  209. ->leftJoin('goods as g', 'g.id', '=', 'a.goods_id')
  210. ->where($where)
  211. ->where(function ($query) use ($params) {
  212. $keyword = isset($params['keyword']) ? $params['keyword'] : '';
  213. if ($keyword) {
  214. $query->where('g.goods_name', 'like', "%{$keyword}%")->orWhere('c.name', 'like', "%{$keyword}%")->orWhere('b.nickname', 'like', "%{$keyword}%")->orWhere('b.mobile', 'like', "%{$keyword}%");
  215. }
  216. $username = isset($params['username']) ? $params['username'] : '';
  217. if ($username) {
  218. $query->orWhere('b.nickname', 'like', "%{$keyword}%")->orWhere('b.mobile', 'like', "%{$keyword}%");
  219. }
  220. })
  221. ->where(function ($query) use ($params) {
  222. $time = isset($params['time']) ? $params['time'] : '';
  223. if ($time) {
  224. $query->where('a.pay_time', '>=', $time)->orWhere('a.create_time', '>=', $time);
  225. }
  226. })
  227. ->select(['a.*', 'b.nickname', 'b.code as user_code', 'b.mobile as mobile', 'c.name as shop_name', 'c.code as shop_code', 'g.goods_name','g.code', 'g.thumb'])
  228. ->orderBy('a.create_time', 'desc')
  229. ->orderBy('a.id', 'desc')
  230. ->paginate($pageSize > 0 ? $pageSize : 9999999);
  231. $list = $list ? $list->toArray() : [];
  232. if ($list) {
  233. foreach ($list['data'] as &$item) {
  234. $item['create_time'] = $item['create_time'] ? datetime($item['create_time'], 'Y-m-d H.i.s') : '';
  235. $item['thumb'] = isset($item['thumb']) && $item['thumb'] ? get_image_url($item['thumb']) : '';
  236. }
  237. }
  238. return [
  239. 'pageSize' => $pageSize,
  240. 'total' => isset($list['total']) ? $list['total'] : 0,
  241. 'list' => isset($list['data']) ? $list['data'] : []
  242. ];
  243. }
  244. /**
  245. * 详情
  246. * @param $id
  247. * @return mixed
  248. */
  249. public function getInfo($id)
  250. {
  251. $info = $this->model->from('trade as a')
  252. ->leftJoin('member as b', 'a.user_id', '=', 'b.id')
  253. ->leftJoin('member as c', 'c.id', '=', 'a.sell_uid')
  254. ->leftJoin('goods as g', 'g.id', '=', 'a.goods_id')
  255. ->where(['a.id' => $id, 'a.mark' => 1])
  256. ->select(['a.*', 'b.nickname', 'b.mobile as buy_mobile', 'c.nickname as sell_nickname', 'c.mobile as sell_mobile', 'g.goods_name', 'g.code', 'g.thumb'])
  257. ->first();
  258. if ($info) {
  259. $info['create_time_text'] = $info['create_time'] ? datetime($info['create_time'], 'Y-m-d H:i:s') : '';
  260. $info['pay_time'] = $info['pay_time'] ? datetime($info['pay_time'], 'Y-m-d H:i:s') : '';
  261. $info['confirm_time'] = $info['confirm_time'] ? datetime($info['confirm_time'], 'Y-m-d H:i:s') : '';
  262. $info['thumb'] = isset($info['thumb']) && $info['thumb'] ? get_image_url($info['thumb']) : '';
  263. $info['pay_img'] = isset($info['pay_img']) && $info['pay_img'] ? get_image_url($info['pay_img']) : '';
  264. $info['price'] = intval($info['price']);
  265. $info['real_price'] = intval($info['real_price']);
  266. $info['fee'] = intval($info['fee']);
  267. $bankInfo = MemberBankService::make()->getBindInfo($info['sell_uid']);
  268. $info['bank_info'] = $bankInfo ? $bankInfo : ['realname' => '', 'bank_name' => '', 'bank_num' => ''];
  269. }
  270. return $info;
  271. }
  272. /**
  273. * 统计
  274. * @param $params
  275. * @return int[]
  276. */
  277. public function getCounts($params)
  278. {
  279. $counts = ['total' => 0, 'service_fee' => 0, 'bonus' => 0, 'fee' => 0];
  280. $where = ['a.mark' => 1];
  281. $status = isset($params['status']) ? $params['status'] : 0;
  282. $userId = isset($params['user_id']) ? $params['user_id'] : 0;
  283. $shopId = isset($params['shop_id']) ? $params['shop_id'] : 0;
  284. $parentId = isset($params['parent_id']) ? $params['parent_id'] : 0;
  285. $isAppeal = isset($params['is_appeal']) ? $params['is_appeal'] : 0;
  286. $sellUid = isset($params['sell_uid']) ? $params['sell_uid'] : 0;
  287. if ($shopId > 0) {
  288. $where['a.shop_id'] = $shopId;
  289. }
  290. if ($parentId > 0) {
  291. $where['b.parent_id'] = $parentId;
  292. }
  293. if ($userId > 0) {
  294. $where['a.user_id'] = $userId;
  295. }
  296. if ($sellUid > 0) {
  297. $where['a.sell_uid'] = $sellUid;
  298. }
  299. if ($isAppeal > 0) {
  300. $where['a.is_appeal'] = $isAppeal;
  301. }
  302. if ($status > 0) {
  303. $where['a.status'] = $status;
  304. }
  305. $counts['total'] = intval($this->model->from('trade as a')
  306. ->leftJoin('member as b', 'a.user_id', '=', 'b.id')
  307. ->where($where)
  308. ->where(function ($query) use ($params) {
  309. $time = isset($params['time']) ? $params['time'] : 0;
  310. if ($time) {
  311. $query->where('a.pay_time', '>=', $time)->orWhere('a.create_time', '>=', $time);
  312. }
  313. })
  314. ->where(function ($query) use ($userId, $sellUid, $status) {
  315. if ($sellUid && $userId) {
  316. $query->where('a.user_id', $userId)->orWhere(function ($query) use ($sellUid) {
  317. $query->where('a.sell_uid', $sellUid)->whereIn('a.status', [1, 2]);
  318. });
  319. } else if ($userId) {
  320. $query->where('a.user_id', '=', $userId);
  321. } else if ($sellUid) {
  322. $query->where('a.sell_uid', '=', $sellUid);
  323. }
  324. })
  325. ->sum('real_price'));
  326. $bonusRate = ConfigService::make()->getConfigByCode('bonus_rate');
  327. $bonusRate = $bonusRate ? $bonusRate : 5;
  328. $counts['bonus'] = intval($counts['total'] * $bonusRate / 100);
  329. $counts['fee'] = intval($this->model->from('trade as a')
  330. ->leftJoin('member as b', 'a.user_id', '=', 'b.id')
  331. ->where($where)
  332. ->where(function ($query) use ($params) {
  333. $time = isset($params['time']) ? $params['time'] : 0;
  334. if ($time) {
  335. $query->where('a.pay_time', '>=', $time)->orWhere('a.create_time', '>=', $time);
  336. }
  337. })
  338. ->where(function ($query) use ($userId, $sellUid, $status) {
  339. if ($sellUid && $userId) {
  340. $query->where('a.user_id', $userId)->orWhere(function ($query) use ($sellUid) {
  341. $query->where('a.sell_uid', $sellUid)->whereIn('a.status', [1, 2]);
  342. });
  343. } else if ($userId) {
  344. $query->where('a.user_id', '=', $userId);
  345. } else if ($sellUid) {
  346. $query->where('a.sell_uid', '=', $sellUid);
  347. }
  348. })
  349. ->sum('fee'));
  350. $serviceRate = ConfigService::make()->getConfigByCode('service_fee_rate');
  351. $serviceRate = $serviceRate ? $serviceRate : 8;
  352. $counts['service_fee'] = intval($counts['total'] * $serviceRate / 100);
  353. return $counts;
  354. }
  355. /**
  356. * 获取用户当天
  357. * @param $userId
  358. * @return array|mixed
  359. */
  360. public function getCountByDay($userId)
  361. {
  362. $cacheKey = "caches:trade:count:{$userId}";
  363. $data = RedisService::get($cacheKey);
  364. if($data){
  365. return $data;
  366. }
  367. $data = $this->model->where(['user_id'=> $userId, 'status'=> 4,'is_sell'=> 2,'mark'=>1])
  368. ->where('create_time','>=',strtotime(date('Y-m-d')))
  369. ->count('id');
  370. if($data){
  371. RedisService::set($cacheKey, $data, rand(3,5));
  372. }
  373. return $data;
  374. }
  375. /**
  376. * 添加或编辑
  377. * @return array
  378. * @since 2020/11/11
  379. * @author laravel开发员
  380. */
  381. public function edit()
  382. {
  383. $data = request()->all();
  384. return parent::edit($data); // TODO: Change the autogenerated stub
  385. }
  386. /**
  387. * 获取用户交易统计
  388. * @param $userId
  389. * @param int $status
  390. * @param int $time
  391. * @return mixed
  392. */
  393. public function getUserTradeTotal($userId, $status = 0, $time = 0)
  394. {
  395. $cacheKey = "caches:trade:userTotal:{$userId}_" . (is_array($status) ? implode('-', $status) : $status) . "_{$time}";
  396. $data = RedisService::get($cacheKey);
  397. if ($data) {
  398. return $data;
  399. }
  400. $where = ['a.user_id' => $userId, 'a.mark' => 1, 'b.status' => 1, 'b.mark' => 1];
  401. $data = $this->model->from('trade as a')
  402. ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
  403. ->where($where)
  404. ->where(function ($query) use ($status, $time) {
  405. $query->whereIn('a.status', is_array($status) ? $status : [$status]);
  406. // 本月
  407. if ($time == 1) {
  408. $query->where('a.pay_time', '>=', strtotime(date('Y-m-01')));
  409. } // 今日
  410. else if ($time == 2) {
  411. $query->where('a.pay_time', '>=', strtotime(date('Y-m-d')));
  412. }
  413. })
  414. ->sum('a.real_price');
  415. RedisService::set($cacheKey, $data, rand(3, 5));
  416. return $data;
  417. }
  418. /**
  419. * 获取用户团队交易统计
  420. * @param $userId
  421. * @param int $status
  422. * @param int $time
  423. * @return mixed
  424. */
  425. public function getTeamTradeTotal($userId, $status = 0, $time = 0)
  426. {
  427. $cacheKey = "caches:trade:teamTotal:{$userId}_" . (is_array($status) ? implode('-', $status) : $status) . "_{$time}";
  428. $data = RedisService::get($cacheKey);
  429. if ($data) {
  430. return $data;
  431. }
  432. $where = ['b.parent_id' => $userId, 'a.mark' => 1, 'b.status' => 1];
  433. $data = $this->model->from('trade as a')
  434. ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
  435. ->where($where)
  436. ->where(function ($query) use ($status, $time) {
  437. $query->whereIn('a.status', is_array($status) ? $status : [$status]);
  438. // 本月
  439. if ($time == 1) {
  440. $query->where('a.pay_time', '>=', strtotime(date('Y-m-01')));
  441. } // 今日
  442. else if ($time == 2) {
  443. $query->where('a.pay_time', '>=', strtotime(date('Y-m-d')));
  444. }
  445. })
  446. ->sum('a.real_price');
  447. RedisService::set($cacheKey, $data, rand(3, 5));
  448. return $data;
  449. }
  450. /**
  451. * 获取店铺交易统计
  452. * @param $userId
  453. * @param int $time
  454. * @return mixed
  455. */
  456. public function getShopTradeTotal($shopId, $type = 'real_price', $time = 2)
  457. {
  458. $cacheKey = "caches:trade:shop_{$type}:{$shopId}_" . (is_array($time) ? implode('-', $time) : $time);
  459. $data = RedisService::get($cacheKey);
  460. if ($data) {
  461. return round($data, 2);
  462. }
  463. $where = ['a.shop_id' => $shopId, 'a.mark' => 1];
  464. $data = $this->model->from('trade as a')
  465. ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
  466. ->where($where)
  467. ->whereIn('a.status', [3, 4])
  468. ->where(function ($query) use ($time) {
  469. // 本月
  470. if ($time == 1) {
  471. $query->where('a.pay_time', '>=', strtotime(date('Y-m-01')));
  472. } // 今日
  473. else if ($time == 2) {
  474. $query->where('a.pay_time', '>=', strtotime(date('Y-m-d')));
  475. }
  476. })
  477. ->sum('a.' . $type);
  478. RedisService::set($cacheKey, $data, rand(3, 5));
  479. return round($data, 2);
  480. }
  481. /**
  482. * 获取店铺佣金统计
  483. * @param $userId
  484. * @param int $time
  485. * @return mixed
  486. */
  487. public function getShopBonusTotal($shopId, $time = 2)
  488. {
  489. $cacheKey = "caches:trade:shop_bonus:{$shopId}_" . (is_array($time) ? implode('-', $time) : $time);
  490. $data = RedisService::get($cacheKey);
  491. if ($data) {
  492. return round($data, 2);
  493. }
  494. $where = ['a.shop_id' => $shopId, 'type' => 2, 'a.coin_type' => 2, 'a.status' => 1, 'a.mark' => 1];
  495. $data = AccountModel::from('account_log as a')
  496. ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
  497. ->where($where)
  498. ->where(function ($query) use ($time) {
  499. // 本月
  500. if ($time == 1) {
  501. $query->where('a.create_time', '>=', strtotime(date('Y-m-01')));
  502. } // 今日
  503. else if ($time == 2) {
  504. $query->where('a.create_time', '>=', strtotime(date('Y-m-d')));
  505. } else if ($time) {
  506. $month = date('Y-m', $time / 1000);
  507. $lastDay = strtotime("{$month}-01 +1 month -1 day");
  508. if ($month) {
  509. $query->where('a.create_time', '>=', $time / 1000);
  510. $query->where('a.create_time', '<', $lastDay + 86400);
  511. }
  512. }
  513. })
  514. ->sum('a.money');
  515. RedisService::set($cacheKey, $data, rand(3, 5));
  516. return round($data, 2);
  517. }
  518. /**
  519. * 获取用户佣金统计
  520. * @param $userId
  521. * @param int $time
  522. * @return mixed
  523. */
  524. public function getTradeBonusTotal($userId, $time = 0)
  525. {
  526. $cacheKey = "caches:trade:bonus:{$userId}_" . (is_array($time) ? implode('-', $time) : $time);
  527. $data = RedisService::get($cacheKey);
  528. if ($data) {
  529. return round($data, 2);
  530. }
  531. $where = ['a.user_id' => $userId, 'type' => 2, 'a.coin_type' => 2, 'a.status' => 1, 'a.mark' => 1];
  532. $data = AccountModel::from('account_log as a')
  533. ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
  534. ->where($where)
  535. ->where(function ($query) use ($time) {
  536. // 本月
  537. if ($time == 1) {
  538. $query->where('a.create_time', '>=', strtotime(date('Y-m-01')));
  539. } // 今日
  540. else if ($time == 2) {
  541. $query->where('a.create_time', '>=', strtotime(date('Y-m-d')));
  542. } else if ($time) {
  543. $month = date('Y-m', $time / 1000);
  544. $lastDay = strtotime("{$month}-01 +1 month -1 day");
  545. if ($month) {
  546. $query->where('a.create_time', '>=', $time / 1000);
  547. $query->where('a.create_time', '<', $lastDay + 86400);
  548. }
  549. }
  550. })
  551. ->sum('a.money');
  552. RedisService::set($cacheKey, $data, rand(3, 5));
  553. return round($data, 2);
  554. }
  555. /**
  556. * 获取用户收益统计
  557. * @param $userId
  558. * @param int $time
  559. * @return mixed
  560. */
  561. public function getTradeProfitTotal($userId, $time = 0)
  562. {
  563. $cacheKey = "caches:trade:profit:{$userId}_" . (is_array($time) ? implode('-', $time) : $time);
  564. $data = RedisService::get($cacheKey);
  565. if ($data) {
  566. return round($data, 2);
  567. }
  568. $where = ['a.user_id' => $userId, 'type' => 2, 'a.coin_type' => 5, 'a.status' => 1, 'a.mark' => 1];
  569. $data = AccountModel::from('account_log as a')
  570. ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
  571. ->where($where)
  572. ->where(function ($query) use ($time) {
  573. // 本月
  574. if ($time == 1) {
  575. $query->where('a.create_time', '>=', strtotime(date('Y-m-01')));
  576. } // 今日
  577. else if ($time == 2) {
  578. $query->where('a.create_time', '>=', strtotime(date('Y-m-d')));
  579. } else if ($time) {
  580. $month = date('Y-m', $time / 1000);
  581. $lastDay = strtotime("{$month}-01 +1 month -1 day");
  582. if ($month) {
  583. $query->where('a.create_time', '>=', $time / 1000);
  584. $query->where('a.create_time', '<', $lastDay + 86400);
  585. }
  586. }
  587. })
  588. ->sum('a.money');
  589. RedisService::set($cacheKey, $data, rand(3, 5));
  590. return round($data, 2);
  591. }
  592. /**
  593. * 获取用户佣金统计
  594. * @param $userId
  595. * @param int $status
  596. * @param int $time
  597. * @return mixed
  598. */
  599. public function getTradeBonusTotal1($userId, $status = 0, $time = 0)
  600. {
  601. $cacheKey = "caches:trade:bonus:{$userId}_" . (is_array($status) ? implode('-', $status) : $status) . "_" . (is_array($time) ? implode('-', $time) : $time);
  602. $data = RedisService::get($cacheKey);
  603. if ($data) {
  604. return round($data, 2);
  605. }
  606. $where = ['b.parent_id' => $userId, 'a.mark' => 1, 'b.status' => 1];
  607. $data = $this->model->from('trade as a')
  608. ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
  609. ->where($where)
  610. ->where(function ($query) use ($status, $time) {
  611. $query->whereIn('a.status', is_array($status) ? $status : [$status]);
  612. // 本月
  613. if ($time == 1) {
  614. $query->where('a.pay_time', '>=', strtotime(date('Y-m-01')));
  615. } // 今日
  616. else if ($time == 2) {
  617. $query->where('a.pay_time', '>=', strtotime(date('Y-m-d')));
  618. } else if (is_array($time)) {
  619. $start = isset($time[0]) ? $time[0] : '';
  620. $end = isset($time[1]) ? $time[1] : '';
  621. if ($end && $end > $start) {
  622. $query->where('a.pay_time', '<=', strtotime($end));
  623. if ($start) {
  624. $query->where('a.pay_time', '>=', strtotime($start));
  625. }
  626. } else if ($start) {
  627. $query->where('a.pay_time', '=', strtotime($start));
  628. }
  629. }
  630. })
  631. ->sum('a.bonus');
  632. RedisService::set($cacheKey, $data, rand(3, 5));
  633. return round($data, 2);
  634. }
  635. /**
  636. * 获取用户收益统计
  637. * @param $userId
  638. * @param int $status
  639. * @param int $time
  640. * @return mixed
  641. */
  642. public function getTradeProfitTotal1($userId, $status = 0, $time = 0)
  643. {
  644. $cacheKey = "caches:trade:profit:{$userId}_" . (is_array($status) ? implode('-', $status) : $status) . "_" . (is_array($time) ? implode('-', $time) : $time);
  645. $data = RedisService::get($cacheKey);
  646. if ($data) {
  647. return round($data, 2);
  648. }
  649. $where = ['a.user_id' => $userId, 'a.mark' => 1, 'b.status' => 1];
  650. $data = $this->model->from('trade as a')
  651. ->leftJoin('member as b', 'b.id', '=', 'a.user_id')
  652. ->where($where)
  653. ->where(function ($query) use ($status, $time) {
  654. $query->whereIn('a.status', is_array($status) ? $status : [$status]);
  655. // 本月
  656. if ($time == 1) {
  657. $query->where('a.pay_time', '>=', strtotime(date('Y-m-01')));
  658. } // 今日
  659. else if ($time == 2) {
  660. $query->where('a.pay_time', '>=', strtotime(date('Y-m-d')));
  661. } else if (is_array($time)) {
  662. $start = isset($time[0]) ? $time[0] : '';
  663. $end = isset($time[1]) ? $time[1] : '';
  664. if ($end && $end > $start) {
  665. $query->where('a.pay_time', '<=', strtotime($end));
  666. if ($start) {
  667. $query->where('a.pay_time', '>=', strtotime($start));
  668. }
  669. } else if ($start) {
  670. $query->where('a.pay_time', '=', strtotime($start));
  671. }
  672. }
  673. })
  674. ->sum('a.profit');
  675. RedisService::set($cacheKey, $data, rand(3, 5));
  676. return round($data, 2);
  677. }
  678. /**
  679. * 抢拍交易订单数
  680. * @param $userId 用户ID
  681. * @param int $status 状态
  682. * @return mixed
  683. */
  684. public function getNewTradeCountByStatus($userId, $shopId = 0, $status = 0)
  685. {
  686. $where = ['user_id' => $userId, 'mark' => 1, 'is_read' => 0, 'is_out' => 0];
  687. if ($shopId) {
  688. $where['shop_id'] = $shopId;
  689. }
  690. $counts = $this->model->where($where)
  691. ->where(function ($query) use ($status) {
  692. $query->whereIn('status', is_array($status) ? $status : [$status]);
  693. })
  694. ->where('create_time', '>=', strtotime(date('Y-m-d')))
  695. ->select(['status', DB::raw('count(*) as count')])
  696. ->groupBy('status')
  697. ->get();
  698. if ($counts) {
  699. $temps = ['status1' => 0, 'status2' => 0, 'status3' => 0];
  700. foreach ($counts as $v) {
  701. $temps['status' . $v['status']] = $v['count'];
  702. }
  703. $counts = $temps;
  704. } else {
  705. $counts = ['status1' => 0, 'status2' => 0, 'status3' => 0];
  706. }
  707. return $counts;
  708. }
  709. /**
  710. * 获取用户抢拍数量
  711. * @param $userId
  712. * @param string $time
  713. * @return array|mixed
  714. */
  715. public function getTradeByDay($userId, $time=''){
  716. $cacheKey = "caches:trade:snapNum:{$userId}";
  717. $data = RedisService::get($cacheKey);
  718. if($data){
  719. return $data;
  720. }
  721. $data = $this->model->where(['user_id'=> $userId,'mark'=>1])
  722. ->whereIn('status',[1,2,3,4])
  723. ->where(function($query) use($time){
  724. if($time){
  725. $query->where('create_time','>=', $time);
  726. }
  727. })
  728. ->count('id');
  729. if($data){
  730. RedisService::set($cacheKey, $data, rand(3,5));
  731. }
  732. return $data;
  733. }
  734. /**
  735. * 抢购
  736. * @param $params
  737. * @param $userId
  738. * @param $shopId
  739. * @return bool
  740. */
  741. public function buy($params, $userId, $shopId)
  742. {
  743. $goodsId = isset($params['id']) ? $params['id'] : 0;
  744. $info = GoodsService::make()->getInfo(['id' => $goodsId, 'status' => 1, 'mark' => 1]);
  745. $goodsUserId = isset($info['user_id']) ? $info['user_id'] : 0;
  746. $isTrade = isset($info['is_trade']) ? $info['is_trade'] : 0;
  747. if (empty($info)) {
  748. $this->error = 2031;
  749. return false;
  750. }
  751. if ($isTrade == 1) {
  752. $this->error = 2032;
  753. return false;
  754. }
  755. // 验证用户是否可以抢拍
  756. $memberInfo = MemberService::make()->getCacheInfo($userId);
  757. $memberIsTrade = isset($memberInfo['is_trade']) ? $memberInfo['is_trade'] : 0;
  758. if ($memberIsTrade != 1) {
  759. $this->error = 2032;
  760. return false;
  761. }
  762. if ($goodsUserId == $userId) {
  763. $this->error = 2036;
  764. return false;
  765. }
  766. $shopInfo = ShopService::make()->getInfo($shopId);
  767. if (empty($shopInfo)) {
  768. $this->error = 2033;
  769. return false;
  770. }
  771. // 营业时间
  772. $curTime = time();
  773. $startTime = isset($shopInfo['start_time']) ? $shopInfo['start_time'] : '';
  774. $endTime = isset($shopInfo['end_time']) ? $shopInfo['end_time'] : '';
  775. // 抢拍数量限制
  776. $snapNum = ConfigService::make()->getConfigByCode('member_snap_num');
  777. $snapNum = $snapNum>0? $snapNum : 5;
  778. // 店长自己抢
  779. if ($shopInfo['user_id'] == $userId) {
  780. $shopownerSnapNum = ConfigService::make()->getConfigByCode('shopowner_snap_num');
  781. $snapNum = $shopownerSnapNum>0? $shopownerSnapNum : 5;
  782. $snapTime = ConfigService::make()->getConfigByCode('snap_time');
  783. $snapTime = $snapTime ? $snapTime : 5;
  784. $curTime = strtotime(date('Y-m-d') . ' ' . $startTime) + 1;
  785. if (time() < strtotime(date('Y-m-d') . ' ' . $startTime) - $snapTime * 60) {
  786. $this->error = 2034;
  787. return false;
  788. } else if (time() > strtotime(date('Y-m-d') . ' ' . $endTime)) {
  789. $this->error = 2035;
  790. return false;
  791. }
  792. } else {
  793. if (time() < strtotime(date('Y-m-d') . ' ' . $startTime)) {
  794. $this->error = 2034;
  795. return false;
  796. } else if (time() > strtotime(date('Y-m-d') . ' ' . $endTime)) {
  797. $this->error = 2035;
  798. return false;
  799. }
  800. }
  801. // 抢拍数量验证
  802. $curSnapNum = TradeService::make()->getTradeByDay($userId, strtotime(date('Y-m-d')));
  803. if($curSnapNum>=$snapNum){
  804. $this->error = lang(2096,['num'=> $snapNum]);
  805. return false;
  806. }
  807. // 验证收款账号
  808. if (!MemberBankService::make()->getBindInfo($userId)) {
  809. $this->error = 2037;
  810. return false;
  811. }
  812. $feeRate = ConfigService::make()->getConfigByCode('sell_fee_rate');
  813. $feeRate = $feeRate ? $feeRate : '2.5';
  814. $realPrice = intval($info['price'] - $info['sell_price'] + $info['source_price']);
  815. $fee = round($realPrice * $feeRate / 100, 0);
  816. $lockCacheKey = "caches:trade:lock:{$goodsId}";
  817. if (RedisService::get($lockCacheKey)) {
  818. $this->error = 2032;
  819. return false;
  820. }
  821. RedisService::set($lockCacheKey, $info, rand(5, 10));
  822. $data = [
  823. 'order_sn' => get_order_num('T'),
  824. 'goods_id' => $goodsId,
  825. 'user_id' => $userId,
  826. 'shop_id' => $shopId,
  827. 'sell_uid' => $info['user_id'],
  828. 'num' => 1,
  829. 'price' => $info['price'],
  830. 'source_price' => $info['source_price'],
  831. 'sell_price' => $info['sell_price'],
  832. 'real_price' => $realPrice,
  833. 'new_real_price' => $realPrice,
  834. 'fee' => $fee,
  835. 'new_price' => $info['price'],
  836. 'remark' => '抢拍交易',
  837. 'create_time' => $curTime,
  838. 'update_time' => $curTime,
  839. 'status' => 1
  840. ];
  841. DB::beginTransaction();
  842. if (TradeModel::where(['goods_id' => $goodsId, 'mark' => 1])->whereIn('status', [1, 2])->value('id')) {
  843. DB::rollBack();
  844. $this->error = 2032;
  845. return false;
  846. }
  847. if (!TradeModel::insertGetId($data)) {
  848. DB::rollBack();
  849. $this->error = 2040;
  850. RedisService::keyDel($lockCacheKey);
  851. return false;
  852. }
  853. if (!GoodsModel::where(['id' => $goodsId])->update(['is_trade' => 1, 'update_time' => time()])) {
  854. DB::rollBack();
  855. $this->error = 2040;
  856. RedisService::keyDel($lockCacheKey);
  857. return false;
  858. }
  859. DB::commit();
  860. $this->error = 2041;
  861. RedisService::keyDel($lockCacheKey);
  862. // 抢拍成功,清除当天已抢拍数量统计
  863. RedisService::keyDel("caches:trade:snapNum:{$userId}");
  864. return true;
  865. }
  866. /**
  867. * 付款
  868. * @param $params
  869. * @param $userId
  870. * @param $shopId
  871. * @return bool
  872. */
  873. public function pay($params, $userId, $shopId)
  874. {
  875. $id = isset($params['id']) ? $params['id'] : 0;
  876. $payImg = isset($params['pay_img']) ? $params['pay_img'] : '';
  877. if (empty($payImg)) {
  878. $this->error = 2043;
  879. return false;
  880. }
  881. $info = $this->model->where(['id' => $id, 'mark' => 1])->first();
  882. if (empty($id) || empty($info)) {
  883. $this->error = 2042;
  884. return false;
  885. }
  886. if ($info['status'] != 1) {
  887. $this->error = 2044;
  888. return false;
  889. }
  890. if ($info['user_id'] != $userId) {
  891. $this->error = 2045;
  892. return false;
  893. }
  894. // 卖家收款账号
  895. // $bankInfo = MemberBankService::make()->getBindInfo($info['user_id']);
  896. // if (empty($bankInfo)) {
  897. // $this->error = 2060;
  898. // return false;
  899. // }
  900. if ($this->model->where(['id' => $id, 'mark' => 1])->update(['pay_time' => time(), 'pay_img' => $payImg, 'status' => 2, 'update_time' => time()])) {
  901. $this->error = 2046;
  902. return true;
  903. }
  904. $this->error = 2047;
  905. return false;
  906. }
  907. /**
  908. * 确认收款
  909. * @param $params
  910. * @param $userId
  911. * @return bool
  912. */
  913. public function confirm($params, $userId)
  914. {
  915. $id = isset($params['id']) ? $params['id'] : 0;
  916. $info = $this->model->where(['id' => $id, 'mark' => 1])->first();
  917. if (empty($id) || empty($info)) {
  918. $this->error = 2042;
  919. return false;
  920. }
  921. if (!in_array($info['status'], [1, 2])) {
  922. $this->error = 2044;
  923. return false;
  924. }
  925. DB::beginTransaction();
  926. $data = ['confirm_time' => time(), 'is_pay' => 1, 'status' => 3, 'update_time' => time()];
  927. if (!$this->model->where(['id' => $id, 'mark' => 1])->update($data)) {
  928. $this->error = 2050;
  929. DB::rollBack();
  930. return false;
  931. }
  932. DB::commit();
  933. $this->error = 2049;
  934. return true;
  935. }
  936. /**
  937. * 确认收款
  938. * @param $params
  939. * @param $userId
  940. * @return bool
  941. */
  942. public function confirm1($params, $userId)
  943. {
  944. $id = isset($params['id']) ? $params['id'] : 0;
  945. $info = $this->model->where(['id' => $id, 'mark' => 1])->first();
  946. if (empty($id) || empty($info)) {
  947. $this->error = 2042;
  948. return false;
  949. }
  950. if (!in_array($info['status'], [1, 2])) {
  951. $this->error = 2044;
  952. return false;
  953. }
  954. DB::beginTransaction();
  955. $data = ['confirm_time' => time(), 'is_pay' => 1, 'status' => 3, 'update_time' => time()];
  956. if (!$this->model->where(['id' => $id, 'mark' => 1])->update($data)) {
  957. $this->error = 2050;
  958. DB::rollBack();
  959. return false;
  960. }
  961. $this->model->where(['goods_id' => $info['goods_id'], 'status' => 4, 'mark' => 1])->update(['is_out' => 1, 'update_time' => time()]);
  962. // 更改商品归属人
  963. if (!GoodsModel::where(['id' => $info['goods_id'], 'mark' => 1])->update(['user_id' => $info['user_id'], 'update_time' => time()])) {
  964. $this->error = 2050;
  965. DB::rollBack();
  966. return false;
  967. }
  968. $memberInfo = MemberModel::where(['id' => $info['user_id'], 'mark' => 1])->first();
  969. $parentId = isset($memberInfo['parent_id']) ? $memberInfo['parent_id'] : 0;
  970. $meritsCount = isset($memberInfo['merits_count']) ? $memberInfo['merits_count'] : 0;
  971. $updateData = ['merits_count' => $meritsCount + $info['real_price'], 'merits_time' => date('Y-m-d H:i:s'), 'member_level' => 1, 'update_time' => time()];
  972. if (!MemberModel::where(['id' => $info['user_id']])->update($updateData)) {
  973. $this->error = 2050;
  974. DB::rollBack();
  975. return false;
  976. }
  977. // 佣金结算
  978. $parentInfo = MemberModel::where(['id' => $parentId, 'mark' => 1])->first();
  979. $bonusRate = ConfigService::make()->getConfigByCode('bonus_rate');
  980. $bonusRate = $bonusRate ? $bonusRate : 5;
  981. $bonus = $info['real_price'] * $bonusRate / 100;
  982. $profitRate = ConfigService::make()->getConfigByCode('profit_rate');
  983. $profitRate = $profitRate ? $profitRate : 0;
  984. $profit = $info['real_price'] * $profitRate / 100;
  985. if (!$this->model->where(['id' => $id, 'mark' => 1])->update(['bonus' => $bonus, 'profit' => $profit, 'update_time' => time()])) {
  986. $this->error = 2051;
  987. DB::rollBack();
  988. return true;
  989. }
  990. // 收益记录
  991. $data = [
  992. 'user_id' => $info['user_id'],
  993. 'shop_id' => $info['shop_id'],
  994. 'source_uid' => 0,
  995. 'source_order_sn' => $info['order_sn'],
  996. 'type' => 2,
  997. 'coin_type' => 5,
  998. 'money' => $profit,
  999. 'balance' => 0,
  1000. 'create_time' => time(),
  1001. 'update_time' => time(),
  1002. 'remark' => '抢拍收益',
  1003. 'status' => 1,
  1004. 'mark' => 1
  1005. ];
  1006. if (!AccountModel::insertGetId($data)) {
  1007. $this->error = 2051;
  1008. DB::rollBack();
  1009. return true;
  1010. }
  1011. // 佣金入账
  1012. if ($memberInfo && $parentId && $parentInfo && $bonus > 0) {
  1013. $meritsTotal = isset($parentInfo['merits_total']) ? $parentInfo['merits_total'] : 0;
  1014. $updateData = ['merits_total' => $meritsTotal + $info['real_price'], 'bonus' => $parentInfo['bonus'] + $bonus, 'bonus_total' => $parentInfo['bonus_total'] + $bonus, 'update_time' => time()];
  1015. if (!MemberModel::where(['id' => $parentId, 'mark' => 1])->update($updateData)) {
  1016. $this->error = 2051;
  1017. DB::rollBack();
  1018. return true;
  1019. }
  1020. // 佣金记录
  1021. $data = [
  1022. 'user_id' => $parentId,
  1023. 'shop_id' => $info['shop_id'],
  1024. 'source_uid' => $info['user_id'],
  1025. 'source_order_sn' => $info['order_sn'],
  1026. 'type' => 2,
  1027. 'coin_type' => 2,
  1028. 'money' => $bonus,
  1029. 'balance' => $parentInfo['bonus'],
  1030. 'create_time' => time(),
  1031. 'update_time' => time(),
  1032. 'remark' => '推广佣金',
  1033. 'status' => 1,
  1034. 'mark' => 1
  1035. ];
  1036. if (!AccountModel::insertGetId($data)) {
  1037. $this->error = 2051;
  1038. DB::rollBack();
  1039. return true;
  1040. }
  1041. // 结算统计
  1042. FinanceService::make()->settleBonus($bonus, 2);
  1043. }
  1044. DB::commit();
  1045. // 店铺统计
  1046. $shopId = isset($info['shop_id']) ? $info['shop_id'] : 0;
  1047. $shopInfo = ShopModel::where(['id' => $shopId])->first();
  1048. if ($shopInfo) {
  1049. ShopModel::where(['id' => $shopId])->update(['trade_count' => $shopInfo['trade_count'], 'trade_total' => $info['real_price'] + $shopInfo['trade_total']]);
  1050. }
  1051. $this->error = 2049;
  1052. return true;
  1053. }
  1054. /**
  1055. * 申请待售
  1056. * @param $params
  1057. * @param $userId
  1058. * @return false
  1059. */
  1060. public function sell($params, $userId)
  1061. {
  1062. $id = isset($params['id']) ? $params['id'] : 0;
  1063. $info = $this->model->where(['id' => $id, 'mark' => 1])->first();
  1064. if (empty($id) || empty($info)) {
  1065. $this->error = 2042;
  1066. return false;
  1067. }
  1068. if ($info['status'] != 3) {
  1069. $this->error = 2053;
  1070. return false;
  1071. }
  1072. if ($info['user_id'] != $userId) {
  1073. $this->error = 2045;
  1074. return false;
  1075. }
  1076. DB::beginTransaction();
  1077. if (!$this->model->where(['id' => $id])->update(['status' => 4, 'is_sell' => 1, 'update_time' => time()])) {
  1078. DB::rollBack();
  1079. $this->error = 2054;
  1080. return false;
  1081. }
  1082. if (!GoodsModel::where(['id' => $info['goods_id']])->update(['confirm_status' => 2, 'update_time' => time()])) {
  1083. DB::rollBack();
  1084. $this->error = 2054;
  1085. return false;
  1086. }
  1087. DB::commit();
  1088. $this->error = 2055;
  1089. return true;
  1090. }
  1091. /**
  1092. * 申请待售审核
  1093. * @param $params
  1094. * @param $userId
  1095. * @return false
  1096. */
  1097. public function sellConfirm($params)
  1098. {
  1099. $id = isset($params['id']) ? $params['id'] : 0;
  1100. $info = $this->model->from('trade as a')
  1101. ->leftJoin('goods as b', 'b.id', '=', 'a.goods_id')
  1102. ->where(['a.id' => $id, 'a.mark' => 1])
  1103. ->select(['a.*', 'b.split_price', 'b.split_num'])
  1104. ->first();
  1105. if (empty($id) || empty($info)) {
  1106. $this->error = 2042;
  1107. return false;
  1108. }
  1109. if (!in_array($info['status'], [3, 4])) {
  1110. $this->error = 2053;
  1111. return false;
  1112. }
  1113. DB::beginTransaction();
  1114. $priceRate = ConfigService::make()->getConfigByCode('price_rate');
  1115. $priceRate = $priceRate ? $priceRate : 4;
  1116. $stopSplitPrice = ConfigService::make()->getConfigByCode('stop_split_price');
  1117. $stopSplitPrice = $stopSplitPrice ? $stopSplitPrice : 500;
  1118. // 判断是否可以上架或拆分
  1119. if ($info['split_price'] <= 0) {
  1120. $splitPrice = ConfigService::make()->getConfigByCode('split_price');
  1121. $splitPrice = $splitPrice ? $splitPrice : 10000;
  1122. $info['split_price'] = $splitPrice;
  1123. }
  1124. $realPrice = $info['real_price'];
  1125. $sellPrice = $info['sell_price']; // 特价
  1126. $price = $info['price']; // 买入价格
  1127. $price1 = $info['new_price']; // 买入价格
  1128. $addPrice = intval($realPrice * $priceRate / 100, 0);
  1129. // 满足涨价上架
  1130. if ($price1 + $addPrice < $info['split_price']) {
  1131. // 更新价格
  1132. if (!$this->model->where(['id' => $id])->update(['status' => 4, 'new_price' => $price1 + $addPrice, 'new_real_price' => $realPrice + $addPrice, 'is_sell' => 2, 'update_time' => time()])) {
  1133. $this->error = 2056;
  1134. DB::rollBack();
  1135. return false;
  1136. }
  1137. // 更新其他交易状态
  1138. $this->model->where(['goods_id' => $info['goods_id'], 'status' => 4, 'mark' => 1])->whereNotIn('id', [$id])->update(['is_out' => 1, 'update_time' => time()]);
  1139. if (!GoodsModel::where(['id' => $info['goods_id']])->update(['user_id'=>$info['user_id'],'last_sell_time' => time(), 'price' => $price1 + $addPrice, 'real_price' => $realPrice + $addPrice, 'is_trade' => 2, 'confirm_status' => 1, 'remark' => '上架审核 ' . date('Y-m-d H:i:s'), 'update_time' => time()])) {
  1140. $this->error = 2056;
  1141. DB::rollBack();
  1142. return false;
  1143. }
  1144. DB::commit();
  1145. // 佣金结算
  1146. if (!TradeService::make()->tradeSettle($id, $info)) {
  1147. return false;
  1148. }
  1149. $this->error = 2057;
  1150. return true;
  1151. } // 停止拆分
  1152. else if ($info['sell_price'] == $stopSplitPrice) {
  1153. // 更新审核状态
  1154. if (!$this->model->where(['id' => $id])->update(['status' => 4, 'is_sell' => 2, 'update_time' => time()])) {
  1155. $this->error = 2056;
  1156. DB::rollBack();
  1157. return false;
  1158. }
  1159. // 更改商品归属人
  1160. if (!GoodsModel::where(['id' => $info['goods_id'], 'mark' => 1])->update(['user_id' => $info['user_id'], 'update_time' => time()])) {
  1161. $this->error = 2050;
  1162. DB::rollBack();
  1163. return false;
  1164. }
  1165. if (!GoodsModel::where(['id' => $info['goods_id']])->update(['status' => 1, 'confirm_status' => 2, 'split_stop' => 1, 'update_time' => time()])) {
  1166. $this->error = 2054;
  1167. DB::rollBack();
  1168. return false;
  1169. }
  1170. // 佣金结算
  1171. DB::commit();
  1172. if (!TradeService::make()->tradeSettle($id, $info)) {
  1173. return false;
  1174. }
  1175. $this->error = 2064;
  1176. return true;
  1177. } // 满足拆分
  1178. else if ($info['split_price']) {
  1179. // 更新审核状态
  1180. if (!$this->model->where(['id' => $id])->update(['status' => 4, 'is_sell' => 2, 'update_time' => time()])) {
  1181. $this->error = 2056;
  1182. DB::rollBack();
  1183. return false;
  1184. }
  1185. // 更新其他交易状态
  1186. $this->model->where(['goods_id' => $info['goods_id'], 'status' => 4, 'mark' => 1])->whereNotIn('id', [$id])->update(['is_out' => 1, 'update_time' => time()]);
  1187. // 更改商品归属人
  1188. if (!GoodsModel::where(['id' => $info['goods_id'], 'mark' => 1])->update(['user_id' => $info['user_id'], 'update_time' => time()])) {
  1189. $this->error = 2050;
  1190. DB::rollBack();
  1191. return false;
  1192. }
  1193. if (!GoodsService::make()->split($info['goods_id'], $info)) {
  1194. $this->error = 2058;
  1195. DB::rollBack();
  1196. return false;
  1197. }
  1198. // 佣金结算
  1199. DB::commit();
  1200. if (!TradeService::make()->tradeSettle($id, $info)) {
  1201. return false;
  1202. }
  1203. $this->error = 2059;
  1204. return true;
  1205. }
  1206. $this->error = 2056;
  1207. return false;
  1208. }
  1209. /**
  1210. * 交易结算
  1211. * @param $tradeId
  1212. * @param $info
  1213. * @return bool
  1214. */
  1215. public function tradeSettle($tradeId, $info)
  1216. {
  1217. // 更新商品交易状态
  1218. DB::beginTransaction();
  1219. $memberInfo = MemberModel::where(['id' => $info['user_id'], 'mark' => 1])->first();
  1220. $parentId = isset($memberInfo['parent_id']) ? $memberInfo['parent_id'] : 0;
  1221. $meritsCount = isset($memberInfo['merits_count']) ? $memberInfo['merits_count'] : 0;
  1222. $updateData = ['merits_count' => $meritsCount + $info['real_price'], 'merits_time' => date('Y-m-d H:i:s'), 'member_level' => 1, 'update_time' => time()];
  1223. if (!MemberModel::where(['id' => $info['user_id']])->update($updateData)) {
  1224. $this->error = 2050;
  1225. DB::rollBack();
  1226. return false;
  1227. }
  1228. // 佣金结算
  1229. $parentInfo = MemberModel::where(['id' => $parentId, 'mark' => 1])->first();
  1230. $bonusRate = ConfigService::make()->getConfigByCode('bonus_rate');
  1231. $bonusRate = $bonusRate ? $bonusRate : 5;
  1232. $bonus = $info['real_price'] * $bonusRate / 100;
  1233. $profitRate = ConfigService::make()->getConfigByCode('profit_rate');
  1234. $profitRate = $profitRate ? $profitRate : 0;
  1235. $profit = $info['real_price'] * $profitRate / 100;
  1236. // 平台服务费
  1237. $serviceRate = ConfigService::make()->getConfigByCode('service_fee_rate');
  1238. $serviceRate = $serviceRate ? $serviceRate : 8;
  1239. $serviceFee = round($info['real_price'] * $serviceRate / 100, 0);
  1240. if (!$this->model->where(['id' => $tradeId, 'mark' => 1])->update(['bonus' => $bonus,'service_fee'=> $serviceFee, 'profit' => $profit, 'update_time' => time()])) {
  1241. $this->error = 2051;
  1242. DB::rollBack();
  1243. return true;
  1244. }
  1245. // 服务费统计
  1246. if($serviceFee>0){
  1247. FinanceService::make()->settleBonus($serviceFee, 1);
  1248. }
  1249. // 收益记录
  1250. $data = [
  1251. 'user_id' => $info['user_id'],
  1252. 'shop_id' => $info['shop_id'],
  1253. 'source_uid' => 0,
  1254. 'source_order_sn' => $info['order_sn'],
  1255. 'type' => 2,
  1256. 'coin_type' => 5,
  1257. 'money' => $profit,
  1258. 'balance' => 0,
  1259. 'create_time' => time(),
  1260. 'update_time' => time(),
  1261. 'remark' => '抢拍收益',
  1262. 'status' => 1,
  1263. 'mark' => 1
  1264. ];
  1265. if (!AccountModel::insertGetId($data)) {
  1266. $this->error = 2051;
  1267. DB::rollBack();
  1268. return true;
  1269. }
  1270. // 佣金入账
  1271. if ($memberInfo && $parentId && $parentInfo && $bonus > 0) {
  1272. $meritsTotal = isset($parentInfo['merits_total']) ? $parentInfo['merits_total'] : 0;
  1273. $updateData = ['merits_total' => $meritsTotal + $info['real_price'], 'bonus' => $parentInfo['bonus'] + $bonus, 'bonus_total' => $parentInfo['bonus_total'] + $bonus, 'update_time' => time()];
  1274. if (!MemberModel::where(['id' => $parentId, 'mark' => 1])->update($updateData)) {
  1275. $this->error = 2051;
  1276. DB::rollBack();
  1277. return true;
  1278. }
  1279. // 佣金记录
  1280. $data = [
  1281. 'user_id' => $parentId,
  1282. 'shop_id' => $info['shop_id'],
  1283. 'source_uid' => $info['user_id'],
  1284. 'source_order_sn' => $info['order_sn'],
  1285. 'type' => 2,
  1286. 'coin_type' => 2,
  1287. 'money' => $bonus,
  1288. 'balance' => $parentInfo['bonus'],
  1289. 'create_time' => time(),
  1290. 'update_time' => time(),
  1291. 'remark' => '推广佣金',
  1292. 'status' => 1,
  1293. 'mark' => 1
  1294. ];
  1295. if (!AccountModel::insertGetId($data)) {
  1296. $this->error = 2051;
  1297. DB::rollBack();
  1298. return true;
  1299. }
  1300. // 结算统计
  1301. FinanceService::make()->settleBonus($bonus, 2);
  1302. }
  1303. DB::commit();
  1304. // 店铺统计
  1305. $shopId = isset($info['shop_id']) ? $info['shop_id'] : 0;
  1306. $shopInfo = ShopModel::where(['id' => $shopId])->first();
  1307. if ($shopInfo) {
  1308. ShopModel::where(['id' => $shopId])->update(['trade_count' => $shopInfo['trade_count'] + 1, 'trade_total' => $info['real_price'] + $shopInfo['trade_total']]);
  1309. }
  1310. return true;
  1311. }
  1312. /**
  1313. * 修改订单
  1314. * @param $params
  1315. * @return bool
  1316. */
  1317. public function modify($params)
  1318. {
  1319. $id = isset($params['id']) ? $params['id'] : 0;
  1320. $status = isset($params['status']) ? $params['status'] : 0;
  1321. $info = $this->model->where(['id' => $id, 'mark' => 1])->first();
  1322. if (!$id || empty($info)) {
  1323. $this->error = 2042;
  1324. return false;
  1325. }
  1326. if (!in_array($info['status'], [1, 2, 3, 4])) {
  1327. $this->error = 2082;
  1328. return false;
  1329. }
  1330. if (!in_array($status, [1, 2, 4])) {
  1331. $this->error = 2087;
  1332. return false;
  1333. }
  1334. // $safePassword = isset($params['password'])? trim($params['password']) : '';
  1335. // if(empty($safePassword)){
  1336. // $this->error = 2085;
  1337. // return false;
  1338. // }
  1339. $memberInfo = MemberModel::where(['id' => $info['user_id']])->select(['id', 'safe_password'])->first();
  1340. $password = isset($memberInfo['safe_password']) ? $memberInfo['safe_password'] : '';
  1341. if (empty($memberInfo)) {
  1342. $this->error = 2019;
  1343. return false;
  1344. }
  1345. // $safePassword = get_password($safePassword);
  1346. // if($password != $safePassword){
  1347. // $this->error = 2086;
  1348. // return false;
  1349. // }
  1350. if ($this->model->where(['id' => $id])->update(['status' => $status, 'update_time' => time()])) {
  1351. $this->error = 1020;
  1352. return true;
  1353. } else {
  1354. $this->error = 1021;
  1355. return false;
  1356. }
  1357. }
  1358. /**
  1359. * 修改订单
  1360. * @param $params
  1361. * @return bool
  1362. */
  1363. public function cancel($params)
  1364. {
  1365. $id = isset($params['id']) ? $params['id'] : 0;
  1366. $status = isset($params['status']) ? $params['status'] : 0;
  1367. $info = $this->model->where(['id' => $id, 'mark' => 1])->first();
  1368. if (!$id || empty($info)) {
  1369. $this->error = 2042;
  1370. return false;
  1371. }
  1372. if (!in_array($info['status'], [1, 2, 3, 4])) {
  1373. $this->error = 2082;
  1374. return false;
  1375. }
  1376. DB::beginTransaction();
  1377. if (!$this->model->where(['id' => $id])->update(['status' => 5,'remark'=>'店长取消订单:'.date('Y-m-d H:i:s'), 'update_time' => time()])) {
  1378. DB::rollBack();
  1379. $this->error = 2089;
  1380. return false;
  1381. }
  1382. if(!GoodsModel::where(['id'=> $info['goods_id'],'mark'=>1])->update(['status'=>1,'is_trade'=>2,'confirm_status'=>1,'remark'=>'店长取消订单'])){
  1383. DB::rollBack();
  1384. $this->error = 2089;
  1385. return false;
  1386. }
  1387. DB::commit();
  1388. $this->error = 2088;
  1389. return true;
  1390. }
  1391. /**
  1392. * 定期清除交易记录
  1393. * @return false
  1394. */
  1395. public function clearByDay()
  1396. {
  1397. $day = ConfigService::make()->getConfigByCode('clear_trade_time');
  1398. $day = $day ? $day : 2;
  1399. $cacheKey = "caches:task:clearTrade:d{$day}_" . date('Ymd');
  1400. if (RedisService::get($cacheKey)) {
  1401. $this->error = '2301';
  1402. return false;
  1403. }
  1404. // 取消订单
  1405. $this->model->where('create_time', '<', strtotime(date('Y-m-d')))
  1406. ->where('create_time', '<', time() - 7200)->where(['mark' => 1])
  1407. ->where('status','<',4)
  1408. ->update(['mark'=>0,'remark'=>'订单未付款取消']);
  1409. // 清除订单
  1410. $clearDay = strtotime(date('Y-m-d')) - $day * 86400;
  1411. $count = $this->model->where('create_time', '<', $clearDay)->count();
  1412. if ($count <= 0) {
  1413. $this->error = '';
  1414. RedisService::set($cacheKey, ['error' => '没有记录可以清除', 'day' => $day, 'clearDay' => date('Y-m-d', $clearDay)], 6 * 3600);
  1415. return false;
  1416. }
  1417. $this->model->where('create_time', '<', $clearDay)->update(['mark' => 0, 'remark' => '到期清除', 'update_time' => time()]);
  1418. $this->model->where('create_time', '<', $clearDay - 86400)->where(['mark' => 0])->delete();
  1419. $result = ['count' => $count, 'day' => date('Y-m-d H:i:s', $clearDay)];
  1420. RedisService::set($cacheKey, $result, 7200);
  1421. return $result;
  1422. }
  1423. }