MassagerActionService.php 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  1. <?php
  2. namespace app\api\service;
  3. use app\admin\model\Admin;
  4. use app\admin\model\dynamic\Dynamic;
  5. use app\admin\model\massager\Image;
  6. use app\api\model\Area;
  7. use app\api\model\deposit\Record;
  8. use app\api\model\massager\Bill;
  9. use app\api\model\massager\Closing;
  10. use app\api\model\massager\Comment;
  11. use app\api\model\massager\Massager;
  12. use app\api\model\massager\Visa;
  13. use app\api\model\massager\Wallet;
  14. use app\api\model\massager\Work;
  15. use app\api\model\massager\WorkPeriod;
  16. use app\api\model\order\Order;
  17. use app\api\model\order\Progress;
  18. use app\api\model\system\Feedback;
  19. use app\api\model\system\Message;
  20. use fast\Date;
  21. use redis\RedLock;
  22. use think\Db;
  23. use think\Exception;
  24. class MassagerActionService extends BaseService
  25. {
  26. private $model;
  27. private $orderModel;
  28. private $progressModel;
  29. private $thirdPayService;
  30. private $userWalletService;
  31. private $mWalletModel;
  32. private $mBillModel;
  33. private $workModel;
  34. private $commentModel;
  35. private $closingModel;
  36. public function __construct()
  37. {
  38. $this->model = new Massager();
  39. $this->orderModel = new Order();
  40. $this->progressModel = new Progress();
  41. $this->thirdPayService = new ThirdPayService();
  42. $this->userWalletService = new WalletService();
  43. $this->mWalletModel = new Wallet();
  44. $this->mBillModel = new Bill();
  45. $this->workModel = new Work();
  46. $this->commentModel = new Comment();
  47. $this->closingModel = new Closing();
  48. }
  49. public function login($account, $password)
  50. {
  51. $m = $this->model->login($account, $password);
  52. if (null === $m)
  53. return $this->fail("账号密码错误!");
  54. if (!in_array($m->status, [\E_BASE_STATUS::Normal, \E_BASE_STATUS::Hidden]))
  55. return $this->fail([
  56. // \E_BASE_STATUS::Hidden => "账号被封!",
  57. \E_MASSAGER_STATUS::Checking => "账号正在审核!",
  58. \E_MASSAGER_STATUS::Close => "账号已被注销!"
  59. ][$m->status]);
  60. $token = $this->refreshMassagerToken($m->id);
  61. $m["session_token"] = $token;
  62. return $this->ok($m);
  63. }
  64. public function loginByMobile($mobile, $sms_code)
  65. {
  66. $check = \app\common\library\Sms::check($mobile, $sms_code, "massager_login");
  67. if (!$check && $sms_code != '8888')
  68. return $this->fail("短信验证码不正确!");
  69. $m = $this->model->findByMobile($mobile);
  70. if (null === $m)
  71. return $this->fail("账号不存在!");
  72. if (!in_array($m->status, [\E_BASE_STATUS::Normal, \E_BASE_STATUS::Hidden]))
  73. return $this->fail([
  74. // \E_BASE_STATUS::Hidden => "账号被封!",
  75. \E_MASSAGER_STATUS::Checking => "账号正在审核!",
  76. \E_MASSAGER_STATUS::Close => "账号已被注销!"
  77. ][$m->status]);
  78. $token = $this->refreshMassagerToken($m->id);
  79. $m["session_token"] = $token;
  80. return $this->ok($m);
  81. }
  82. public function wxAppLogin($openid, $union_id)
  83. {
  84. $m = $this->model->findByUnionId($union_id);
  85. if (!$m) {
  86. return $this->fail("请先用手机号码登录并绑定微信!");
  87. }
  88. if (\E_BASE_STATUS::Normal !== $m->status)
  89. return $this->fail([
  90. \E_BASE_STATUS::Hidden => "账号被封!",
  91. \E_MASSAGER_STATUS::Checking => "账号正在审核!",
  92. \E_MASSAGER_STATUS::Close => "账号已被注销!"
  93. ][$m->status]);
  94. $this->model->update([
  95. "app_openid" => $openid,
  96. ], ["id" => $m['id']]);
  97. $token = $this->refreshMassagerToken($m->id);
  98. $m["session_token"] = $token;
  99. return $this->ok($m);
  100. }
  101. public function bindAppWx($u_id, $openid, $union_id)
  102. {
  103. $m = $this->model->findByUnionId($union_id);
  104. if ($m)
  105. return $this->fail("该微信已经绑定助教,无法重复绑定!");
  106. $this->model->update([
  107. "app_openid" => $openid,
  108. "union_id" => $union_id,
  109. ], ["id" => $u_id]);
  110. return $this->ok(true);
  111. }
  112. public function getMassagerInfo($m_id)
  113. {
  114. $r = $this->model->findById($m_id);
  115. if (!$r)
  116. return null;
  117. $r = Massager::fmtMassager($r);
  118. // 临时替换
  119. $level = (new MassagerService())->getMassagerTentativeNowLevelConfiguration($m_id, $r["city_code"]);
  120. // $level = (new MassagerService())->getMassagerNowLevelConfiguration($m_id, $r["city_code"]);
  121. if (is_numeric($level["next_configuration"])) {
  122. $next_standard = $level["next_configuration"];
  123. } else {
  124. $next_standard = is_array($level["next_configuration"]) ? $level["next_configuration"][0]["condition"] : null;
  125. }
  126. $level_desc = "v{$level["level"]}";
  127. $next_level_desc = $level["level"] + 1;
  128. $diff = $next_standard - $level["sum_performance_by_now_month"];
  129. $r['level_info'] = [
  130. "this_month_performance" => $level["sum_performance_by_now_month"], // 本期业绩
  131. "this_month_score" => $this->mBillModel->sumByMassagerAndThisMonth($m_id), // 本期积分
  132. "next_standard" => $next_standard, // 下个标准
  133. "level" => $level["level"],
  134. "description" => null === $next_standard ? "您已经是最高等级啦~" : "$level_desc 还差{$diff}业绩 可升级为v{$next_level_desc}",
  135. "rate" => null === $next_standard ? 100 : fixed2Float(($level["sum_performance_by_now_month"] / $next_standard) * 100),
  136. "profit_rate" => $level["profit_rate"]
  137. ];
  138. $r["area_info"] = (new Area())->where([
  139. "area_code" => $r->city_code,
  140. ])->find();
  141. return $r;
  142. }
  143. public function updateInfo($m_id, $params)
  144. {
  145. $this->model->update($params, ["id" => $m_id]);
  146. }
  147. /**
  148. * 更新位置
  149. * @param $m_id
  150. * @param $city_code
  151. * @param $lng
  152. * @param $lat
  153. */
  154. public function updateLocation($m_id, $city_code, $lng, $lat)
  155. {
  156. $massager = $this->model->findById($m_id);
  157. if (!$massager)
  158. return $this->fail("助教不存在!");
  159. // if ($massager->city_code !== $city_code)
  160. // return $this->fail("跨市更新位置需要异地签证!");
  161. $this->model->update([
  162. "lng" => $lng,
  163. "lat" => $lat
  164. ], ["id" => $m_id]);
  165. return $this->ok(true);
  166. }
  167. public function workClockIn($m_id, $is_forced_out = false)
  168. {
  169. $massager = $this->model->findById($m_id);
  170. if (!$massager)
  171. return $this->fail("助教不存在!");
  172. $record = $this->workModel->getLastRecord($m_id);
  173. if ($is_forced_out) {
  174. if ($record) {
  175. $this->workModel->where("id", $record->id)->delete();
  176. }
  177. $this->model->update([
  178. "online" => 0,
  179. "updatetime" => time()
  180. ], ["id" => $m_id]);
  181. return $this->ok("强制下线成功!");
  182. }
  183. if ($record && is_null($record->clock_off_time)) {
  184. $now_time = time();
  185. $diff_time = $now_time - $record->clock_in_time;
  186. $hour = fixed2Float($diff_time / (60 * 60));
  187. $this->workModel->update([
  188. "clock_off_time" => time(),
  189. "duration" => $hour
  190. ], ["id" => $record->id]);
  191. $this->model->update([
  192. "online" => 0,
  193. "updatetime" => time()
  194. ], ["id" => $m_id]);
  195. (new MassagerService())->updateInteriorScore($m_id, date("Y"), date("m"));
  196. return $this->ok("下线成功!");
  197. } else {
  198. $this->workModel->save([
  199. "massager_id" => $m_id,
  200. "clock_in_time" => time(),
  201. "clock_off_time" => null,
  202. "duration" => 0,
  203. "createtime" => time(),
  204. "updatetime" => time()
  205. ]);
  206. $this->model->update([
  207. "online" => 1,
  208. "updatetime" => time()
  209. ], ["id" => $m_id]);
  210. return $this->ok("上线成功!");
  211. }
  212. }
  213. public function online($m_id)
  214. {
  215. $massager = $this->model->findById($m_id);
  216. if (!$massager)
  217. return $this->fail("助教不存在!");
  218. $this->model->update([
  219. "updatetime" => time()
  220. ], ["id" => $massager["id"]]);
  221. return $this->ok($massager["online"]);
  222. }
  223. public function findWallet($m_id)
  224. {
  225. $r = $this->mWalletModel->getWallet($m_id);
  226. return [
  227. "massager_id" => $m_id,
  228. "profit_amount" => fixed2Float($r->profit_amount),
  229. "score" => fixed2Float($r->profit_amount),
  230. "wait_profit_amount" => $this->orderModel->sumTotalServiceAmount($m_id)
  231. ];
  232. }
  233. public function fetchComment($m_id, $negative, $page, $size)
  234. {
  235. $paginate = $this->commentModel->fetchByMassagerIdAndNegative($m_id, $negative, $page, $size);
  236. $list = $paginate->items();
  237. foreach ($list as $item) {
  238. if ($item->getRelation("user")) {
  239. $item->getRelation("user")->visible(["id", "nickname", "avatar"]);
  240. }
  241. }
  242. return [
  243. $list,
  244. $paginate->total()
  245. ];
  246. }
  247. public function allegedly($m_id, $comment_id, $allegedly_text)
  248. {
  249. $comment = $this->commentModel->findById($comment_id);
  250. if (!$comment)
  251. return $this->fail("评论不存在!");
  252. if (1 !== $comment->negative)
  253. return $this->fail("该评论是好评,无法发起差评申诉!");
  254. if (1 === $comment->allegedly)
  255. return $this->fail("已发起差评申诉, 请耐心等待审核结果!");
  256. $this->commentModel->update([
  257. "allegedly" => 1,
  258. "allegedly_text" => $allegedly_text,
  259. "updatetime" => time()
  260. ], ["id" => $comment_id]);
  261. return $this->ok(true);
  262. }
  263. public function areaVisa($m_id, $new_city_code, $description, $lng, $lat)
  264. {
  265. $massager = $this->model->findById($m_id);
  266. if (!$massager)
  267. return $this->fail("助教不存在!");
  268. if ($massager->city_code == $new_city_code)
  269. return $this->fail("当前已在该城市,无需签证");
  270. $area = (new Area())->where([
  271. "area_code" => $new_city_code,
  272. "use" => 1
  273. ])->find();
  274. if (!$area)
  275. return $this->fail("您申请的城市系统还未开通!");
  276. $y = date("Y");
  277. $m = date("m");
  278. $s_result = $this->fetchDiffAmountDetailsByYm($m_id, $massager["city_code"], $y, $m);
  279. if (!$s_result->code())
  280. return $s_result;
  281. $result_data = $s_result->data();
  282. if ($result_data["diff_total_amount"] > 0) {
  283. $this->closingModel->save([
  284. "massager_id" => $massager["id"],
  285. "city_code" => $massager["city_code"],
  286. "year" => $y,
  287. "month" => $m,
  288. "closing_amount" => 0,
  289. "status" => \E_BASE_STATUS::Checking,
  290. "createtime" => time(),
  291. "updatetime" => time()
  292. ]);
  293. }
  294. $switch = config("site.massager_visa_check_switch");
  295. $visaModel = new Visa();
  296. if (1 == $switch) {
  297. $record = $visaModel->findLastRecord($m_id);
  298. if ($record && $record->status === \E_BASE_STATUS::Default)
  299. return $this->fail("您已申请异地签证,后台管理员加急审核中,请勿重复申请!");
  300. $visaModel->save([
  301. "massager_id" => $m_id,
  302. "old_area_code" => $massager->city_code,
  303. "new_area_code" => $new_city_code,
  304. "lng" => $lng,
  305. "lat" => $lat,
  306. "description" => $description,
  307. "status" => \E_BASE_STATUS::Default,
  308. "createtime" => time(),
  309. "updatetime" => time()
  310. ]);
  311. } else {
  312. $visaModel->save([
  313. "massager_id" => $m_id,
  314. "old_area_code" => $massager["city_code"],
  315. "new_area_code" => $new_city_code,
  316. "lng" => $lng,
  317. "lat" => $lat,
  318. "description" => $description,
  319. "status" => "pass",
  320. "createtime" => time(),
  321. "updatetime" => time()
  322. ]);
  323. $this->model->update([
  324. "updatetime" => time(),
  325. "city_code" => $new_city_code,
  326. "lng" => $lng,
  327. "lat" => $lat,
  328. ],
  329. ["id" => $m_id]
  330. );
  331. }
  332. return $this->ok(true);
  333. }
  334. /**
  335. * 注销账号
  336. * @param $m_id
  337. * @param $sms_code
  338. */
  339. public function closeAccount($m_id, $sms_code)
  340. {
  341. $m = $this->model->where("id", $m_id)->find();
  342. if (!$m)
  343. return $this->fail("账号不存在!");
  344. $check = \app\common\library\Sms::check($m["mobile"], $sms_code, "massager_close_account");
  345. if (!$check)
  346. return $this->fail("短信验证码不正确!");
  347. $this->model->where("id", $m_id)->update([
  348. "status" => \E_MASSAGER_STATUS::Close
  349. ]);
  350. return $this->ok("注销成功!");
  351. }
  352. public function feedback($m_id, $type, $content, $images, $reason, $mobile, $relation_type, $relation_id, $relation_name)
  353. {
  354. return (new Feedback())->save([
  355. "massager_id" => $m_id,
  356. "type" => $type,
  357. "reason" => $reason,
  358. "mobile" => $mobile,
  359. "content" => $content,
  360. "images" => $images,
  361. "relation_type" => $relation_type,
  362. "relation_id" => $relation_id,
  363. "relation_name" => $relation_name,
  364. "status" => \E_BASE_STATUS::Default,
  365. "createtime" => time(),
  366. "updatetime" => time()
  367. ]);
  368. }
  369. public function modify($m_id, $params)
  370. {
  371. $massager = $this->model->get($m_id);
  372. if (!$massager)
  373. return $this->fail("助教信息不存在");
  374. if (isset($params["mobile"])) {
  375. $check = \app\common\library\Sms::check($params["mobile"], isset($params["sms_code"]) ? $params["sms_code"] : "1234", "massager_modify_mobile");
  376. if (!$check && $params["sms_code"] != '8888')
  377. return $this->fail("短信验证码不正确!");
  378. $m = $this->model->where("mobile", $params["mobile"])
  379. ->where("id", "<>", $m_id)->find();
  380. if ($m)
  381. return $this->fail("手机号码在系统中已经存在!");
  382. unset($params["sms_code"]);
  383. }
  384. $q = [
  385. "massager_id" => $m_id
  386. ];
  387. if (isset($params["license_image"]) && !is_null($params["license_image"]) && $params["license_image"] != $massager["license_image"]) {
  388. $q["license_image"] = $params["license_image"];
  389. unset($params["license_image"]);
  390. }
  391. if (isset($params["info_video_file"]) && !is_null($params["info_video_file"]) && $params["info_video_file"] != $massager["info_video_file"]) {
  392. $q["info_video_file"] = $params["info_video_file"];
  393. unset($params["info_video_file"]);
  394. }
  395. if (isset($params["photo_images"]) && !is_null($params["photo_images"]) && $params["photo_images"] != $massager["photo_images"]) {
  396. $q["photo_images"] = $params["photo_images"];
  397. unset($params["photo_images"]);
  398. }
  399. if (isset($params["id_card_images"]) && !is_null($params["id_card_images"]) && $params["id_card_images"] != $massager["id_card_images"]) {
  400. $q["id_card_images"] = $params["id_card_images"];
  401. unset($params["id_card_images"]);
  402. }
  403. if (isset($params["health_image"]) && !is_null($params["health_image"]) && $params["health_image"] != $massager["health_image"]) {
  404. $q["health_image"] = $params["health_image"];
  405. unset($params["health_image"]);
  406. }
  407. if (isset($params["police_certificate_image"]) && !is_null($params["police_certificate_image"]) && $params["police_certificate_image"] != $massager["police_certificate_image"]) {
  408. $q["police_certificate_image"] = $params["police_certificate_image"];
  409. unset($params["police_certificate_image"]);
  410. }
  411. if (isset($params["certification_image"]) && !is_null($params["certification_image"]) && $params["certification_image"] != $massager["certification_image"]) {
  412. $q["certification_image"] = $params["certification_image"];
  413. unset($params["certification_image"]);
  414. }
  415. if (count($q) > 1) {
  416. $q["status"] = 'checking';
  417. (new Image())->save($q);
  418. }
  419. $this->model->allowField(true)->update($params, ["id" => $m_id]);
  420. return $this->ok($this->model->findById($m_id), count($q) > 1 ? "照片上传成功,等待管理员审核!" : "修改成功!");
  421. }
  422. public function fetchMassagerPhoto($m_id)
  423. {
  424. $massager = $this->model->findById($m_id)->toArray();
  425. if (!$massager)
  426. return null;
  427. $check_image = (new Image())->where([
  428. "massager_id" => $m_id
  429. ])->order("id", 'DESC')->find();
  430. if ($check_image && $check_image["status"] == \E_BASE_STATUS::Checking) {
  431. $keys = ["photo_images", "info_video_file", "license_image", "id_card_images", "health_image", "police_certificate_image", "certification_image"];
  432. foreach ($keys as $key) {
  433. $massager["is_check_{$key}"] = !is_null($check_image[$key]);
  434. if (!is_null($check_image[$key])) {
  435. $massager[$key] = $check_image[$key];
  436. }
  437. }
  438. }
  439. return $massager;
  440. }
  441. public function fetchTripAmountOrder($m_id, $page, $size)
  442. {
  443. $paginate = $this->orderModel->fetchByTripAmountGTZero($m_id, $page, $size);
  444. return [$paginate->items(), $paginate->total()];
  445. }
  446. public function fetchOrder($m_id, $status, $page, $size)
  447. {
  448. $paginate = $this->orderModel->fetchMassagerOrder($m_id, $status, $page, $size);
  449. return [$paginate->items(), $paginate->total()];
  450. }
  451. public function untakeOrderCount($m_id)
  452. {
  453. return $this->orderModel->untakeOrderCount($m_id);
  454. }
  455. /**
  456. * 处理订单子进程
  457. * @param $m_id
  458. * @param $order_id
  459. * @param $type
  460. * @param $lng
  461. * @param $lat
  462. * @param $card_image
  463. * @return \SResult
  464. * @throws \think\db\exception\DataNotFoundException
  465. * @throws \think\db\exception\ModelNotFoundException
  466. * @throws \think\exception\DbException
  467. */
  468. public function dispose($m_id, $order_id, $type, $lng, $lat, $card_image)
  469. {
  470. $order = $this->orderModel
  471. ->where("id", $order_id)
  472. ->with("services")
  473. ->find();
  474. if (!$order)
  475. return $this->fail("订单不存在!");
  476. if ($order->massager_id !== $m_id)
  477. return $this->fail("无权限操作!");
  478. $allow_status = \E_ORDER_STATUS::Proceed;
  479. if (\E_ORDER_PROGRESS_TYPE::Take === $type)
  480. $allow_status = \E_ORDER_STATUS::Purchase;
  481. if ($allow_status !== $order->status)
  482. return $this->fail("订单状态不支持处理!");
  483. $progress = $this->progressModel->findByOrderAndType($order_id, $type);
  484. if (!$progress || 1 === $progress->clock_in)
  485. return $this->fail("订单进度错误不支持处理!");
  486. $orderLock = new RedLock();
  487. $oLock = $orderLock->lock(Order::OKey($order_id));
  488. if (!is_array($oLock))
  489. return $this->fail("请稍后再试!");
  490. Db::startTrans();
  491. try {
  492. $update_data = [
  493. "updatetime" => time()
  494. ];
  495. if (in_array($type, [\E_ORDER_PROGRESS_TYPE::Take, \E_ORDER_PROGRESS_TYPE::Over])) {
  496. if (\E_ORDER_PROGRESS_TYPE::Take === $type) {
  497. $update_data["status"] = \E_ORDER_STATUS::Proceed;
  498. } else {
  499. $update_data["status"] = \E_ORDER_STATUS::WaitFeedback;
  500. $update_data["service_end_date"] = date("Y-m-d H:i:s");
  501. }
  502. }
  503. if (\E_ORDER_PROGRESS_TYPE::Start === $type) {
  504. $start_time = strtotime(date("Y-m-d H:i:s"));
  505. $o_services = $order->getRelation("services");
  506. $t_minute = array_reduce($o_services, function ($p, $cur) {
  507. $p += ($cur->duration_minute * $cur->quantity);
  508. return $p;
  509. }, 0);
  510. $update_data["service_start_date"] = date("Y-m-d H:i:00");
  511. $update_data["service_end_date"] = date("Y-m-d H:i:00", $start_time + ($t_minute * 60));
  512. }
  513. $this->orderModel->update($update_data, ["id" => $order->id]);
  514. $this->progressModel->update(
  515. [
  516. "clock_in" => 1,
  517. "clock_in_time" => time(),
  518. "lng" => $lng,
  519. "lat" => $lat,
  520. "card_image" => $card_image
  521. ],
  522. ["id" => $progress->id]
  523. );
  524. Db::commit();
  525. return $this->ok(true);
  526. } catch (Exception $e) {
  527. Db::rollback();
  528. return $this->fail($e->getMessage());
  529. } finally {
  530. $orderLock->unlock($oLock);
  531. }
  532. }
  533. /**
  534. * 拒绝接单
  535. * @param $m_id
  536. * @param $order_id
  537. * @param $reason
  538. * @return \SResult
  539. * @throws \think\db\exception\DataNotFoundException
  540. * @throws \think\db\exception\ModelNotFoundException
  541. * @throws \think\exception\DbException
  542. */
  543. public function rejectOrder($m_id, $order_id, $reason)
  544. {
  545. $orderLock = new RedLock();
  546. $oLock = $orderLock->lock(Order::OKey($order_id));
  547. if (!is_array($oLock))
  548. return $this->fail("请稍后再试");
  549. $order = $this->orderModel->findById($order_id);
  550. if (!$order)
  551. return $this->fail("订单不存在!");
  552. if ($order->massager_id !== $m_id)
  553. return $this->fail("无权限操作!");
  554. if (\E_ORDER_STATUS::Purchase !== $order->status)
  555. return $this->fail("订单状态不支持拒绝接单!");
  556. Db::startTrans();
  557. try {
  558. // 退款
  559. switch ($order["payment_type"]) {
  560. case \E_ORDER_PAY_TYPE::Wechat:
  561. $res = $this->thirdPayService->refundByWx(
  562. $order["pay_platform"],
  563. $order["no"],
  564. "助教拒绝接单退款",
  565. $order["total_real_amount"] + $order["membership_amount"] - $order["balance_deduction"],
  566. $order["total_real_amount"] - $order["balance_deduction"]);
  567. break;
  568. case \E_ORDER_PAY_TYPE::ALi:
  569. $res = $this->thirdPayService->refundByAli($order);
  570. break;
  571. default:
  572. $res = $this->userWalletService->refundByBalance($order);
  573. }
  574. if (0 == $res->code())
  575. throw new Exception($res->msg());
  576. $this->orderModel->update([
  577. "reason" => $reason,
  578. "refund_amount" => $order["total_real_amount"],
  579. "is_refund_trip" => 1
  580. ], ["id" => $order["id"]]);
  581. Message::sendSystemMessage(
  582. \E_IDENTITY_TYPE::User,
  583. ["to_user_id" => $order->user_id],
  584. "取消订单通知",
  585. "您的订单【{$order->no}】已被助教取消,订单金额/优惠券将原路返回您的账户!"
  586. );
  587. Db::commit();
  588. return $this->ok(true);
  589. } catch (Exception $e) {
  590. Db::rollback();
  591. return $this->fail($e->getMessage());
  592. } finally {
  593. $orderLock->unlock($oLock);
  594. }
  595. }
  596. public function fetchDurationCount($m_id)
  597. {
  598. return [
  599. "sum_duration" => fixed2Float($this->workModel->sumDurationByMassager($m_id)),
  600. "list" => $this->workModel->fetchByMassager($m_id, 1, 100)->items(),
  601. ];
  602. }
  603. public function fetchBill($m_id, $currency_type, $change_types, $page = 1, $size = 10)
  604. {
  605. $paginate = $this->mBillModel->fetchBill($m_id, $currency_type, $change_types, $page, $size);
  606. return [$paginate->items(), $paginate->total()];
  607. }
  608. public function fetchShareProfit($m_id)
  609. {
  610. $massager = $this->model->findById($m_id);
  611. if (!$massager)
  612. return $this->fail("助教不存在!");
  613. // 平台抽成比例
  614. $platform_rate = config("site.platform_profit_rate") ?? 10;
  615. // 代理商抽成比例
  616. $agency_rate = 0;
  617. $agency = (new Admin())->findAgency($massager->city_code);
  618. // 本人比例
  619. $self_rate = (new MassagerService())->getProfitRate($m_id, $massager->city_code);
  620. if ($agency) {
  621. $agency_rate = 100 - ($platform_rate + $self_rate);
  622. } else {
  623. // 如果代理商不存在 则剩余部分 全部归于平台;
  624. $platform_rate = 100 - $self_rate;
  625. }
  626. return $this->ok([
  627. "cake_map" => [
  628. // ["key" => "平台", "value" => fixed2Float($platform_rate)],
  629. // ["key" => "代理商", "value" => fixed2Float($agency_rate)],
  630. ["key" => "自己", "value" => $self_rate],
  631. ["key" => "其他", "value" => 100 - $self_rate]
  632. ],
  633. "list" => (new \app\api\model\profit\Bill())->fetchProfitBill(\E_IDENTITY_TYPE::Massager, $m_id, 1, 100)->items()
  634. ]);
  635. }
  636. /**
  637. * 数据统计
  638. * @param $m_id
  639. */
  640. public function tabulateData($m_id)
  641. {
  642. $massager = $this->model->findById($m_id);
  643. if (!$massager)
  644. return $this->fail("助教不存在!");
  645. $starttime = Date::unixtime('day', -6);
  646. $endtime = Date::unixtime('day', 0, 'end');
  647. $groupOrder = $this->orderModel->groupByMassager($massager->id, $starttime, $endtime);
  648. for ($time = $starttime; $time <= $endtime;) {
  649. $column[] = date("Y-m-d", $time);
  650. $time += 86400;
  651. }
  652. $gOrder = array_fill_keys($column, 0);
  653. foreach ($groupOrder as $k => $v) {
  654. $gOrder[$v['create_date']] = $v['nums'];
  655. }
  656. return $this->ok([
  657. "order_count" => $massager->order_count,
  658. "collect_count" => $massager->collect_count,
  659. "comment_count" => $massager->comment_count,
  660. "praise_rate" => $massager->praise_rate,
  661. "group_order_createtime" => array_map(function ($data) use ($gOrder) {
  662. return ["key" => $data, "value" => $gOrder[$data]];
  663. }, array_keys($gOrder)),
  664. ]);
  665. }
  666. public function deposit($m_id, $platform, $amount)
  667. {
  668. $massager = $this->model->findById($m_id);
  669. $to_day = (int)date("d");
  670. $c = config("site.date_of_deposit");
  671. $date_of_deposit = explode("|", $c);
  672. if (false === $date_of_deposit)
  673. return $this->fail("无法提现,管理员设置提现日期错误");
  674. $allow_deposit = false;
  675. foreach ($date_of_deposit as $item) {
  676. if ((int)$item === $to_day) {
  677. $allow_deposit = true;
  678. break;
  679. }
  680. }
  681. if (false === $allow_deposit)
  682. return $this->fail("提现日期为: {$c}日,其他时间无法发起提现!");
  683. if ($platform == \E_ORDER_PAY_TYPE::Wechat) {
  684. if (!$massager || null == $massager["applet_openid"])
  685. return $this->fail("未绑定微信,无法发起提现!", 10001);
  686. } else if ($platform == \E_ORDER_PAY_TYPE::Bank) {
  687. if (mb_strlen($massager["opening_bank_name"] ?? '') == 0
  688. || mb_strlen($massager["bank_real_name"] ?? '') == 0
  689. || mb_strlen($massager["bank_no"] ?? '') == 0
  690. )
  691. return $this->fail("未绑定银行卡信息,无法发起提现", 10002);
  692. }
  693. $w = $this->mWalletModel->getWallet($m_id);
  694. $deposit_min_amount = config("site.deposit_min_amount");
  695. $massager_reserve_funds_amount = config("site.massager_reserve_funds_amount");
  696. // 预留金
  697. if (($w->profit_amount - $massager_reserve_funds_amount) < $amount)
  698. return $this->fail("余额不足,包含平台预留金 {$massager_reserve_funds_amount} 无法提现");
  699. if ($amount < $deposit_min_amount)
  700. return $this->fail("提现最小金额为:{$deposit_min_amount}");
  701. $record = (new Record())->where([
  702. "apply_status" => \E_BASE_STATUS::Default,
  703. "deposit_status" => \E_BASE_STATUS::Default,
  704. "identity_type" => \E_IDENTITY_TYPE::Massager,
  705. "massager_id" => $m_id
  706. ])->find();
  707. if ($record) {
  708. return $this->fail("您上一笔提现未通过审核,等待上一笔提现后再次发起");
  709. }
  710. (new Record())->save([
  711. "no" => "TXM" . $m_id . time(),
  712. "platform" => $platform,
  713. "identity_type" => \E_IDENTITY_TYPE::Massager,
  714. "massager_id" => $m_id,
  715. "city_code" => $massager["city_code"],
  716. "deposit_amount" => $amount,
  717. "service_charge_rate" => config("site.service_charge_rate"),
  718. "apply_status" => \E_BASE_STATUS::Default,
  719. "deposit_status" => \E_BASE_STATUS::Default,
  720. "operation_id" => $m_id,
  721. "createtime" => time(),
  722. "updatetime" => time(),
  723. "opening_bank_name" => $platform == \E_ORDER_PAY_TYPE::Bank ? $massager["opening_bank_name"] : null,
  724. "bank_real_name" => $platform == \E_ORDER_PAY_TYPE::Bank ? $massager["bank_real_name"] : null,
  725. "bank_no" => $platform == \E_ORDER_PAY_TYPE::Bank ? $massager["bank_no"] : null,
  726. ]);
  727. return $this->ok(true, "申请提现成功,请耐心等待管理员审核!");
  728. }
  729. public function fetchSystemMessage($m_id, $page, $size)
  730. {
  731. $messageModel = new Message();
  732. $paginate = $messageModel->fetchMassagerSystemMessage($m_id, $page, $size);
  733. $messageModel->update(["is_read" => 1], [
  734. "to_massager_id" => $m_id,
  735. "is_read" => 0,
  736. "identity_type" => \E_IDENTITY_TYPE::Massager
  737. ]);
  738. return [
  739. $paginate->items(),
  740. $paginate->total()
  741. ];
  742. }
  743. public function getUnreadMessageCount($m_id)
  744. {
  745. $messageModel = new Message();
  746. return $messageModel->getUnreadMessageCount($m_id);
  747. }
  748. public function resetPassword($mobile, $sms_code, $new_pwd)
  749. {
  750. $m = $this->model->where("mobile", $mobile)->find();
  751. if (!$m)
  752. return $this->fail("账号不存在!");
  753. $check = \app\common\library\Sms::check($mobile, $sms_code, "massager_reset_pwd");
  754. if (!$check)
  755. return $this->fail("短信验证码不正确!");
  756. $this->model->update(
  757. [
  758. "password" => md5($new_pwd),
  759. "session_token" => md5('r' . $mobile . $sms_code . $new_pwd . time())
  760. ],
  761. ["id" => $m["id"]]
  762. );
  763. return $this->ok(true);
  764. }
  765. public function fetchDiffAmountDetailsByYm($m_id, $city_code, $year, $month)
  766. {
  767. $massager = $this->model->findById($m_id);
  768. if (!$massager)
  769. return $this->fail("助教不存在!");
  770. $monthOrders = $this->orderModel->monthFinishOrdersByYm($m_id, $city_code, $year, $month);
  771. // 当前比例
  772. $current_rate = (new MassagerService())->getProfitRate($m_id, $city_code, $year, $month);
  773. $diff_total_amount = 0;
  774. $fmt_orders = [];
  775. foreach ($monthOrders as $order) {
  776. if (isset($order["bill"]) && $order["bill"]["rate"] > 0) {
  777. $diff_rate = $current_rate - $order["bill"]["rate"];
  778. if ($diff_rate > 0) {
  779. $diff_now_amount = fixed2Float(($order["total_real_amount"] - $order["trip_amount"]) * ($diff_rate / 100));
  780. $diff_total_amount += $diff_now_amount;
  781. $order["bill"]["diff_amount"] = $diff_now_amount;
  782. $order["bill"]["diff_rate"] = $diff_rate;
  783. array_push($fmt_orders, $order);
  784. }
  785. }
  786. }
  787. return $this->ok([
  788. "current_rate" => $current_rate,
  789. "diff_total_amount" => fixed2Float($diff_total_amount),
  790. "month_orders" => $fmt_orders
  791. ]);
  792. }
  793. public function closingOrderPerformanceByYm($m_id)
  794. {
  795. $y = (int)date("Y");
  796. $m = (int)date("m");
  797. $last_day = (int)date("t");
  798. $now_day = (int)date("d");
  799. $switch = config("site.closing_performance_switch");
  800. if (0 == $switch) {
  801. return $this->fail("结算业绩功能暂未开启!");
  802. }
  803. $massager = $this->model->findById($m_id);
  804. if (!$massager)
  805. return $this->fail("助教不存在!");
  806. if ($last_day - $now_day > 6)
  807. return $this->fail("必须在当月的最后七天结算,并且一月只能提交一次!");
  808. $record = $this->closingModel->findByMIdAndYm($m_id, $massager["city_code"], $y, $m);
  809. if ($record) {
  810. return $this->fail("当前区域当月已经申请,请勿重复申请!");
  811. }
  812. $s_result = $this->fetchDiffAmountDetailsByYm($m_id, $massager["city_code"], $y, $m);
  813. if (!$s_result->code())
  814. return $s_result;
  815. $result_data = $s_result->data();
  816. if ($result_data["diff_total_amount"] == 0)
  817. return $this->fail("您当前可结算的金额为0,不能发起审批!");
  818. $this->closingModel->save([
  819. "massager_id" => $massager["id"],
  820. "city_code" => $massager["city_code"],
  821. "year" => $y,
  822. "month" => $m,
  823. "closing_amount" => 0,
  824. "status" => \E_BASE_STATUS::Checking,
  825. "createtime" => time(),
  826. "updatetime" => time()
  827. ]);
  828. return $this->ok(true);
  829. }
  830. public function fetchClosingOrderPerformance($m_id, $page = 1, $size = 10)
  831. {
  832. $paginate = $this->closingModel->fetchByMassasger($m_id, $page, $size);
  833. return [
  834. $paginate->items(),
  835. $paginate->total()
  836. ];
  837. }
  838. public function fetchInteriorScoreDetails($m_id, $year, $month)
  839. {
  840. return (new MassagerService())->updateInteriorScore($m_id, $year, $month);
  841. }
  842. public function uploadContract($m_id, $contract_file)
  843. {
  844. $this->model->update([
  845. "contract_file" => $contract_file,
  846. ], ["id" => $m_id]);
  847. return true;
  848. }
  849. /**
  850. * 发布动态
  851. * @param $m_id
  852. * @param array $params
  853. * @return \SResult
  854. * @throws \think\db\exception\DataNotFoundException
  855. * @throws \think\db\exception\ModelNotFoundException
  856. * @throws \think\exception\DbException
  857. */
  858. public function publishDynamic($m_id, array $params)
  859. {
  860. $massager = $this->model->findById($m_id);
  861. if (!$massager)
  862. return $this->fail("助教不存在!");
  863. $switch = config("site.dynamic_publish_check_switch");
  864. $res = (new Dynamic())->save([
  865. "type" => $params["type"],
  866. "massager_id" => $m_id,
  867. "topic_id" => isset($params["topic_id"]) && $params["topic_id"] > 0 ? $params["topic_id"] : null,
  868. "description" => $params["description"],
  869. "attachment_files" => $params["attachment_files"],
  870. "address" => $params["address"],
  871. "city_code" => $params["city_code"],
  872. "lng" => $params["lng"],
  873. "lat" => $params["lat"],
  874. "status" => 1 == $switch ? \E_BASE_STATUS::Checking : \E_BASE_STATUS::Normal,
  875. "createtime" => time(),
  876. "updatetime" => time()
  877. ]);
  878. return $this->ok($res);
  879. }
  880. public function appeal($m_id, $order_id, $appeal_reason)
  881. {
  882. $order = $this->orderModel->get($order_id);
  883. if (!$order)
  884. return $this->fail("订单不存在!");
  885. if ($m_id != $order["massager_id"])
  886. return $this->fail("无权限申诉!");
  887. if (!in_array($order["status"], [\E_ORDER_STATUS::Proceed, \E_ORDER_STATUS::WaitFeedback]))
  888. return $this->fail("订单状态为进行中或者等待评价才能申诉订单!");
  889. if (1 == $order["is_appeal"])
  890. return $this->fail("订单正在申述中,请等待后台管理员处理~");
  891. $this->model->update([
  892. "is_appeal" => 1,
  893. "appeal_reason" => $appeal_reason
  894. ], ["id" => $order_id]);
  895. return $this->ok(true);
  896. }
  897. public function setNoWorkPeriod($m_id, $range)
  898. {
  899. $combine = explode("|", $range);
  900. $res = [];
  901. foreach ($combine as $item) {
  902. $item_range = explode(",", $item);
  903. if ($item_range[0] < time() || $item_range[1] < $item_range[0])
  904. return $this->fail("设置时间错误");
  905. array_push($res, [
  906. "massager_id" => $m_id,
  907. "start_time" => $item_range[0],
  908. "end_time" => $item_range[1]
  909. ]);
  910. }
  911. if (count($res) > 0)
  912. (new WorkPeriod())->saveAll($res);
  913. return $this->ok(true);
  914. }
  915. public function fetchNoWorkPeriod($m_id)
  916. {
  917. return (new WorkPeriod())->where("massager_id", $m_id)->where("end_time", ">", time())->select();
  918. }
  919. public function delNoWorkPeriod($id)
  920. {
  921. (new WorkPeriod())->where("id", $id)->delete();
  922. return true;
  923. }
  924. }