CustomClass.php 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290
  1. <?php
  2. namespace bizGhs\custom\classes;
  3. use biz\ghs\classes\GhsClass;
  4. use biz\sj\classes\SjClass;
  5. use bizGhs\admin\classes\AdminClass;
  6. use bizGhs\book\classes\BookCustomClass;
  7. use bizGhs\book\classes\BookItemCustomClass;
  8. use bizGhs\custom\models\Custom;
  9. use bizGhs\ghs\classes\GhsBalanceChangeClass;
  10. use bizGhs\shop\classes\MainClass;
  11. use bizGhs\shop\classes\ShopMoneyClass;
  12. use bizGhs\shop\classes\TotalDebtChangeClass;
  13. use bizGhs\ghs\classes\GhsBalanceClass;
  14. use bizGhs\ghs\classes\GhsRechargeClass;
  15. use bizGhs\order\classes\OrderClearClass;
  16. use bizGhs\shop\classes\ShopClass;
  17. use bizHd\member\classes\MemberLevelClass;
  18. use bizHd\saas\classes\ApplyClass;
  19. use bizHd\saas\services\ApplyService;
  20. use common\components\dict;
  21. use common\components\imgUtil;
  22. use common\components\noticeUtil;
  23. use common\components\stringUtil;
  24. use common\components\util;
  25. use common\components\orderSn;
  26. use bizHd\base\classes\BaseClass;
  27. use Yii;
  28. class CustomClass extends BaseClass
  29. {
  30. public static $baseFile = '\bizGhs\custom\models\Custom';
  31. const IS_DEBT_NO = 0;
  32. const IS_DEBT_YES = 1;
  33. const NOT_BLACK = 1;
  34. const IS_BLACK = 2;
  35. const LEVEL_SK = 0; //散客
  36. const LEVEL_PT = 1; //花店
  37. const LEVEL_HJ = 2; //同行
  38. const LEVEL_ZS = 3; //金店
  39. public static $levelMap = [
  40. self::LEVEL_SK => '散客',
  41. self::LEVEL_PT => '花店',
  42. self::LEVEL_HJ => '同行',
  43. self::LEVEL_ZS => '金店',
  44. ];
  45. public static $nickNameMap = [
  46. self::LEVEL_SK => '零售',
  47. self::LEVEL_PT => '批发',
  48. self::LEVEL_HJ => '同行',
  49. self::LEVEL_ZS => '金店',
  50. ];
  51. public static $levelPriceKeyMap = [
  52. self::LEVEL_SK => 'skPrice',
  53. self::LEVEL_PT => 'price',
  54. self::LEVEL_HJ => 'hjPrice',
  55. self::LEVEL_ZS => 'zsPrice',
  56. ];
  57. public static $levelAddPriceKeyMap = [
  58. self::LEVEL_SK => 'skMore',
  59. self::LEVEL_PT => 'addPrice',
  60. self::LEVEL_HJ => 'hjAddPrice',
  61. self::LEVEL_ZS => 'zsAddPrice',
  62. ];
  63. public static function pullOtherShopCustom($data)
  64. {
  65. $connection = Yii::$app->db;
  66. $transaction = $connection->beginTransaction();
  67. try {
  68. $toShopId = $data['toShopId'] ?? 0;
  69. $fromShopId = $data['fromShopId'] ?? 0;
  70. //指定当前环境为批发商,重要!!!
  71. Yii::$app->params['ptStyle'] = dict::getDict('ptStyle', 'ghs');
  72. $fromCustomList = CustomClass::getAllByCondition(['ownShopId' => $fromShopId], null, '*');
  73. if (!empty($fromCustomList)) {
  74. foreach ($fromCustomList as $fromCustomer) {
  75. $exist = CustomClass::exists(['ownShopId' => $toShopId, 'shopId' => $fromCustomer['shopId']]);
  76. if (!$exist) {
  77. CustomClass::build($toShopId, $fromCustomer['shopId'], $fromCustomer['name']);
  78. }
  79. }
  80. }
  81. $transaction->commit();
  82. return true;
  83. } catch (\Exception $exception) {
  84. $transaction->rollBack();
  85. noticeUtil::push("批量拉取客户时报错了,fromShopId:{$fromShopId} toShopId:{$toShopId},报错内容:" . $exception->getMessage(), '15280215347');
  86. }
  87. return true;
  88. }
  89. public static function generateCustom($data)
  90. {
  91. $connection = Yii::$app->db;
  92. $transaction = $connection->beginTransaction();
  93. try {
  94. // 组织表单数据
  95. $shopName = $data['name'] ?? '';
  96. $mobile = $data['mobile'] ?? '';
  97. $post = [];
  98. $post['introSjId'] = $data['sjId'] ?? '';
  99. $post['introShopId'] = $data['shopId'] ?? '';
  100. $post['introSjName'] = $data['sjName'] ?? '';
  101. $post['introStyle'] = SjClass::STYLE_SUPPLIER;
  102. $post['name'] = $shopName;
  103. if (empty($shopName)) {
  104. noticeUtil::push("花店 {$shopName} 手机号 {$mobile} 添加失败,名称没有填写", '15280215347');
  105. $transaction->rollBack();
  106. return true;
  107. }
  108. $post['mobile'] = $mobile;
  109. if (!stringUtil::isMobile($mobile)) {
  110. noticeUtil::push("花店 {$shopName} 手机号 {$mobile} 添加失败,手机号填写错误", '15280215347');
  111. $transaction->rollBack();
  112. return true;
  113. }
  114. if (stringUtil::getWordNum($shopName) > 15) {
  115. noticeUtil::push("花店 {$shopName} 手机号 {$mobile} 添加失败,名称超过了15个汉字", '15280215347');
  116. $transaction->rollBack();
  117. return true;
  118. }
  119. $has = ApplyClass::getByCondition(['mobile' => $mobile]);
  120. if (!empty($has)) {
  121. noticeUtil::push("花店 {$shopName} 手机号 {$mobile} 添加失败,手机号已经存在了哦", '15280215347');
  122. $transaction->rollBack();
  123. return true;
  124. }
  125. $hasShop = \biz\shop\classes\ShopClass::getByCondition(['mobile' => $mobile]);
  126. if (!empty($hasShop)) {
  127. noticeUtil::push("花店 {$shopName} 手机号 {$mobile} 添加失败,手机号已经存在了", '15280215347');
  128. $transaction->rollBack();
  129. return true;
  130. }
  131. $adminName = $post['adminName'] ?? '';
  132. $miniOpenId = $post['miniOpenId'] ?? '';
  133. $adminInfo = ['name' => $adminName, 'mobile' => $mobile, 'miniOpenId' => $miniOpenId];
  134. $fromApp = dict::getDict('userSourceGetId', 'app', 'id');
  135. $admin = AdminClass::replaceAdmin($adminInfo, $fromApp);
  136. $adminId = $admin['id'] ?? 0;
  137. $post['adminId'] = $adminId;
  138. $post['adminName'] = $admin['name'] ?? '';
  139. $post['long'] = isset($post['longitude']) ? $post['longitude'] : '';
  140. $post['lat'] = isset($post['latitude']) ? $post['latitude'] : '';
  141. $post['from'] = ApplyClass::FROM_RETAIL;
  142. $post['style'] = SjClass::STYLE_RETAIL;
  143. //增加或更新申请
  144. $respond = ApplyService::replaceRetail($post);
  145. $id = $respond['id'] ?? 0;
  146. //后面的代码,要用到此参数,重要
  147. Yii::$app->params['ptStyle'] = 2;
  148. ApplyService::pass($id, '批发商手动添加');
  149. $transaction->commit();
  150. //只要手动添加的都标记为花店,任何情况都不会标记为散客,任何情况都是审核通过的状态
  151. $customList = CustomClass::getAllByCondition(['mobile' => $mobile], null, '*', null, true);
  152. if (!empty($customList)) {
  153. foreach ($customList as $custom) {
  154. $custom->isHd = 1;
  155. $custom->passStatus = 1;
  156. $custom->save();
  157. $ghsId = $custom->ghsId;
  158. GhsClass::updateById($ghsId, ['passStatus' => 1]);
  159. }
  160. }
  161. //noticeUtil::push("花店 {$shopName} 手机号 {$mobile} 由批发商添加成功");
  162. return true;
  163. } catch (\Exception $exception) {
  164. $transaction->rollBack();
  165. noticeUtil::push("花店 {$shopName} 手机号 {$mobile} 添加失败,原因:" . $exception->getMessage(), '15280215347');
  166. }
  167. return true;
  168. }
  169. //预订相关表同步更新货位 ssh 20240729
  170. public static function syncBookSeat($shop, $custom, $seatSn)
  171. {
  172. $bookSn = $shop->bookSn ?? 0;
  173. if (empty($bookSn)) {
  174. return true;
  175. }
  176. $customId = $custom->id ?? 0;
  177. BookItemCustomClass::updateByCondition(['bookSn' => $bookSn, 'customId' => $customId], ['seatSn' => $seatSn]);
  178. BookCustomClass::updateByCondition(['bookSn' => $bookSn, 'customId' => $customId], ['seatSn' => $seatSn]);
  179. }
  180. /**
  181. * 用账面正余额支付挂账:扣减净 balance 并记「结账」流水。
  182. * 来款充值后的自动销单不要调本方法(对照 hd:来款已入账,销单只改订单)。
  183. * 调用方:GhsRechargeSettleService::consumePositiveBalanceFifo。
  184. */
  185. public static function clearConsumeBalance($amount, $custom, $ghs, $shop, $staff, $clear, $options = [])
  186. {
  187. $skipBalanceChangeRecord = !empty($options['skipBalanceChangeRecord']);
  188. // 先合并历史挂账到 balance,再扣减(只记余额变动)
  189. AccountMoneyClass::ensureCustomMoneyReady($custom, true);
  190. AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
  191. $customId = $custom->id ?? 0;
  192. $customName = $custom->name ?? '';
  193. $ghsId = $ghs->id ?? 0;
  194. $relateId = $clear->id ?? 0;
  195. $staffId = $staff->id ?? 0;
  196. $staffName = $staff->name ?? '';
  197. $clearSn = $clear->orderSn;
  198. $mainId = $shop->mainId ?? 0;
  199. $shopId = $shop->id ?? 0;
  200. $sjId = $shop->sjId ?? 0;
  201. $amount = bcadd((string)$amount, '0', 2);
  202. if (bccomp($amount, '0', 2) <= 0) {
  203. util::fail('销账扣款金额须大于0');
  204. }
  205. $newGhsBalance = bcsub((string)($ghs->balance ?? '0'), $amount, 2);
  206. $newCustomBalance = bcsub((string)($custom->balance ?? '0'), $amount, 2);
  207. // 合并后净余额可为负(待结),勿再因扣款后 <0 报错;金额由 CustomPaymentAllocateService 按来款池控制
  208. if (bccomp($newGhsBalance, $newCustomBalance, 2) !== 0) {
  209. util::fail('客户与供货商余额不一致,无法结账,请联系管理员');
  210. }
  211. $ghs->balance = $newGhsBalance;
  212. $ghs->save();
  213. $custom->balance = $newCustomBalance;
  214. $custom->save();
  215. // 充值销账:只记一条充值流水(附 clearAmount),不另记「结账 -X」行(对照 hd settleAmount)
  216. if ($skipBalanceChangeRecord) {
  217. return;
  218. }
  219. $capitalType = dict::getDict('capitalType', 'ghsHelpCustomUseBalanceClear', 'id');
  220. $fromType = dict::getDict('fromType', 'shop');
  221. $cbData = [
  222. 'customId' => $customId,
  223. 'customName' => $customName,
  224. 'relateId' => $relateId,
  225. 'onlinePay' => 1,
  226. 'ptStyle' => 2,
  227. 'capitalType' => $capitalType,
  228. 'amount' => $amount,
  229. 'balance' => $newCustomBalance,
  230. 'staffId' => $staffId,
  231. 'staffName' => $staffName,
  232. 'io' => 0,
  233. 'side' => 0,
  234. 'payWay' => 0,
  235. 'fromType' => $fromType,
  236. 'event' => '结账 ' . $clearSn,
  237. 'mainId' => $mainId,
  238. 'shopId' => $shopId,
  239. 'sjId' => $sjId,
  240. 'remark' => '',
  241. ];
  242. $cbc = CustomBalanceChangeClass::add($cbData, true);
  243. $customShopId = $custom->shopId ?? 0;
  244. $customShop = ShopClass::getById($customShopId, true);
  245. if (empty($customShop)) {
  246. util::fail('没有找到客户门店呢..');
  247. }
  248. $customShopSjId = $customShop->sjId ?? 0;
  249. $customShopMainId = $customShop->mainId ?? 0;
  250. $capitalType = dict::getDict('capitalType', 'customAskGhsUseBalanceClear', 'id');
  251. $gbData = [
  252. 'ghsId' => $ghsId,
  253. 'relateId' => $relateId,
  254. 'ptStyle' => 2,
  255. 'capitalType' => $capitalType,
  256. 'amount' => $amount,
  257. 'balance' => $newGhsBalance,
  258. 'io' => 0,
  259. 'side' => 0,
  260. 'onlinePay' => 1,
  261. 'payWay' => 0,
  262. 'fromType' => $fromType,
  263. 'event' => '结账 ' . $clearSn,
  264. 'sjId' => $customShopSjId,
  265. 'mainId' => $customShopMainId,
  266. 'shopId' => $customShopId,
  267. 'remark' => '',
  268. ];
  269. $gbc = GhsBalanceChangeClass::add($gbData, true);
  270. $clear->customBalanceChangeId = $cbc->id ?? 0;
  271. $clear->ghsBalanceChangeId = $gbc->id ?? 0;
  272. $clear->save();
  273. }
  274. /** 供货商帮充与花店线上充:成对充值单互相关联,供余额明细展示结账单 */
  275. protected static function linkCustomAndGhsRecharge($customRecharge, $ghsRecharge)
  276. {
  277. if (empty($customRecharge) || empty($ghsRecharge)) {
  278. return;
  279. }
  280. $customRechargeId = intval(is_object($customRecharge) ? ($customRecharge->id ?? 0) : 0);
  281. $ghsRechargeId = intval(is_object($ghsRecharge) ? ($ghsRecharge->id ?? 0) : 0);
  282. if ($customRechargeId <= 0 || $ghsRechargeId <= 0) {
  283. return;
  284. }
  285. $cProbe = new \bizGhs\custom\models\CustomRecharge();
  286. if (method_exists($cProbe, 'hasAttribute') && $cProbe->hasAttribute('ghsRechargeId')) {
  287. $customRecharge->ghsRechargeId = $ghsRechargeId;
  288. $customRecharge->save(false, ['ghsRechargeId']);
  289. }
  290. $gProbe = new \bizGhs\ghs\models\GhsRecharge();
  291. if (method_exists($gProbe, 'hasAttribute') && $gProbe->hasAttribute('customRechargeId')) {
  292. $ghsRecharge->customRechargeId = $customRechargeId;
  293. $ghsRecharge->save(false, ['customRechargeId']);
  294. }
  295. }
  296. // 充值/返充(增加净 balance);有多个地方要同步修改,请搜索关键词 custom_ghs_recharge ssh 20240310
  297. public static function rechargeBalance($custom, $amount, $shop, $staff, $payWay, $params = [])
  298. {
  299. // 充值前合并;之后对 balance 做 bcadd(只记余额变动)
  300. AccountMoneyClass::ensureCustomMoneyReady($custom, true);
  301. $ghsId = $custom->ghsId ?? 0;
  302. $ghsInfo = GhsClass::getLockById($ghsId);
  303. AccountMoneyClass::ensureGhsMoneyReady($ghsInfo, true);
  304. if (empty($ghsInfo)) {
  305. util::fail('没有找到供货商');
  306. }
  307. $ghsShopId = $ghsInfo->shopId ?? 0;
  308. $ghsName = $ghsInfo->name ?? '';
  309. $customId = $custom->id ?? 0;
  310. $customShopId = $custom->shopId ?? 0;
  311. $customName = $custom->name ?? '';
  312. $customShop = ShopClass::getById($customShopId, true);
  313. if (empty($customShop)) {
  314. util::fail('没有找到客户门店');
  315. }
  316. $payTime = date("Y-m-d H:i:s");
  317. $customShopSjId = $customShop->sjId ?? 0;
  318. $customShopMainId = $customShop->mainId ?? 0;
  319. $custom->balance = bcadd($custom->balance, $amount, 2);
  320. $custom->save();
  321. $orderSn = orderSn::getGhsCustomRechargeSn();
  322. $shopId = $shop->id ?? 0;
  323. $sjId = $shop->sjId ?? 0;
  324. $mainId = $shop->mainId ?? 0;
  325. $staffId = $staff->id ?? 0;
  326. $staffName = $staff->name ?? '';
  327. $remark = $params['remark'] ?? '';
  328. $rechargeType = $params['rechargeType'] ?? 0;
  329. $payMap = dict::getDict('payWayName');
  330. $payName = $payMap[$payWay] ?? '';
  331. $rechargeEvent = $payName . '充值';
  332. if ($rechargeType == 1) {
  333. $rechargeEvent = '售后返充';
  334. }
  335. $cData = [
  336. 'orderSn' => $orderSn,
  337. 'onlinePay' => 1,
  338. 'payWay' => $payWay,
  339. 'shopId' => $shopId,
  340. 'mainId' => $mainId,
  341. 'amount' => $amount,
  342. 'balance' => $custom->balance,
  343. 'side' => 0,
  344. 'staffId' => $staffId,
  345. 'staffName' => $staffName,
  346. 'payStatus' => 1,
  347. 'status' => 1,
  348. 'ghsId' => $ghsId,
  349. 'ghsShopId' => $ghsShopId,
  350. 'ghsName' => $ghsName,
  351. 'customId' => $customId,
  352. 'customShopId' => $customShopId,
  353. 'customName' => $customName,
  354. 'remark' => $remark,
  355. 'payTime' => $payTime,
  356. 'rechargeType' => $rechargeType,
  357. ];
  358. if (!empty($params['clearAudit']) && is_array($params['clearAudit'])) {
  359. $cData = CustomBalanceChangeClass::mergeClearAuditIntoRechargeData($cData, $params['clearAudit']);
  360. }
  361. $cRecharge = CustomRechargeClass::add($cData, true);
  362. $cRechargeId = $cRecharge->id ?? 0;
  363. $capitalType = dict::getDict('capitalType', 'ghsHelpCustomRecharge', 'id');
  364. if ($rechargeType == 1) {
  365. //售后返充
  366. $capitalType = dict::getDict('capitalType', 'ghsHelpCustomRechargeReturn', 'id');
  367. }
  368. $fromType = dict::getDict('fromType', 'shop');
  369. $cbData = [
  370. 'customId' => $customId,
  371. 'customName' => $customName,
  372. 'relateId' => $cRechargeId,
  373. 'onlinePay' => 1,
  374. 'ptStyle' => 2,
  375. 'capitalType' => $capitalType,
  376. 'amount' => $amount,
  377. 'balance' => $custom->balance,
  378. 'staffId' => $staffId,
  379. 'staffName' => $staffName,
  380. 'io' => 1,
  381. 'side' => 0,
  382. 'payWay' => $payWay,
  383. 'fromType' => $fromType,
  384. 'event' => $rechargeEvent,
  385. 'mainId' => $mainId,
  386. 'shopId' => $shopId,
  387. 'sjId' => $sjId,
  388. 'remark' => $remark,
  389. ];
  390. if (!empty($params['clearAudit']) && is_array($params['clearAudit'])) {
  391. $cbData = CustomBalanceChangeClass::mergeClearAuditIntoRowData($cbData, $params['clearAudit']);
  392. }
  393. CustomBalanceChangeClass::add($cbData, true);
  394. $ghsInfo->balance = bcadd($ghsInfo->balance, $amount, 2);
  395. $ghsInfo->save();
  396. $orderSn = orderSn::getGhsRechargeSn();
  397. $customMainId = $custom->mainId ?? 0;
  398. $gData = [
  399. 'orderSn' => $orderSn,
  400. 'onlinePay' => 1,
  401. 'payWay' => $payWay,
  402. 'shopId' => $customShopId,
  403. 'mainId' => $customMainId,
  404. 'amount' => $amount,
  405. 'balance' => $ghsInfo->balance,
  406. 'side' => 0,
  407. 'staffId' => 0,
  408. 'staffName' => '',
  409. 'payStatus' => 1,
  410. 'status' => 1,
  411. 'ghsId' => $ghsId,
  412. 'ghsShopId' => $ghsShopId,
  413. 'ghsName' => $ghsName,
  414. 'customId' => $customId,
  415. 'customShopId' => $customShopId,
  416. 'customName' => $customName,
  417. 'remark' => $remark,
  418. 'payTime' => $payTime,
  419. 'rechargeType' => $rechargeType,
  420. ];
  421. $gRecharge = GhsRechargeClass::add($gData, true);
  422. $gRechargeId = $gRecharge->id ?? 0;
  423. self::linkCustomAndGhsRecharge($cRecharge, $gRecharge);
  424. $capitalType = dict::getDict('capitalType', 'customAskGhsRecharge', 'id');
  425. if ($rechargeType == 1) {
  426. //售后返充
  427. $capitalType = dict::getDict('capitalType', 'customAskGhsRechargeReturn', 'id');
  428. }
  429. $gbData = [
  430. 'ghsId' => $ghsId,
  431. 'ghsName' => $ghsName,
  432. 'relateId' => $gRechargeId,
  433. 'ptStyle' => 2,
  434. 'capitalType' => $capitalType,
  435. 'amount' => $amount,
  436. 'balance' => $ghsInfo->balance,
  437. 'io' => 1,
  438. 'side' => 0,
  439. 'onlinePay' => 1,
  440. 'payWay' => $payWay,
  441. 'fromType' => $fromType,
  442. 'event' => $rechargeEvent,
  443. 'sjId' => $customShopSjId,
  444. 'mainId' => $customShopMainId,
  445. 'shopId' => $customShopId,
  446. 'remark' => $remark,
  447. ];
  448. GhsBalanceChangeClass::add($gbData, true);
  449. // 现金充值,同步更新表 xhMain 的 money 字段
  450. if ($payWay == 4) {
  451. $m = \bizGhs\shop\classes\MainClass::getById($mainId, true, 'id, money');
  452. $balance = $m->money;
  453. $m->money = bcadd($m->money, $amount);
  454. $m->save();
  455. $event = '客户(' . $customName . ')充值' . $amount . '元';
  456. $data = [
  457. 'amount' => $amount,
  458. 'balance' => $balance,
  459. 'io' => 1,
  460. 'mainId' => $mainId,
  461. 'capitalType' => $capitalType,
  462. 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
  463. 'event' => $event,
  464. 'remark' => $remark,
  465. ];
  466. ShopMoneyClass::addData($data);
  467. }
  468. return ['custom' => $custom, 'ghs' => $ghsInfo, 'customRecharge' => $cRecharge, 'ghsRecharge' => $gRecharge];
  469. }
  470. public static function createSeatSn($mainId)
  471. {
  472. $max = Custom::find(['mainId' => $mainId])->max('seatSn');
  473. $new = bcadd($max, 1);
  474. return $new;
  475. }
  476. //建立客户和供货商关系
  477. public static function build($ghsShopId, $hdShopId, $changeName = '')
  478. {
  479. return GhsClass::build($ghsShopId, $hdShopId, 2, $changeName);
  480. }
  481. //添加客户 ssh 2021.2.24
  482. public static function addCustom($data)
  483. {
  484. return self::add($data);
  485. }
  486. //获取客户信息 ssh 2021.2.4
  487. public static function getCustom($id)
  488. {
  489. $info = self::getById($id);
  490. if (empty($info)) {
  491. return $info;
  492. }
  493. $respond = self::groupBaseInfo([$info]);
  494. return current($respond);
  495. }
  496. public static function getCustomByIds($ids)
  497. {
  498. $list = self::getByIds($ids, null, 'id');
  499. return self::groupBaseInfo($list);
  500. }
  501. //整合头像等信息 ssh 2021.1.8
  502. public static function groupBaseInfo($list, $mainId = 0)
  503. {
  504. if (empty($list)) {
  505. return $list;
  506. }
  507. //片区划分
  508. $distMap = [];
  509. $custom = current($list);
  510. if (!empty($custom) && !empty($custom['ownMainId'])) {
  511. $distMap = DistClass::getAllByCondition(['mainId' => $custom['ownMainId']], null, '*', 'id');
  512. }
  513. $levelMap = self::$levelMap;
  514. foreach ($list as $key => $val) {
  515. $smallAvatar = imgUtil::getPrefix() . (!empty($val['avatar']) ? $val['avatar'] : '/hhb_small.png') . '?x-oss-process=image/resize,m_fill,h_130,w_130';
  516. $avatar = imgUtil::getPrefix() . (!empty($val['avatar']) ? $val['avatar'] : '/hhb_small.png');
  517. $list[$key]['smallAvatar'] = $smallAvatar;
  518. $list[$key]['avatar'] = $avatar;
  519. $list[$key]['sn'] = $val['id'];
  520. $level = $val['level'] ?? 1;
  521. $levelName = $levelMap[$level] ?? '';
  522. $list[$key]['levelName'] = $levelName;
  523. // 按 appVersion 输出净 balance 或旧版待结+余额字段(合并仅由控制台脚本执行)
  524. $list[$key] = AccountMoneyClass::formatMoneyForClient($list[$key]);
  525. //前端使用,走播,预订客户添加新客户
  526. $list[$key]['zbNum'] = '';
  527. $list[$key]['zbPrice'] = '';
  528. //片区划分
  529. $distId = $val['distId'] ?? 0;
  530. $distInfo = $distMap[$distId] ?? [];
  531. $distName = $distInfo['name'] ?? '';
  532. //注意区别 dist 字段,dist字段是地图里的区
  533. $list[$key]['distName'] = $distName;
  534. //超时未下单
  535. $recentExpend = $val['recentExpend'] ?? '';
  536. $list[$key]['overTimeUnExpend'] = 0;
  537. if ($recentExpend == '0000-00-00 00:00:00') {
  538. $list[$key]['overTimeUnExpend'] = 10000;
  539. } else {
  540. $recentExpendTime = strtotime($recentExpend);
  541. $seven = bcmul(86400, 7);
  542. $sevenTime = bcadd($recentExpendTime, $seven);
  543. if ($sevenTime < time()) {
  544. $list[$key]['overTimeUnExpend'] = 7;
  545. }
  546. $month = bcmul(86400, 30);
  547. $monthTime = bcadd($recentExpendTime, $month);
  548. if ($monthTime < time()) {
  549. $list[$key]['overTimeUnExpend'] = 30;
  550. }
  551. $halfYear = bcmul(86400, 180);
  552. $halfYearTime = bcadd($recentExpendTime, $halfYear);
  553. if ($halfYearTime < time()) {
  554. $list[$key]['overTimeUnExpend'] = 180;
  555. }
  556. $year = bcmul(86400, 365);
  557. $yearTime = bcmul($recentExpendTime, $year);
  558. if ($yearTime < time()) {
  559. $list[$key]['overTimeUnExpend'] = 365;
  560. }
  561. }
  562. }
  563. return $list;
  564. }
  565. //欠款权限开关 ssh 2021.1.8
  566. public static function debt($custom, $debt)
  567. {
  568. $id = $custom['id'] ?? 0;
  569. self::updateById($id, ['debt' => $debt]);
  570. return true;
  571. }
  572. //采购查看权限的黑白名单设置 shizhongqi 2021.08.08
  573. public static function black($custom, $black)
  574. {
  575. $id = $custom['id'] ?? 0;
  576. self::updateById($id, ['black' => $black]);
  577. return true;
  578. }
  579. //权限判断 ssh 2021.1.8
  580. public static function valid($custom, $shopId)
  581. {
  582. if (empty($custom)) {
  583. util::fail('没有找到客户');
  584. }
  585. if ($custom['ownShopId'] != $shopId) {
  586. util::fail('您无法操作此客户');
  587. }
  588. }
  589. /**
  590. * 调用方已 lockAccountPair 时,校验 custom/ghs 净余额一致。
  591. */
  592. protected static function assertPairBalanceEqual($custom, $ghs)
  593. {
  594. if (empty($ghs)) {
  595. return;
  596. }
  597. $customBal = bcadd((string)($custom->balance ?? '0'), '0', 2);
  598. $ghsBal = bcadd((string)($ghs->balance ?? '0'), '0', 2);
  599. if (bccomp($customBal, $ghsBal, 2) !== 0) {
  600. util::fail('余额不一致,请联系管理员');
  601. }
  602. }
  603. /**
  604. * 开单扣减净 balance:写 custom(及成对 ghs),调用方须已 FOR UPDATE 锁行。
  605. */
  606. protected static function savePairBalanceAfterDeduct($custom, $ghs, $newBalance)
  607. {
  608. $newBalance = bcadd((string)$newBalance, '0', 2);
  609. $custom->balance = $newBalance;
  610. $custom->isDebt = bccomp($newBalance, '0', 2) < 0 ? CustomClass::IS_DEBT_YES : CustomClass::IS_DEBT_NO;
  611. $custom->save(false, ['balance', 'isDebt']);
  612. if (empty($ghs)) {
  613. return;
  614. }
  615. AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
  616. $ghs->balance = $newBalance;
  617. $ghs->debt = bccomp($newBalance, '0', 2) < 0 ? 2 : 1;
  618. $ghs->save(false, ['balance', 'debt']);
  619. self::assertPairBalanceEqual($custom, $ghs);
  620. }
  621. protected static function addGhsOrderBalanceChange($custom, $ghs, $order, $amount, $newBalance, $bookOrder = false)
  622. {
  623. if (empty($ghs)) {
  624. return;
  625. }
  626. $orderSn = $order->orderSn ?? '';
  627. $event = '购买花材,单号:' . $orderSn;
  628. if ($bookOrder) {
  629. $event = '预订单多退少补,单号:' . $orderSn;
  630. }
  631. $customShopId = $custom->shopId ?? 0;
  632. $customShop = ShopClass::getById($customShopId, true);
  633. $gbData = [
  634. 'ghsId' => $ghs->id ?? 0,
  635. 'relateId' => $order->id ?? 0,
  636. 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
  637. 'capitalType' => dict::getDict('capitalType', 'xhGhsOrder', 'id'),
  638. 'amount' => $amount,
  639. 'balance' => $newBalance,
  640. 'io' => 0,
  641. 'side' => 0,
  642. 'onlinePay' => 1,
  643. 'payWay' => $order->payWay ?? 0,
  644. 'fromType' => dict::getDict('fromType', 'shop'),
  645. 'event' => $event,
  646. 'sjId' => $customShop->sjId ?? ($custom->sjId ?? 0),
  647. 'mainId' => $customShop->mainId ?? 0,
  648. 'shopId' => $customShopId,
  649. 'remark' => '',
  650. ];
  651. GhsBalanceChangeClass::add($gbData, true);
  652. }
  653. /**
  654. * 充值退款:扣减成对客户/供货商净余额(调用方须已 lockAccountPair)。
  655. *
  656. * @return string 扣减后的净余额
  657. */
  658. public static function deductPairBalanceForRefund($custom, $ghs, $amount)
  659. {
  660. AccountMoneyClass::ensureCustomMoneyReady($custom, true);
  661. if (!empty($ghs)) {
  662. AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
  663. self::assertPairBalanceEqual($custom, $ghs);
  664. }
  665. $amount = bcadd((string)$amount, '0', 2);
  666. if (bccomp($amount, '0', 2) <= 0) {
  667. util::fail('退款金额有误');
  668. }
  669. $beforeBalance = bcadd((string)($custom->balance ?? '0'), '0', 2);
  670. if (bccomp($beforeBalance, $amount, 2) < 0) {
  671. util::fail('客户余额不足,本笔充值可能已用于销账或消费');
  672. }
  673. $newBalance = bcsub($beforeBalance, $amount, 2);
  674. self::savePairBalanceAfterDeduct($custom, $ghs, $newBalance);
  675. return $newBalance;
  676. }
  677. /**
  678. * 后台手动减少客户净余额(只减正余额部分,不增加待结)。
  679. * 调用方须已通过 lockAccountPair 锁定 custom/ghs。
  680. */
  681. public static function manualDeductBalance($shop, $custom, $ghs, $amount, $params = [])
  682. {
  683. if (empty($custom)) {
  684. util::fail('没有找到客户');
  685. }
  686. AccountMoneyClass::ensureCustomMoneyReady($custom, true);
  687. if (!empty($ghs)) {
  688. AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
  689. self::assertPairBalanceEqual($custom, $ghs);
  690. }
  691. $amount = bcadd((string)$amount, '0', 2);
  692. if (bccomp($amount, '0', 2) <= 0) {
  693. util::fail('金额要大于0');
  694. }
  695. $beforeBalance = bcadd((string)($custom->balance ?? '0'), '0', 2);
  696. if (bccomp($beforeBalance, '0', 2) <= 0) {
  697. util::fail('没有可减余额');
  698. }
  699. if (bccomp($beforeBalance, $amount, 2) < 0) {
  700. util::fail('余额不够扣');
  701. }
  702. $newBalance = bcsub($beforeBalance, $amount, 2);
  703. self::savePairBalanceAfterDeduct($custom, $ghs, $newBalance);
  704. $remark = $params['remark'] ?? '';
  705. $staffId = intval($params['staffId'] ?? 0);
  706. $staffName = $params['staffName'] ?? '';
  707. $mainId = $shop->mainId ?? 0;
  708. $shopId = $shop->id ?? 0;
  709. $sjId = $shop->sjId ?? 0;
  710. $customId = $custom->id ?? 0;
  711. $customName = $custom->name ?? '';
  712. $capitalType = dict::getDict('capitalType', 'deduct', 'id');
  713. $fromType = dict::getDict('fromType', 'shop');
  714. $event = '手动减少';
  715. CustomBalanceChangeClass::add([
  716. 'customId' => $customId,
  717. 'customName' => $customName,
  718. 'relateId' => 0,
  719. 'onlinePay' => 1,
  720. 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
  721. 'capitalType' => $capitalType,
  722. 'amount' => $amount,
  723. 'balance' => $newBalance,
  724. 'staffId' => $staffId,
  725. 'staffName' => $staffName,
  726. 'io' => 0,
  727. 'side' => 0,
  728. 'payWay' => 0,
  729. 'fromType' => $fromType,
  730. 'event' => $event,
  731. 'mainId' => $mainId,
  732. 'shopId' => $shopId,
  733. 'sjId' => $sjId,
  734. 'remark' => $remark,
  735. ], true);
  736. if (!empty($ghs)) {
  737. $customShopId = $custom->shopId ?? 0;
  738. $customShop = ShopClass::getById($customShopId, true);
  739. GhsBalanceChangeClass::add([
  740. 'ghsId' => $ghs->id ?? 0,
  741. 'relateId' => 0,
  742. 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
  743. 'capitalType' => $capitalType,
  744. 'amount' => $amount,
  745. 'balance' => $newBalance,
  746. 'io' => 0,
  747. 'side' => 0,
  748. 'onlinePay' => 1,
  749. 'payWay' => 0,
  750. 'fromType' => $fromType,
  751. 'event' => $event,
  752. 'sjId' => $customShop->sjId ?? 0,
  753. 'mainId' => $customShop->mainId ?? 0,
  754. 'shopId' => $customShopId,
  755. 'remark' => $remark,
  756. ], true);
  757. }
  758. }
  759. /**
  760. * 开单余额支付:扣减净 balance 并记购买流水(须传入 payAfter 已 lockAccountPair 的 custom/ghs)。
  761. */
  762. public static function payToChangeBalance($order, $custom, $ghs = null)
  763. {
  764. $actPrice = bcadd((string)($order->actPrice ?? '0'), '0', 2);
  765. if (bccomp($actPrice, '0', 2) <= 0) {
  766. return;
  767. }
  768. if (empty($custom)) {
  769. util::fail('没有找到客户');
  770. }
  771. AccountMoneyClass::ensureCustomMoneyReady($custom, true);
  772. if (!empty($ghs)) {
  773. AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
  774. self::assertPairBalanceEqual($custom, $ghs);
  775. }
  776. $beforeBalance = bcadd((string)($custom->balance ?? '0'), '0', 2);
  777. if (bccomp($beforeBalance, $actPrice, 2) < 0) {
  778. util::fail('余额不足');
  779. }
  780. $newBalance = bcsub($beforeBalance, $actPrice, 2);
  781. self::savePairBalanceAfterDeduct($custom, $ghs, $newBalance);
  782. $orderSn = $order->orderSn ?? '';
  783. $customId = $custom->id ?? 0;
  784. $capitalType = dict::getDict('capitalType', 'xhGhsOrder', 'id');
  785. $change = [
  786. 'relateId' => $order->id ?? 0,
  787. 'customId' => $customId,
  788. 'customName' => $custom->name ?? '',
  789. 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
  790. 'capitalType' => $capitalType,
  791. 'amount' => $actPrice,
  792. 'balance' => $newBalance,
  793. 'io' => 0,
  794. 'payWay' => dict::getDict('payWay', 'balancePay'),
  795. 'event' => '购买花材,单号:' . $orderSn,
  796. 'sjId' => $order->sjId ?? 0,
  797. 'shopId' => $order->shopId ?? 0,
  798. 'mainId' => $order->mainId ?? 0,
  799. 'staffId' => $order->shopAdminId ?? 0,
  800. 'staffName' => $order->shopAdminName ?? '',
  801. 'side' => 0,
  802. 'fromType' => dict::getDict('fromType', 'shop'),
  803. 'remark' => '',
  804. ];
  805. CustomBalanceChangeClass::add($change, true);
  806. self::addGhsOrderBalanceChange($custom, $ghs, $order, $actPrice, $newBalance, false);
  807. }
  808. /**
  809. * 挂账开单时若账户有正余额且不足本单:用余额先结本单一部分(只改 remainDebtPrice,不另扣 balance)。
  810. */
  811. protected static function inlineOrderBalancePartialClear($custom, $order, $clearAmount)
  812. {
  813. $clearAmount = bcadd((string)$clearAmount, '0', 2);
  814. if (bccomp($clearAmount, '0', 2) <= 0) {
  815. return;
  816. }
  817. $orderId = intval($order->id ?? 0);
  818. if ($orderId <= 0) {
  819. return;
  820. }
  821. $shopId = intval($order->shopId ?? 0);
  822. $shop = ShopClass::getById($shopId, true);
  823. if (empty($shop)) {
  824. util::fail('没有找到门店');
  825. }
  826. $staffId = intval($order->shopAdminId ?? 0);
  827. $staffName = $order->shopAdminName ?? '';
  828. $sjId = $shop->sjId ?? 0;
  829. $orderSn = $order->orderSn ?? '';
  830. OrderClearClass::expireAwaitPayClears(intval($custom->id ?? 0));
  831. $clear = OrderClearClass::clearWithAmountMap([
  832. 'customId' => $custom->id ?? 0,
  833. 'ghsShopAdminId' => $staffId,
  834. 'ghsShopId' => $shopId,
  835. 'ghsShopAdminName' => $staffName,
  836. 'modifyPrice' => $clearAmount,
  837. 'payWay' => dict::getDict('payWay', 'balancePay'),
  838. 'complete' => 0,
  839. 'remark' => '开单余额抵挂账',
  840. ], [
  841. ['orderId' => $orderId, 'clearAmount' => $clearAmount, 'orderSn' => $orderSn],
  842. ], $sjId, $shopId);
  843. OrderClearClass::applyNetBalanceClear($clear, dict::getDict('payWay', 'balancePay'), ['skipCashMoney' => true]);
  844. }
  845. /**
  846. * 挂账开单:增加客户待结(改造后 balance 减少,只记余额变动,不再记挂账变动)
  847. * ssh 20220306
  848. */
  849. public static function cgDebtAmountAdd($custom, $order, $bookOrder = false, $ghs = null)
  850. {
  851. // 挂账开单:合并后 balance 减少,不再写 CustomDebtChange
  852. AccountMoneyClass::ensureCustomMoneyReady($custom, true);
  853. if (!empty($ghs)) {
  854. AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
  855. self::assertPairBalanceEqual($custom, $ghs);
  856. }
  857. $amount = bcadd((string)($order->remainDebtPrice ?? '0'), '0', 2);
  858. if (bccomp($amount, '0', 2) <= 0) {
  859. return;
  860. }
  861. $beforeBalance = bcadd((string)($custom->balance ?? '0'), '0', 2);
  862. $positiveBalance = bccomp($beforeBalance, '0', 2) > 0 ? $beforeBalance : '0.00';
  863. if (bccomp($positiveBalance, $amount, 2) >= 0) {
  864. util::fail('余额充足,请用余额支付');
  865. }
  866. if (bccomp($positiveBalance, '0', 2) > 0) {
  867. self::inlineOrderBalancePartialClear($custom, $order, $positiveBalance);
  868. }
  869. $custom->isDebt = CustomClass::IS_DEBT_YES;
  870. $debtLimit = $custom->debtLimit ?? 0;
  871. if (!$bookOrder) {
  872. if (isset($order->shopAdminId) && $order->shopAdminId == 0) {
  873. $outstanding = AccountMoneyClass::getOutstandingDebt($custom);
  874. if (bccomp($outstanding, $debtLimit, 2) > 0) {
  875. if ($custom->live == 1) {
  876. util::fail("已欠款{$outstanding},请先结账哦");
  877. }
  878. }
  879. }
  880. }
  881. $newBalance = bcsub($beforeBalance, $amount, 2);
  882. $mustNotice = false;
  883. if (getenv('YII_ENV') == 'production') {
  884. if ($custom->id == 11726) {
  885. $mustNotice = true;
  886. }
  887. } else {
  888. if ($custom->id == 577) {
  889. $mustNotice = true;
  890. }
  891. }
  892. if (getenv('YII_ENV', 'local') == 'production') {
  893. if ($mustNotice) {
  894. noticeUtil::push("【开单动作 | 客户】变化前余额:{$beforeBalance} 变化金额:{$amount} 变化后余额:{$newBalance}", '15280215347');
  895. }
  896. }
  897. self::savePairBalanceAfterDeduct($custom, $ghs, $newBalance);
  898. $relateId = $order->id ?? 0;
  899. $customId = $custom->id ?? 0;
  900. $customName = $custom->name ?? '';
  901. $orderSn = $order->orderSn ?? '';
  902. $capitalType = dict::getDict('capitalType', 'xhGhsOrder', 'id');
  903. $event = '购买花材,单号:' . $orderSn;
  904. if ($bookOrder) {
  905. $event = '预订单多退少补,单号:' . $orderSn;
  906. }
  907. $change = [
  908. 'relateId' => $relateId,
  909. 'customId' => $customId,
  910. 'customName' => $customName,
  911. 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
  912. 'capitalType' => $capitalType,
  913. 'amount' => $amount,
  914. 'balance' => $newBalance,
  915. 'io' => 0,
  916. 'payWay' => $order->payWay,
  917. 'event' => $event,
  918. 'sjId' => $order->sjId,
  919. 'shopId' => $order->shopId,
  920. 'mainId' => $order->mainId,
  921. 'staffId' => 0,
  922. 'staffName' => '',
  923. 'side' => 0,
  924. 'fromType' => dict::getDict('fromType', 'shop'),
  925. 'remark' => '',
  926. ];
  927. CustomBalanceChangeClass::add($change, true);
  928. self::addGhsOrderBalanceChange($custom, $ghs, $order, $amount, $newBalance, $bookOrder);
  929. $mainId = $order->mainId ?? 0;
  930. $main = MainClass::getLockById($mainId);
  931. if (empty($main)) {
  932. util::fail('没有main信息8');
  933. }
  934. $debt = $main->debt ?? 0;
  935. $remain = bcadd($debt, $amount, 2);
  936. if (getenv('YII_ENV', 'local') == 'production') {
  937. if ($mustNotice) {
  938. noticeUtil::push("【开单动作 | 总欠款】变化前欠款:{$debt} 变化金额:{$amount} 变化后欠款:{$remain}", '15280215347');
  939. }
  940. }
  941. $main->debt = $remain;
  942. $main->save();
  943. $event = $custom->name . ' 购买花材,单号:' . $orderSn;
  944. $change['balance'] = $remain;
  945. $change['event'] = $event;
  946. TotalDebtChangeClass::addChange($change);
  947. }
  948. /**
  949. * 结账收回挂账:balance 增加(原 debtAmount 减少逻辑)
  950. * ssh 20220306
  951. */
  952. public static function clearDebtAmountReduce($custom, $ghs, $amount, $clear)
  953. {
  954. // 结账收回挂账:balance 增加,只记余额变动
  955. AccountMoneyClass::ensureCustomMoneyReady($custom, true);
  956. $beforeBalance = $custom->balance ?? '0.00';
  957. $newBalance = bcadd($beforeBalance, $amount, 2);
  958. if (bccomp($beforeBalance, '0', 2) < 0 && bccomp($newBalance, '0', 2) > 0) {
  959. noticeUtil::push("客户账户余额:{$beforeBalance} 本次结账金额:{$amount} 客户ID:{$custom->id} 【里外金额有问题】", '15280215347');
  960. util::fail('收款失败,结账后欠款金额会出现负数');
  961. }
  962. $custom->isDebt = bccomp($newBalance, '0', 2) < 0 ? CustomClass::IS_DEBT_YES : CustomClass::IS_DEBT_NO;
  963. $custom->balance = $newBalance;
  964. $custom->save(false, ['balance', 'isDebt']);
  965. $relateId = $clear->id ?? 0;
  966. $customId = $custom->id ?? 0;
  967. $customName = $custom->name ?? '';
  968. $capitalType = dict::getDict('capitalType', 'ghsXsClear', 'id');
  969. $orderSn = $clear->orderSn ?? '';
  970. $change = [
  971. 'relateId' => $relateId,
  972. 'customId' => $customId,
  973. 'customName' => $customName,
  974. 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
  975. 'capitalType' => $capitalType,
  976. 'amount' => $amount,
  977. 'balance' => $newBalance,
  978. 'io' => 1,
  979. 'payWay' => 0,
  980. 'event' => "结账,单号:{$orderSn}",
  981. 'sjId' => $ghs->sjId,
  982. 'shopId' => $ghs->shopId,
  983. 'mainId' => $ghs->mainId,
  984. 'staffId' => 0,
  985. 'staffName' => '',
  986. 'side' => 0,
  987. 'fromType' => dict::getDict('fromType', 'shop'),
  988. 'remark' => '',
  989. ];
  990. CustomBalanceChangeClass::add($change, true);
  991. $mainId = $ghs->mainId ?? 0;
  992. $main = MainClass::getLockById($mainId);
  993. if (empty($main)) {
  994. util::fail('没有main信息9');
  995. }
  996. $debt = $main->debt ?? 0;
  997. $remain = bcsub($debt, $amount, 2);
  998. $main->debt = $remain;
  999. $main->save();
  1000. $event = $custom->name . " 结账,单号:{$orderSn}";
  1001. $change['balance'] = $remain;
  1002. $change['event'] = $event;
  1003. TotalDebtChangeClass::addChange($change);
  1004. }
  1005. /**
  1006. * 售后退款:减少待结(balance 增加),只记余额变动
  1007. * ssh 20220306
  1008. */
  1009. public static function refundDebtAmountReduce($custom, $refund, $order)
  1010. {
  1011. // 退款减待结:balance 增加,只记余额变动
  1012. AccountMoneyClass::ensureCustomMoneyReady($custom, true);
  1013. $refundPrice = $refund->refundPrice ?? 0;
  1014. if (bccomp($refundPrice, '0', 2) <= 0) {
  1015. return;
  1016. }
  1017. $newBalance = bcadd($custom->balance ?? '0.00', $refundPrice, 2);
  1018. $custom->balance = $newBalance;
  1019. $custom->isDebt = bccomp($newBalance, '0', 2) < 0 ? CustomClass::IS_DEBT_YES : CustomClass::IS_DEBT_NO;
  1020. $custom->save(false, ['balance', 'isDebt']);
  1021. $relateId = $refund->id ?? 0;
  1022. $customId = $custom->id ?? 0;
  1023. $customName = $custom->name ?? '';
  1024. $saleOrderSn = $order->orderSn ?? '';
  1025. $capitalType = dict::getDict('capitalType', 'saleRefund', 'id');
  1026. $payTime = $order->payTime;
  1027. $change = [
  1028. 'relateId' => $relateId,
  1029. 'customId' => $customId,
  1030. 'customName' => $customName,
  1031. 'ptStyle' => dict::getDict('ptStyle', 'ghs'),
  1032. 'capitalType' => $capitalType,
  1033. 'amount' => $refundPrice,
  1034. 'balance' => $newBalance,
  1035. 'io' => 1,
  1036. 'payWay' => 0,
  1037. 'event' => "订单号:{$saleOrderSn} 退款",
  1038. 'sjId' => $refund->sjId,
  1039. 'shopId' => $refund->shopId,
  1040. 'mainId' => $order->mainId,
  1041. 'payTime' => $payTime,
  1042. 'staffId' => 0,
  1043. 'staffName' => '',
  1044. 'side' => 0,
  1045. 'fromType' => dict::getDict('fromType', 'shop'),
  1046. 'remark' => '',
  1047. ];
  1048. CustomBalanceChangeClass::add($change, true);
  1049. $mainId = $order->mainId ?? 0;
  1050. $main = MainClass::getLockById($mainId);
  1051. if (empty($main)) {
  1052. util::fail('没有main信息10');
  1053. }
  1054. $debt = $main->debt ?? 0;
  1055. $remain = bcsub($debt, $refundPrice, 2);
  1056. $main->debt = $remain;
  1057. $main->save();
  1058. $event = $custom->name . " 订单号:{$saleOrderSn} 退款";
  1059. $change['balance'] = $remain;
  1060. $change['event'] = $event;
  1061. TotalDebtChangeClass::addChange($change);
  1062. }
  1063. public static function exportCustom($where, $sort, $mainId)
  1064. {
  1065. $list = self::getAllByCondition($where, $sort, '*', null);
  1066. if (empty($list)) {
  1067. util::fail('没有找到客户');
  1068. }
  1069. $list = self::groupBaseInfo($list);
  1070. $phpExcelFile = Yii::getAlias("@vendor/phpoffice/phpexcel/");
  1071. require_once($phpExcelFile . 'Classes/PHPExcel.php');
  1072. $objPHPExcel = new \PHPExcel();
  1073. $objPHPExcel->getProperties()->setCreator("Maarten Balliauw")
  1074. ->setLastModifiedBy("Maarten Balliauw")
  1075. ->setTitle("Office 2007 XLSX Document")
  1076. ->setSubject("Office 2007 XLSX Document")
  1077. ->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.")
  1078. ->setKeywords("office 2007 openxml php")
  1079. ->setCategory("file");
  1080. $ghsTitle = '供货商';
  1081. $objPHPExcel->getActiveSheet()->getHeaderFooter()->setOddHeader(date('n月j日') . " " . $ghsTitle);
  1082. $objPHPExcel->getActiveSheet()->getPageMargins()->setTop(0.7);
  1083. $objPHPExcel->getActiveSheet()->getPageMargins()->setBottom(0.1);
  1084. $objPHPExcel->getActiveSheet()->getPageMargins()->setLeft(0.5);
  1085. $objPHPExcel->getActiveSheet()->getPageMargins()->setRight(0);
  1086. $objPHPExcel->getActiveSheet()->getPageMargins()->setHeader(0.1);
  1087. $objPHPExcel->getActiveSheet()->getPageMargins()->setFooter(0);
  1088. $objPHPExcel->getActiveSheet()->setCellValue('A1', 'ID');
  1089. $objPHPExcel->getActiveSheet()->setCellValue('B1', '客户');
  1090. $objPHPExcel->getActiveSheet()->setCellValue('C1', '手机号');
  1091. $objPHPExcel->getActiveSheet()->setCellValue('D1', '欠款');
  1092. $objPHPExcel->getActiveSheet()->setCellValue('E1', '余额');
  1093. $objPHPExcel->getActiveSheet()->setCellValue('F1', '待结金额');
  1094. $objPHPExcel->getActiveSheet()->setCellValue('G1', '最近下单');
  1095. $objPHPExcel->getActiveSheet()->setCellValue('H1', '累计消费');
  1096. $objPHPExcel->getActiveSheet()->setCellValue('I1', '累计消费次数');
  1097. //设置宽度
  1098. $objPHPExcel->getActiveSheet()->getColumnDimension('B')->setWidth(25);
  1099. $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(20);
  1100. $objPHPExcel->getActiveSheet()->getColumnDimension('D')->setWidth(20);
  1101. $objPHPExcel->getActiveSheet()->getColumnDimension('E')->setWidth(20);
  1102. $objPHPExcel->getActiveSheet()->getColumnDimension('F')->setWidth(15);
  1103. $objPHPExcel->getActiveSheet()->getColumnDimension('G')->setWidth(30);
  1104. $objPHPExcel->getActiveSheet()->getColumnDimension('H')->setWidth(15);
  1105. $objPHPExcel->getActiveSheet()->getColumnDimension('I')->setWidth(20);
  1106. //加粗
  1107. $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setSize(9)->setBold(true);
  1108. $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setSize(9)->setBold(true);
  1109. $objPHPExcel->getActiveSheet()->getStyle('C1')->getFont()->setSize(9)->setBold(true);
  1110. $objPHPExcel->getActiveSheet()->getStyle('D1')->getFont()->setSize(9)->setBold(true);
  1111. $objPHPExcel->getActiveSheet()->getStyle('E1')->getFont()->setSize(9)->setBold(true);
  1112. $objPHPExcel->getActiveSheet()->getStyle('F1')->getFont()->setSize(9)->setBold(true);
  1113. $objPHPExcel->getActiveSheet()->getStyle('G1')->getFont()->setSize(9)->setBold(true);
  1114. $objPHPExcel->getActiveSheet()->getStyle('H1')->getFont()->setSize(9)->setBold(true);
  1115. $objPHPExcel->getActiveSheet()->getStyle('I1')->getFont()->setSize(9)->setBold(true);
  1116. $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1117. $objPHPExcel->getActiveSheet()->getStyle('B1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1118. $objPHPExcel->getActiveSheet()->getStyle('C1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1119. $objPHPExcel->getActiveSheet()->getStyle('D1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1120. $objPHPExcel->getActiveSheet()->getStyle('E1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1121. $baseRow = 2;
  1122. foreach ($list as $key => $custom) {
  1123. $i = $baseRow + $key;
  1124. $objPHPExcel->getActiveSheet()->setCellValue('A' . $i, $custom['id']);
  1125. $objPHPExcel->getActiveSheet()->setCellValue('B' . $i, $custom['name']);
  1126. $objPHPExcel->getActiveSheet()->setCellValue('C' . $i, $custom['mobile'], \PHPExcel_Cell_DataType::TYPE_STRING);
  1127. $objPHPExcel->getActiveSheet()->setCellValue('D' . $i, $custom['debtAmount']);
  1128. $objPHPExcel->getActiveSheet()->setCellValue('E' . $i, $custom['balance']);
  1129. $objPHPExcel->getActiveSheet()->setCellValue('F' . $i, $custom['remainDebtAmount']);
  1130. if ($custom['recentExpend'] == '0000-00-00 00:00:00') {
  1131. $objPHPExcel->getActiveSheet()->setCellValue('G' . $i, '没有下过单');
  1132. } else {
  1133. $objPHPExcel->getActiveSheet()->setCellValue('G' . $i, $custom['recentExpend']);
  1134. }
  1135. $objPHPExcel->getActiveSheet()->setCellValue('H' . $i, $custom['buyAmount']);
  1136. $objPHPExcel->getActiveSheet()->setCellValue('I' . $i, $custom['buyNum']);
  1137. //居左
  1138. $objPHPExcel->getActiveSheet()->getStyle('A' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1139. $objPHPExcel->getActiveSheet()->getStyle('B' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1140. $objPHPExcel->getActiveSheet()->getStyle('C' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1141. $objPHPExcel->getActiveSheet()->getStyle('D' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1142. $objPHPExcel->getActiveSheet()->getStyle('E' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1143. $objPHPExcel->getActiveSheet()->getStyle('F' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1144. $objPHPExcel->getActiveSheet()->getStyle('G' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1145. $objPHPExcel->getActiveSheet()->getStyle('H' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1146. $objPHPExcel->getActiveSheet()->getStyle('I' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1147. }
  1148. $fileName = '客户-' . date("m-d");
  1149. $objPHPExcel->getActiveSheet()->setTitle($fileName);
  1150. $objPHPExcel->setActiveSheetIndex(0);
  1151. $dir = './priceTable/' . $mainId;
  1152. if (file_exists($dir) == false) {
  1153. mkdir($dir, 0777, true);
  1154. }
  1155. $date = $fileName;
  1156. $file = $date . '.xls';
  1157. $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
  1158. if (file_exists($dir . '/' . $file)) {
  1159. unlink($dir . '/' . $file);
  1160. }
  1161. $objWriter->save($dir . '/' . $file);
  1162. $fileUrl = Yii::$app->params['ghsHost'] . '/priceTable/' . $mainId . '/' . $file;
  1163. util::success(['file' => $fileUrl, 'shortFile' => $file]);
  1164. }
  1165. public static function showTotalBalance($pfShopId = 0, $lsShopId = 0)
  1166. {
  1167. ini_set('memory_limit', '2045M');
  1168. set_time_limit(0);
  1169. $pfAmount = 0;
  1170. $lsAmount = 0;
  1171. if (!empty($pfShopId)) {
  1172. $custom = CustomClass::getAllByCondition(['ownShopId' => $pfShopId], null, '*', null, true);
  1173. if (!empty($custom)) {
  1174. foreach ($custom as $c) {
  1175. $new = AccountMoneyClass::getNetBalanceFromRow($c);
  1176. $pfAmount = bcadd($pfAmount, $new, 2);
  1177. }
  1178. }
  1179. }
  1180. if (!empty($lsShopId)) {
  1181. $lsCustom = \bizHd\custom\classes\CustomClass::getAllByCondition(['shopId' => $lsShopId], null, '*', null, true);
  1182. if (!empty($lsCustom)) {
  1183. foreach ($lsCustom as $lc) {
  1184. $balance = $lc->balance ?? 0;
  1185. $lsAmount = bcadd($balance, $lsAmount, 2);
  1186. }
  1187. }
  1188. }
  1189. return ['pfAmount' => $pfAmount, 'lsAmount' => $lsAmount];
  1190. }
  1191. }