SeedOrder.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. <?php
  2. namespace addons\Seed\common\models;
  3. use addons\Seed\common\enums\SeedEnum;
  4. use addons\Store\common\models\StoreCashierOrder;
  5. use addons\Store\common\models\StoreOrder;
  6. use common\enums\OrderStatusEnum;
  7. use common\enums\StatusEnum;
  8. use common\enums\UserWalletEnum;
  9. use common\models\user\User;
  10. use services\common\UserWalletService;
  11. use yii\db\Exception;
  12. /**
  13. * This is the model class for table "{{%addons_seed_order}}".
  14. *
  15. * @property int $id
  16. * @property int $mall_id 商城ID
  17. * @property int $store_id 门店id
  18. * @property int $user_id 用户ID
  19. * @property int $identity 身份[1:消费者,2:店长]
  20. * @property int $order_id 订单ID
  21. * @property int $event_pay 事件类型[1=普通订单,2=收银台订单]
  22. * @property float $credit_money 赊账金额,单位:元
  23. * @property int $is_credit 是否是赊账订单[0:否,1:是]
  24. * @property string $order_no 订单号
  25. * @property string $goods_name 第一个商品名称
  26. * @property int $seed_num 种子金数量
  27. * @property float $basic_unit_price 种子金基础单价,单位:元
  28. * @property float $unit_price 种子金现单价,单位:元
  29. * @property float $seed_cost 种子金总价值,单位:元
  30. * @property int $increase_num 增长次数
  31. * @property int $join_pool_money 存放到能量池的金额,单位:元
  32. * @property int $can_send_at 可发放能量时间
  33. * @property int $last_send_at 上次能量池释放时间
  34. * @property int|null $seed_status 状态[0:冻结中,1:增长中,2:已收取]
  35. * @property int $is_able_collect 是否允许收取[0:不允许,1:允许]
  36. * @property int|null $status 状态[-1:删除;0:禁用;1启用]
  37. * @property int $created_at 创建时间
  38. * @property int $updated_at 修改时间
  39. */
  40. class SeedOrder extends \common\models\base\BaseActiveRecord
  41. {
  42. /**
  43. * {@inheritdoc}
  44. */
  45. public static function tableName()
  46. {
  47. return '{{%addons_seed_order}}';
  48. }
  49. /**
  50. * {@inheritdoc}
  51. */
  52. public function rules()
  53. {
  54. return [
  55. [['mall_id', 'store_id', 'user_id', 'identity', 'order_id', 'event_pay', 'is_credit', 'seed_num', 'increase_num', 'can_send_at', 'last_send_at', 'seed_status', 'status', 'is_able_collect', 'created_at', 'updated_at'], 'integer'],
  56. [['credit_money','basic_unit_price', 'unit_price', 'seed_cost', 'join_pool_money'], 'number'],
  57. [['order_no'], 'string', 'max' => 60],
  58. [['goods_name'], 'string', 'max' => 255],
  59. ];
  60. }
  61. /**
  62. * {@inheritdoc}
  63. */
  64. public function attributeLabels()
  65. {
  66. return [
  67. 'id' => 'ID',
  68. 'mall_id' => '商城ID',
  69. 'store_id' => '门店id',
  70. 'user_id' => '用户ID',
  71. 'identity' => '身份[1:消费者,2:店长]',
  72. 'order_id' => '订单ID',
  73. 'order_no' => '订单号',
  74. 'event_pay' => '事件类型[1=普通订单,2=收银台订单]',
  75. 'is_credit' => '是否是赊账订单[0:否,1:是]',
  76. 'credit_money' => '赊账金额,单位:元',
  77. 'goods_name' => '第一个商品名称',
  78. 'seed_num' => '种子金数量',
  79. 'basic_unit_price' => '种子金基础单价,单位:元',
  80. 'unit_price' => '种子金现单价,单位:元',
  81. 'seed_cost' => '种子金总价值,单位:元',
  82. 'increase_num' => '增长次数',
  83. 'join_pool_money' => '存放到能量池的金额,单位:元',
  84. 'can_send_at' => '可发放能量时间',
  85. 'last_send_at' => '上次能量池释放时间',
  86. 'seed_status' => '状态[0:冻结中,1:增长中,2:已收取]',
  87. 'is_able_collect' => '是否允许收取[0:不允许,1:允许]',
  88. 'status' => '状态[-1:删除;0:禁用;1启用]',
  89. 'created_at' => '创建时间',
  90. 'updated_at' => '修改时间',
  91. ];
  92. }
  93. /**
  94. * 关联用户表
  95. * @Author: lun
  96. * @DateTime: 2022/7/28 0028 10:07
  97. * @Copyright: copyright (c) 2021 广东七件事集团
  98. * @return \yii\db\ActiveQuery
  99. */
  100. public function getUser()
  101. {
  102. return $this->hasOne(User::class, ['id' => 'user_id'])->select('id,mobile,nickname,username,avatar_url');
  103. }
  104. /**
  105. * 关联订单表
  106. * @Author: lun
  107. * @DateTime: 2022/8/26 0026 19:33
  108. * @Copyright: copyright (c) 2021 广东七件事集团
  109. * @return \yii\db\ActiveQuery
  110. */
  111. public function getOrder()
  112. {
  113. return $this->hasOne(StoreOrder::class, ['id' => 'order_id'])->select('id,order_no,order_status');
  114. }
  115. /**
  116. * 消费生成数据
  117. * @Author: lun
  118. * @DateTime: 2022/7/27 0027 11:51
  119. * @Copyright: copyright (c) 2021 广东七件事集团
  120. * @param $params
  121. * @return bool
  122. */
  123. public static function consumeOrder($params, $extra)
  124. {
  125. try {
  126. $model = self::findOne(['user_id' => $params['user_id'], 'order_no' => $params['order_no'], 'identity' => $params['identity'], 'status' => StatusEnum::ENABLED]);
  127. if (empty($model)) {
  128. $model = new self();
  129. $model->loadDefaultValues();
  130. }
  131. // 额度变化处理
  132. if (!empty($params['unit_price'])) {
  133. $unit_price = $params['unit_price'];// 变动的单价
  134. $model->unit_price += $params['unit_price'];
  135. !empty($params['seed_num']) && $model->seed_num = $params['seed_num'];
  136. $model->seed_cost = sprintf("%.2f",substr(sprintf("%.3f", $model->seed_num * $unit_price), 0, -2));// 不四舍五入保留两位小数
  137. unset($params['unit_price']);
  138. }
  139. if (!$model->load($params, '') || !$model->save()) throw new Exception('订单种子金:'.$model->getErrorMessage());
  140. // 增加用户种子金
  141. $res = SeedUser::setData($model->mall_id, $model->user_id, [
  142. 'total_seed_num' => $model->seed_num,
  143. 'total_seed_cost' => $model->seed_cost,
  144. ]);
  145. if ($res === false) throw new \Exception(SeedUser::getStaticError());
  146. // 增加种子金变动记录
  147. $res = SeedLog::setData([
  148. 'seed_order_id' => $model->id,
  149. 'mall_id' => $model->mall_id,
  150. 'store_id' => $model->store_id,
  151. 'user_id' => $model->user_id,
  152. 'order_id' => $model->order_id,
  153. 'event_pay' => $model->event_pay,
  154. 'seed_num' => $model->seed_num,
  155. 'seed_cost' => $model->seed_cost,
  156. 'change_unit_price' => $unit_price ?? 0,
  157. 'after_unit_price' => $model->unit_price,
  158. 'desc' => $extra['desc'] ?? '',
  159. 'capital_type' => $extra['capital_type'] ?? '',
  160. 'pool_id' => $extra['pool_id'] ?? 0,
  161. 'setting' => $extra['setting'] ?? '',
  162. ]);
  163. if ($res === false) throw new \Exception(SeedLog::getStaticError());
  164. return true;
  165. } catch (\Exception $e) {
  166. self::setStaticError('用户种子金保存:第'.$e->getLine().'行,原因:'.$e->getMessage());
  167. return false;
  168. }
  169. }
  170. /**
  171. * API接口收取种子金
  172. * @Author: lun
  173. * @DateTime: 2022/8/30 0030 18:34
  174. * @Copyright: copyright (c) 2021 广东七件事集团
  175. * @param $user_id
  176. * @param $id
  177. * @param string $desc
  178. * @throws Exception
  179. */
  180. public static function collect($user_id, $id, $desc = '种子金收取')
  181. {
  182. try {
  183. // 种子金订单状态修改
  184. $seed_order = self::findOne(['id' => $id,'user_id' => $user_id, 'status' => StatusEnum::ENABLED]);
  185. if (empty($seed_order)) throw new \Exception('暂无此订单');
  186. self::collectError($seed_order->seed_status);
  187. // 检查是否是赊账订单,并且是否可收取
  188. if ($seed_order->is_credit == StatusEnum::ENABLED && $seed_order->is_able_collect == StatusEnum::DISABLED) {
  189. throw new Exception('该订单为赊账订单,未还款前暂不允许收取');
  190. }
  191. $res = self::handleCollect($seed_order, 'api', $desc);
  192. if ($res === false) throw new \Exception(self::getStaticError());
  193. } catch (\Exception $e) {
  194. self::setStaticError($e->getMessage());
  195. return false;
  196. }
  197. }
  198. /**
  199. * 种子金收取处理
  200. * @Author: lun
  201. * @DateTime: 2022/8/1 0001 10:11
  202. * @Copyright: copyright (c) 2021 广东七件事集团
  203. * @param $seed_order
  204. * @param $type
  205. * @param $desc
  206. */
  207. public static function handleCollect($seed_order, $type = 'api', $desc = '种子金收取')
  208. {
  209. $trans = \Yii::$app->db->beginTransaction();
  210. try {
  211. // 获取收取类型[1=支付完成后,2=订单完成后]
  212. $collect_type = \Yii::$app->services->setting->addons->get($seed_order->mall_id, SeedEnum::ADDONS_NAME, 'basic.collect_type');
  213. if ($collect_type == 2 && $seed_order->event_pay == 1) {
  214. // 获取订单状态
  215. $order_status = StoreOrder::find()->select('order_status')->where(['id' => $seed_order->order_id])->scalar();
  216. if ($order_status != OrderStatusEnum::ACCOMPLISH) {
  217. if ($type == 'api') {
  218. throw new Exception('订单未完成不可收取');
  219. } else {
  220. $trans->commit();
  221. return true;
  222. }
  223. }
  224. }
  225. $seed_order->seed_status = SeedEnum::SEED_COLLECT;
  226. $seed_order->is_able_collect = StatusEnum::ENABLED;
  227. if (!$seed_order->save()) throw new Exception($seed_order->getErrorMessage());
  228. // 增加用户种子金收取金额
  229. $res = SeedUser::setData($seed_order->mall_id, $seed_order->user_id, ['collect_seed_num' => $seed_order->seed_num, 'total_change_money' => $seed_order->seed_cost]);
  230. if ($res === false) throw new \Exception(SeedUser::getStaticError());
  231. // 增加种子金收取记录
  232. $res = SeedLog::setData([
  233. 'seed_order_id' => $seed_order->id,
  234. 'mall_id' => $seed_order->mall_id,
  235. 'store_id' => $seed_order->store_id,
  236. 'user_id' => $seed_order->user_id,
  237. 'order_id' => $seed_order->order_id,
  238. 'event_pay' => $seed_order->event_pay,
  239. 'seed_num' => $seed_order->seed_num,
  240. 'seed_cost' => $seed_order->seed_cost,
  241. 'change_unit_price' => 0,
  242. 'after_unit_price' => $seed_order->unit_price,
  243. 'desc' => $desc,
  244. 'capital_type' => SeedEnum::LOG_COLLECT,
  245. ]);
  246. if ($res === false) throw new \Exception(SeedLog::getStaticError());
  247. // 用户数据统计
  248. $res = SeedUserStatistics::setData([
  249. 'mall_id' => $seed_order->mall_id,
  250. 'store_id' => $seed_order->store_id,
  251. 'user_id' => $seed_order->user_id,
  252. ], ['collect_seed_num' => $seed_order->seed_num]);
  253. if ($res === false) throw new \Exception(SeedUserStatistics::getStaticError());
  254. // 资金统计
  255. SeedCapitalStatistics::saveStatistics($seed_order->mall_id, ['collect_seed_num' => $seed_order->seed_num]);
  256. // 插入资金
  257. $insert_wallet[] = [
  258. 'mall_id' => $seed_order->mall_id,
  259. 'user_id' => $seed_order->user_id,
  260. 'is_frozen' => false,
  261. 'wallet_type' => 'balance',
  262. 'money' => $seed_order->seed_cost,
  263. 'desc' => $desc,
  264. 'source_table' => 'seed_order',
  265. 'source_table_id' => $seed_order->id,
  266. 'from_type' => SeedEnum::ADDONS_NAME,
  267. 'capital_type' => SeedEnum::LOG_COLLECT,
  268. ];
  269. $res = UserWalletService::batchHandleByQueue($insert_wallet);
  270. if (empty($res)) throw new \Exception(UserWalletService::getStaticError());
  271. $trans->commit();
  272. return true;
  273. } catch (\Exception $e) {
  274. $trans->rollBack();
  275. self::setStaticError($e->getMessage());
  276. return false;
  277. }
  278. }
  279. /**
  280. * 收取状态提示
  281. * @Author: lun
  282. * @DateTime: 2022/8/30 0030 15:51
  283. * @Copyright: copyright (c) 2021 广东七件事集团
  284. * @param $seed_status
  285. * @return bool
  286. * @throws \Exception
  287. */
  288. private static function collectError($seed_status)
  289. {
  290. switch ($seed_status) {
  291. case SeedEnum::SEED_COLLECT :
  292. throw new \Exception('该订单已被收取');
  293. break;
  294. case SeedEnum::SEED_REFUND :
  295. throw new \Exception('订单已退款,无法收取');
  296. break;
  297. case SeedEnum::SEED_BAD :
  298. throw new \Exception('订单被冻结,请尽快还款或等待订单完成');
  299. break;
  300. default :
  301. return true;
  302. break;
  303. }
  304. }
  305. /**
  306. * 批量收取
  307. * @Author: lun
  308. * @DateTime: 2022/8/31 0031 11:20
  309. * @Copyright: copyright (c) 2021 广东七件事集团
  310. * @param $mall_id
  311. * @param $seed_order_ids
  312. * @param int $event_pay
  313. * @return array|bool
  314. */
  315. public static function batchCollect($mall_id, $seed_order_ids, $event_pay = 1)
  316. {
  317. $trans = \Yii::$app->db->beginTransaction();
  318. try {
  319. // 获取订单id
  320. $store_order_ids = self::find()->select('order_id')->where(['id' => $seed_order_ids])->column();
  321. $collect_order_ids = $store_order_ids = array_unique($store_order_ids);
  322. $handle_credit = [];// 赊账订单自动收取
  323. // 获取收取类型[1=支付完成后,2=订单完成后]
  324. $collect_type = \Yii::$app->services->setting->addons->get($mall_id, SeedEnum::ADDONS_NAME, 'basic.collect_type');
  325. if ($collect_type == 2 && $event_pay <= 2) {
  326. // 获取已完成的订单id
  327. if ($event_pay == 1) {
  328. $collect_order_ids = StoreOrder::find()->select('id')->where(['id' => $store_order_ids, 'order_status' => OrderStatusEnum::ACCOMPLISH])->column();
  329. } else {
  330. $collect_order_ids = StoreCashierOrder::find()->select('id')->where(['id' => $store_order_ids, 'pay_status' => StatusEnum::ENABLED])->column();
  331. }
  332. // 将未完成的订单并且是已达到倍数自动收取的订单改为停止增长 - 针对消费者订单停止增长
  333. $diff_order_ids = array_diff($store_order_ids, $collect_order_ids);
  334. if ($diff_order_ids) {
  335. self::updateAll(['seed_status' => SeedEnum::SEED_STOP, 'updated_at' => time()], 'id in('.implode(',', $seed_order_ids).') and order_id in('.implode(',', $diff_order_ids).") and event_pay={$event_pay}");
  336. }
  337. }
  338. // 查询条件
  339. $where = ['id' => $seed_order_ids, 'order_id' => $collect_order_ids, 'event_pay' => $event_pay, 'seed_status' => SeedEnum::SEED_ADD, 'status' => StatusEnum::ENABLED];
  340. // 获取可收取的种子金订单
  341. $list = self::find()->where($where)->with(['order'])->asArray()->all();
  342. if (empty($list)) {
  343. $trans->commit();
  344. return $handle_credit;
  345. }
  346. // 批量修改状态,改为已收取
  347. self::updateAll(['seed_status' => SeedEnum::SEED_COLLECT, 'updated_at' => time()], 'id in('.implode(',', $seed_order_ids).') and order_id in('.implode(',', $collect_order_ids).") and event_pay={$event_pay}");
  348. // 增加用户收取金额跟数量
  349. $seed_users = $statistics = [];
  350. $total_collect_num = 0;
  351. $change_money_arr = [];
  352. foreach ($list as $item) {
  353. $seed_users[$item['user_id']] = empty($seed_users[$item['user_id']]) ? $item['seed_num'] : $item['seed_num'] + $seed_users[$item['user_id']];
  354. $statistics[$item['store_id']][$item['user_id']] = empty($statistics[$item['store_id']][$item['user_id']]) ? $item['seed_num'] : $item['seed_num'] + $statistics[$item['store_id']][$item['user_id']];
  355. $change_money_arr[$item['user_id']] = empty($change_money_arr[$item['user_id']]) ? $item['seed_cost'] : $item['seed_cost'] + $change_money_arr[$item['user_id']];
  356. $total_collect_num += $item['seed_num'];
  357. // 插入资金列表
  358. $insert_wallet[] = [
  359. 'mall_id' => $mall_id,
  360. 'user_id' => $item['user_id'],
  361. 'is_frozen' => false,
  362. 'wallet_type' => 'balance',
  363. 'money' => $item['seed_cost'],
  364. 'desc' => '自动收取种子金',
  365. 'source_table' => 'seed_order',
  366. 'source_table_id' => $item['id'],
  367. 'from_type' => SeedEnum::ADDONS_NAME,
  368. 'capital_type' => SeedEnum::LOG_COLLECT,
  369. ];
  370. // 插入收取记录
  371. $res = SeedLog::setData([
  372. 'seed_order_id' => $item['id'],
  373. 'mall_id' => $item['mall_id'],
  374. 'store_id' => $item['store_id'],
  375. 'user_id' => $item['user_id'],
  376. 'identity' => $item['identity'],
  377. 'order_id' => $item['order_id'],
  378. 'event_pay' => $item['event_pay'],
  379. 'seed_num' => $item['seed_num'],
  380. 'seed_cost' => $item['seed_cost'],
  381. 'change_unit_price' => 0,
  382. 'after_unit_price' => $item['unit_price'],
  383. 'desc' => '自动收取种子金',
  384. 'capital_type' => SeedEnum::LOG_COLLECT,
  385. ]);
  386. if ($res === false) throw new \Exception(SeedLog::getStaticError());
  387. // 赊账订单处理 - 只处理消费者
  388. if ($item['is_credit'] == StatusEnum::ENABLED && $item['identity'] == StatusEnum::ENABLED) $handle_credit[$item['event_pay']][] = $item['order_id'];
  389. }
  390. // 增加用户种子金收取金额
  391. foreach ($seed_users as $user_id => $collect_seed_num) {
  392. $res = SeedUser::setData($mall_id, $user_id, ['collect_seed_num' => $collect_seed_num, 'total_change_money' => $change_money_arr[$user_id]]);
  393. if ($res === false) throw new \Exception(SeedUser::getStaticError());
  394. }
  395. // 用户数据统计
  396. foreach ($statistics as $store_id => $item) {
  397. foreach ($item as $user_id => $seed_num) {
  398. $res = SeedUserStatistics::setData([
  399. 'mall_id' => $mall_id,
  400. 'store_id' => $store_id,
  401. 'user_id' => $user_id,
  402. ], ['collect_seed_num' => $seed_num]);
  403. if ($res === false) throw new \Exception(SeedUserStatistics::getStaticError());
  404. }
  405. }
  406. // 资金统计
  407. SeedCapitalStatistics::saveStatistics($mall_id, ['collect_seed_num' => $total_collect_num]);
  408. // 插入资金
  409. if ($insert_wallet) {
  410. $res = UserWalletService::batchHandleByQueue($insert_wallet);
  411. if (empty($res)) throw new \Exception(UserWalletService::getStaticError());
  412. }
  413. $trans->commit();
  414. return $handle_credit;
  415. } catch (\Exception $e) {
  416. $trans->rollBack();
  417. self::setStaticError('种子金批量自动收取:第'.$e->getLine().'行,原因:'.$e->getMessage());
  418. return false;
  419. }
  420. }
  421. /**
  422. * 坏账订单处理
  423. * @Author: lun
  424. * @DateTime: 2022/8/5 0005 16:17
  425. * @Copyright: copyright (c) 2021 广东七件事集团
  426. * @param $mall_id
  427. * @param $seed_order_ids
  428. * @return bool
  429. */
  430. public static function badOrderHandle($mall_id, $seed_order_ids)
  431. {
  432. try {
  433. // 订单列表
  434. $bad_seed_num = self::find()->where(['id' => $seed_order_ids, 'seed_status' => SeedEnum::SEED_ADD, 'status' => StatusEnum::ENABLED])->sum('seed_num');
  435. // 批量修改状态
  436. self::updateAll(['seed_status' => SeedEnum::SEED_BAD, 'updated_at' => time()], 'id in('.implode(',', $seed_order_ids).')');
  437. // 增加坏账订单金额
  438. if ($bad_seed_num) SeedCapitalStatistics::saveStatistics($mall_id, ['bad_seed_num' => $bad_seed_num]);
  439. return true;
  440. } catch (\Exception $e) {
  441. self::setStaticError('坏账订单处理:'.$e->getMessage());
  442. return false;
  443. }
  444. }
  445. }