Store.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. <?php
  2. /**
  3. * 厦门云联储网络科技有限公司
  4. * https://www.baokuaiyun.com
  5. * Copyright (c) 2023 爆块云 All rights reserved.
  6. */
  7. namespace app\models;
  8. use yii\behaviors\TimestampBehavior;
  9. use app\models\StoreAccountLog;
  10. /**
  11. * Class Store
  12. * @package app\models
  13. * @property integer $id
  14. * @property integer $admin_id
  15. * @property integer $is_delete
  16. * @property string $share_setting
  17. * @property float $transfer_profit
  18. * @property float $scan_transfer_profit
  19. * @property integer $is_alliance
  20. * @property string $douyin_url
  21. * @property string $recommend_keyword
  22. * @property string $coordinate
  23. * @property string $address
  24. * @property string $parent_id
  25. * @property string $app_auth_token
  26. * @property string $shop_id
  27. * @property integer $created_at
  28. * @property integer $updated_at
  29. * @property string $info
  30. * @property integer $store_type
  31. * @property string $category_id
  32. * @property string $name
  33. * @property string $logo
  34. * @property string $store_front_photo
  35. * @property integer $province_id
  36. * @property integer $city_id
  37. * @property integer $district_id
  38. * @property integer $sales
  39. * @property integer $rank
  40. * @property integer $per_spend
  41. * @property string $tags
  42. * @property string $user_name
  43. * @property string $contact_tel
  44. * @property string $wechat_msg_token
  45. * @property string $delivery_category
  46. * @property integer $delivery_type
  47. * @property integer $salesman_id
  48. * @property string $md_agreement
  49. * @property string $md_banner
  50. * @property string $open_price
  51. * @property string $renew_price
  52. * @property int $end_time
  53. * @property string $profit
  54. * @property string $food_payment
  55. * @property int $food_pay_type
  56. * @property int $open_status
  57. * @property int $shop_time_type
  58. * @property int $is_time_forbid
  59. * @property int $is_set_distance
  60. * @property int $distance
  61. * @property string $s_time
  62. * @property string $e_time
  63. * @property int $store_admin
  64. * @property double $rate
  65. * @property int $store_share_switch // 店铺间分销开关
  66. * @property int $store_share_type // 店铺间分销佣金类型:0,百分比 1,固定金额
  67. * @property string $store_share_value // 店铺间分销值
  68. * @property int $business_model
  69. * @property string $auth
  70. * @property int $self_rebate_switch
  71. * @property float $self_rebate_value
  72. * @property string $device_name
  73. * @property string $is_auth_trans
  74. * @property int $is_use_default
  75. * @property string $kefu_id
  76. * @property float $longitude
  77. * @property float $latitude
  78. * @property float $price
  79. * @property float $total_price
  80. * @property float $league_price
  81. * @property int $wechat_delivery_type
  82. * @property string $store_number
  83. * @property string $cusid
  84. * @property float $ratio
  85. * @property string $yunst_user_id
  86. * @property float $food_transfer_profit
  87. * @property float $cashier_transfer_profit
  88. * @property float $pv_transfer_profit
  89. * @property string $store_url_info
  90. * @property string $small_model_proportion
  91. */
  92. class Store extends \yii\db\ActiveRecord
  93. {
  94. const TYPE_BRAND = 1;
  95. const TYPE_STORE = 2;
  96. /**
  97. * @inheritdoc
  98. */
  99. public static function tableName()
  100. {
  101. return '{{%store}}';
  102. }
  103. public function behaviors()
  104. {
  105. return [
  106. [
  107. // 自动更新创建和更新时间
  108. 'class' => TimestampBehavior::class,
  109. 'value' => time()
  110. ]
  111. ];
  112. }
  113. /**
  114. * @inheritdoc
  115. */
  116. public function rules()
  117. {
  118. return [
  119. [['rank', 'per_spend', 'self_rebate_value'], 'number'],
  120. [['id', 'admin_id', 'salesman_id', 'is_delete', 'is_alliance', 'created_at', 'updated_at', 'parent_id',
  121. 'category_id', 'province_id', 'city_id', 'district_id', 'sales', 'delivery_type', 'end_time', 'food_pay_type',
  122. 'open_status', 'shop_time_type', 'is_time_forbid', 'is_set_distance', 'store_admin', 'store_share_switch',
  123. 'store_share_type', 'business_model', 'self_rebate_switch', 'is_auth_trans', 'is_use_default', 'wechat_delivery_type','is_platform_transfers'], 'integer'],
  124. [['delivery_category', 'share_setting', 'douyin_url', 'recommend_keyword', 'app_auth_token', 'coordinate',
  125. 'address', 'shop_id', 'name', 'logo','store_front_photo', 'tags', 'contact_tel', 'user_name', 'wechat_msg_token', 'md_banner',
  126. 'md_agreement', 'food_payment', 's_time', 'e_time', 'auth', 'device_name', 'kefu_id', 'store_number', 'cusid', 'yunst_user_id'], 'string'],
  127. [['transfer_profit', 'open_price', 'renew_price', 'profit', 'distance', 'rate', 'store_share_value', 'latitude', 'longitude', 'price', 'total_price', 'scan_transfer_profit', 'ratio', 'food_transfer_profit', 'cashier_transfer_profit','small_model_proportion'], 'double'],
  128. [['created_at', 'update_at', 'info','store_url_info'], 'safe']
  129. ];
  130. }
  131. /**
  132. * @inheritdoc
  133. */
  134. public function attributeLabels()
  135. {
  136. return [
  137. 'id' => 'ID',
  138. 'admin_id' => '管理员ID',
  139. 'created_at' => '创建时间',
  140. 'updated_at' => '更新时间',
  141. 'share_setting' => 'saas分销配置',
  142. 'transfer_profit' => '商城让利比例',
  143. 'scan_transfer_profit' => '当面付让利比例',
  144. 'is_alliance' => '是否加入联盟', // 0=未加入, 1=加入, 2=待审核
  145. 'recommend_keyword' => '店铺推荐关键词',
  146. 'is_delete' => '是否已删除',
  147. 'douyin_url' => '抖口令',
  148. 'parent_id' => '父级ID',
  149. 'coordinate' => '坐标',
  150. 'address' => '商城地址',
  151. 'shop_id' => '蚂蚁门店id',
  152. 'app_auth_token' => '授权token',
  153. 'category_id' => '分类id',
  154. 'info' => '类目筛选信息',
  155. 'name' => '商城名称',
  156. 'logo' => '商城logo',
  157. 'province_id' => '省id',
  158. 'city_id' => '市id',
  159. 'district_id' => '区域id',
  160. 'sales' => '销量',
  161. 'rank' => '评分',
  162. 'per_spend' => '人均花费',
  163. 'tags' => '标签',
  164. 'wechat_msg_token' => '微信推送消息token',
  165. 'open_price'=>"开铺金额",
  166. 'renew_price'=>"续费金额",
  167. 'end_time'=>"有效期",
  168. 'profit'=>"分佣金额",
  169. 'store_admin' => '商城管理员saas_user_id',
  170. 'rate' => '销售溢价比',
  171. 'store_share_switch' => '店铺间分销开关',
  172. 'store_share_type' => '店铺间分销佣金类型',
  173. 'store_share_value' => '店铺间分销值',
  174. 'business_model' => '运营模式',
  175. 'auth' => '商盟对店铺的权限控制',
  176. 'device_name' => '语音播报设备名称',
  177. 'is_auth_trans' => '是否自动转单',
  178. 'is_use_default' => '是否使用默认费用设置',
  179. 'kefu_id' => '客服id',
  180. 'price' => '店铺可提现金额',
  181. 'total_price' => '店铺累计金额',
  182. 'league_price' => '店铺联盟券金额',
  183. 'wechat_delivery_type' => '微信配送方式0即时配送(旧) 1同城配送',
  184. 'store_number' => '商城编号',
  185. 'cusid' => '进件商户号',
  186. 'ratio' => '通联签约抽佣比例',
  187. 'yunst_user_id' => '通联生成的会员UID',
  188. ];
  189. }
  190. public function afterSave($insert, $changedAttributes)
  191. {
  192. parent::afterSave($insert, $changedAttributes);
  193. // 云仓溢价比例修改后,同步云仓商品价格
  194. if (isset($changedAttributes['rate']) && $changedAttributes['rate'] != $this->rate) {
  195. $job = new \app\jobs\SyncCloudGoodsPriceJob();
  196. $job->store_id = $this->id;
  197. \queue_push($job);
  198. }
  199. }
  200. public function beforeSave($insert)
  201. {
  202. if (parent::beforeSave($insert)) {
  203. if (\Yii::$app->prod_is_shangmeng()) {
  204. // 商盟版本没有独立运营, 如果传的是1,改成默认2
  205. if ($this->business_model == 1 || empty($this->business_model)) {
  206. $this->business_model = 2;
  207. }
  208. }
  209. if($insert){
  210. $count = 0;
  211. if($this->salesman_id > 0){
  212. $salesman = Salesman::findOne($this->salesman_id);
  213. $currentAdmin = Admin::findOne($salesman->admin_id);
  214. }else{
  215. $currentAdmin = Admin::findOne($this->admin_id);
  216. }
  217. if($currentAdmin && $currentAdmin->type == Admin::ADMIN_TYPE_BD_AGENT){
  218. $count = Store::find()->where(['is_delete' => 0])
  219. ->andWhere([
  220. 'or',
  221. ['admin_id' => $currentAdmin->id],
  222. ['salesman_id' => Salesman::find()->where(['admin_id' => $currentAdmin->id, 'is_delete' => 0])->select('id')]
  223. ])->count();
  224. $canStoreCount = $currentAdmin->max_app_count - $count;
  225. if($canStoreCount <= 0){
  226. \Yii::error([__METHOD__, $this->admin_id, $currentAdmin->max_app_count, $count, $this->attributes, '商城数量超过限制']);
  227. $this->addError('max_app_count', '操作失败,商城数量超过限制'. $count . '/' . $currentAdmin->max_app_count);
  228. return false;
  229. }
  230. }
  231. }
  232. return true;
  233. }
  234. return false;
  235. }
  236. public function getCategory(){
  237. return $this->hasOne(SaasCategory::className(),['id'=>'category_id']);
  238. }
  239. public function getOrder(){
  240. return $this->hasMany(Order::className(),['store_id'=>'id']);
  241. }
  242. public function getReorder(){
  243. return $this->hasMany(StoreReOrder::className(),['store_id'=>'id']);
  244. }
  245. public function getAdmin(){
  246. return $this->hasOne(Admin::className(),['id'=>'admin_id']);
  247. }
  248. public static function nameList() {
  249. return self::find()->andWhere(['is_delete' => 0])->asArray()->select('id,name,salesman_id')->all();
  250. }
  251. // 是否进件 // yunst是否是通联支付
  252. public static function hasIncoming($store_id, $platform = 'wechat')
  253. {
  254. if (($platform == 'alipay') || is_alipay_platform()) {
  255. $data = StoreAliMini::findOne(['store_id' => $store_id, 'is_cancel' => 0, 'batch_status' => [2, 6]]);
  256. if (!$data) {
  257. return false;
  258. }
  259. return true;
  260. } elseif (($platform == 'wechat' || $platform == 'yunst') || is_wechat_platform()) {
  261. $data = MerchantInfo::find()->where([
  262. 'bind_store_id' => $store_id,
  263. 'status' => 3,
  264. 'is_use' => 1,
  265. 'is_yunst' => intval($platform == 'yunst'),
  266. 'is_delete' => 0
  267. ])->one();
  268. if (!$data) {
  269. return false;
  270. }
  271. if (empty($data->sub_mch_id)) {
  272. return false;
  273. }
  274. return true;
  275. }
  276. }
  277. public static function isStoreCurrency($store_id)
  278. {
  279. $saleman_id = Store::find()->where(['id'=>$store_id,'is_delete'=>0])->select('salesman_id')->scalar();
  280. if (!$saleman_id) return false;
  281. $store_id = Salesman::find()->alias('s')->leftJoin(['a'=>Admin::tableName()],'s.admin_id = a.id')
  282. ->where(['s.id'=>$store_id,'s.is_delete'=>0])->select('a.store_id')->scalar();
  283. $coin = \Yii::$app->db->createCommand("SELECT money,user_percent FROM cyy_user_wallet_coin where store_id= :store_id and is_status=1 and shop_status = 1")
  284. ->bindValues([
  285. ':store_id' => $store_id,
  286. ])->queryOne();
  287. if (!$coin || $coin['money'] <= 0) return false;
  288. $setting = Option::getShareDefaultSetting($store_id);
  289. if (!isset($setting['currceny_percent_scan']) || $setting['currceny_percent_scan']<=0) return false;
  290. $data['percent'] = ($setting['currceny_percent_scan'] * $coin['user_percent'])/100;
  291. $data['money'] = $coin['money'];
  292. return $data;
  293. }
  294. public static function is_red_package($store_id)
  295. {
  296. $coin = Option::getShareSaleSetting($store_id);
  297. $setting = Option::getShareDefaultSetting($store_id);
  298. if (!isset($setting['scan_qr_code_percent']) || $setting['scan_qr_code_percent']<=0) return false;
  299. if (!isset($coin['string_code_store_red_packet']) || $coin['string_code_store_red_packet']<=0) return false;
  300. $data['percent'] = ($setting['scan_qr_code_percent'] * $coin['string_code_store_red_packet'])/100;
  301. return $data;
  302. }
  303. // 店铺累计金额
  304. public static function getTotalMoney($store)
  305. {
  306. return $store->total_price;
  307. }
  308. // 店铺金额
  309. public static function getMoney($store)
  310. {
  311. return $store->price;
  312. }
  313. // 店铺减少金额
  314. public static function subMoney($store, $price, $desc = '账户提现',$cash_id=0)
  315. {
  316. $t = \Yii::$app->db->beginTransaction();
  317. try {
  318. $before = $store->price;
  319. $store->price -= $price;
  320. if (!$store->save()) {
  321. throw new \Exception('商城金额减少失败');
  322. }
  323. $log = new StoreAccountLog();
  324. $log->store_id = $store->id;
  325. $log->price = $price;
  326. $log->desc = $desc;
  327. $log->before = $before;
  328. $log->after = $store->price;
  329. $log->type = 2;
  330. $log->time = time();
  331. $log->order_id = $cash_id;
  332. if (!$log->save()) {
  333. throw new \Exception('商城金额日志记录失败');
  334. }
  335. $t->commit();
  336. } catch (\Exception $e) {
  337. $t->rollBack();
  338. return false;
  339. }
  340. return true;
  341. }
  342. // 店铺增加金额
  343. public static function addMoney($store, $price, $desc = '用户下单', $order_id = 0, $user_id = 0)
  344. {
  345. $t = \Yii::$app->db->beginTransaction();
  346. try {
  347. if($order_id){
  348. $StoreAccountLog = StoreAccountLog::findOne(['order_id' => $order_id, 'user_id' => $user_id, 'store_id' => $store->id, 'type' => 1]);
  349. if($StoreAccountLog){
  350. throw new \Exception('此订单已存在商城金额增加记录');
  351. }
  352. }
  353. $before = $store->price;
  354. $store->price += $price;
  355. $store->total_price += $price;
  356. if (!$store->save()) {
  357. throw new \Exception('商城金额增加失败');
  358. }
  359. $log = new StoreAccountLog();
  360. $log->store_id = $store->id;
  361. $log->order_id = $order_id;
  362. $log->user_id = $user_id;
  363. $log->price = $price;
  364. $log->desc = $desc;
  365. $log->before = $before;
  366. $log->after = $store->price;
  367. $log->type = 1;
  368. $log->time = time();
  369. if (!$log->save()) {
  370. throw new \Exception('商城金额日志记录失败');
  371. }
  372. $t->commit();
  373. } catch (\Exception $e) {
  374. \Yii::error($e);
  375. $t->rollBack();
  376. return false;
  377. }
  378. return true;
  379. }
  380. //小程序是否开启审核
  381. public static function mpAudit($store_id) {
  382. $audit_status = Option::get('is_shenhe', $store_id, 'wechat', 0)['value'];
  383. $is_ali_shenhe = Option::get('is_ali_shenhe', $store_id, 'wechat', 0)['value'];
  384. $is_component_ali_shenhe = Option::get('is_component_ali_shenhe', $store_id, 'wechat', 0)['value'];
  385. if ((int)$is_ali_shenhe === 1 && is_alipay_platform()) {
  386. $audit_status = 1;
  387. }
  388. if ((int)$audit_status === 1 && (int)$is_ali_shenhe === 0 && is_alipay_platform()) {
  389. $audit_status = 0;
  390. }
  391. if ((int)$is_ali_shenhe === 1 && (int)$is_component_ali_shenhe === 0) {
  392. $is_ali_shenhe = 0;
  393. } elseif ((int)$is_ali_shenhe === 1 && (int)$is_component_ali_shenhe === 1 && is_alipay_platform()) {
  394. $is_ali_shenhe = 1;
  395. $audit_status = 1;
  396. }
  397. if (\Yii::$app->prod_is_dandianpu() && is_single_store()) {
  398. if (is_wechat_platform()) {
  399. $audit_status = Option::get('one_store_is_shenhe', 0, 'saas', 0)['value'];
  400. }
  401. if (is_alipay_platform()) {
  402. $one_store_alipay_config = json_decode(Option::get('one_store_alipay_config', 0, 'saas', '')['value'], true);
  403. $audit_status = !empty($one_store_alipay_config['one_store_is_shenhe']) ? $one_store_alipay_config['one_store_is_shenhe'] : 0;
  404. }
  405. }
  406. $wechat_login_toggle_article = Option::get('wechat_login_toggle_article', $store_id, 'wechat', 0)['value']; //审核页面文章
  407. $article = null;
  408. if ($wechat_login_toggle_article) {
  409. $aboutArticle = AboutArticle::findOne($wechat_login_toggle_article);
  410. $article = [
  411. 'name' => $aboutArticle->name ?? '',
  412. 'desc' => $aboutArticle->desc ?? ''
  413. ];
  414. }
  415. // 根据版本判断是否开启审核,低版本的不开启,最新版本开启
  416. if (\client_version() < \cyy_version()) {
  417. $audit_status = 0;
  418. $is_ali_shenhe = 0;
  419. }
  420. // 是否允许切换门店
  421. $mdSetting = MdSetting::findOne(['store_id' => $store_id]);
  422. $changeShop = $mdSetting->change_shop ?? 1;
  423. return [
  424. 'status' => $audit_status,
  425. 'is_ali_shenhe' => intval($is_ali_shenhe),
  426. 'article' => $article,
  427. 'change_shop' => $changeShop
  428. ];
  429. }
  430. // 店铺结算减少pv奖励金额
  431. public static function subStoreMoney($store, $price, $desc = '扣pv奖励金额', $order_id = 0, $user_id = 0 ,$huifuId = 0)
  432. {
  433. $t = \Yii::$app->db->beginTransaction();
  434. try {
  435. $before = $store->price;
  436. $store->price -= $price;
  437. if (!$store->save()) {
  438. throw new \Exception('店铺金额减少失败');
  439. }
  440. $log = new StoreAccountLog();
  441. $log->store_id = $store->id;
  442. $log->order_id = $order_id;
  443. $log->user_id = $user_id;
  444. $log->price = $price;
  445. $log->desc = $desc;
  446. $log->before = $before;
  447. $log->after = $store->price;
  448. $log->type = 2;
  449. $log->time = time();
  450. if (!$log->save()) {
  451. throw new \Exception('商城金额日志记录失败');
  452. }
  453. $t->commit();
  454. return $log->id;
  455. } catch (\Exception $e) {
  456. \Yii::error($e);
  457. $t->rollBack();
  458. return false;
  459. }
  460. }
  461. }