OrderDeleteForm.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. <?php
  2. namespace common\models\forms;
  3. use common\helpers\Cache;
  4. use common\helpers\Date;
  5. use common\components\Model;
  6. use common\helpers\Form;
  7. use common\helpers\user\Balance;
  8. use common\helpers\user\Cash;
  9. use common\helpers\user\Info;
  10. use common\libs\logging\operate\AdminOperate;
  11. use common\models\DealType;
  12. use common\models\Order;
  13. use common\models\OrderGoods;
  14. use common\models\Period;
  15. use common\models\ReceiveAddress;
  16. use common\models\Region;
  17. use common\models\ShopGoods;
  18. use common\models\User;
  19. use common\models\UserNetwork;
  20. use yii\base\Exception;
  21. /**
  22. * 删除订单
  23. */
  24. class OrderDeleteForm extends Model
  25. {
  26. public $orderSn;
  27. /**
  28. * @var Order
  29. */
  30. private $_model;
  31. /**
  32. * @inheritdoc
  33. */
  34. public function rules()
  35. {
  36. return [
  37. [['orderSn'], 'trim'],
  38. [['orderSn'], 'required'],
  39. [['orderSn'], 'checkOrderType'],
  40. ];
  41. }
  42. public function attributeLabels()
  43. {
  44. return [
  45. 'orderSn' => '订单号',
  46. ];
  47. }
  48. /**
  49. * 指定校验场景
  50. * @return array
  51. */
  52. public function scenarios()
  53. {
  54. $parentScenarios = parent::scenarios();
  55. $customScenarios = [
  56. // // 管理员发货
  57. // 'adminDelivery' => ['sn', 'expressCompany', 'orderTrackNo'],
  58. // // 会员确认收货
  59. // 'userConfirm' => ['sn', 'expressCompany', 'orderTrackNo'],
  60. // // 管理员修改订单状态
  61. // 'adminStatus' => ['sn', 'status'],
  62. // // 管理员修改备注
  63. // 'adminRemark' => ['sn', 'remark'],
  64. // // 会员下单
  65. // 'userOrder' => ['type','addressId', 'payType','goodsId','goodsNum', 'remark', 'payPassword'],
  66. // // 帮会员复消下单
  67. // 'reconsumeOrder' => ['type','userName', 'payType','goodsId','goodsNum', 'remark', 'payPassword','consignee','acceptMobile','province','city','county','detailaddress'],
  68. ];
  69. return array_merge($parentScenarios, $customScenarios);
  70. }
  71. // /**
  72. // * 校验之前
  73. // * @return bool
  74. // */
  75. // public function beforeValidate()
  76. // {
  77. // $parentValidate = parent::beforeValidate();
  78. // if ($this->sn) {
  79. // $this->_model = Order::findOne(['SN'=>$this->sn]);
  80. // if (!$this->_model){
  81. // $this->addError('sn', '订单不存在');
  82. // return false;
  83. // }
  84. // }
  85. // if ($this->scenario == 'adminDelivery'){
  86. // if($this->_model['STATUS'] == \Yii::$app->params['orderStatus']['cancel']) {
  87. // $this->addError('sn', '订单已取消不能发货');
  88. // return false;
  89. // }
  90. // if($this->_model['STATUS'] == \Yii::$app->params['orderStatus']['del']) {
  91. // $this->addError('sn', '订单已删除不能发货');
  92. // return false;
  93. // }
  94. // }
  95. // return $parentValidate;
  96. // }
  97. public function returnOrder() {
  98. if(!$this->validate()){
  99. return null;
  100. }
  101. }
  102. /**
  103. * 判断支付方式
  104. * @param $attribute
  105. */
  106. public function isPayType($attribute){
  107. if(!array_key_exists($this->payType, ShopGoods::payTypes())){
  108. $this->addError($attribute, '支付方式错误');
  109. return;
  110. }
  111. }
  112. // 判断订单类型
  113. public function checkOrderType($attribute) {
  114. $this->addError($attribute, $this->orderSn);
  115. return ;
  116. }
  117. /**
  118. * 校验类型
  119. * @param $attribute
  120. */
  121. public function isStatus($attribute){
  122. if(!in_array($this->type, \Yii::$app->params['orderStatus'])){
  123. $this->addError($attribute, '类型错误');
  124. return ;
  125. }
  126. if ($this->scenario == 'adminStatus'){
  127. if ($this->status == $this->_model['STATUS']) {
  128. $this->addError($attribute, '订单状态没有改变');
  129. return ;
  130. }
  131. if($this->status == \Yii::$app->params['orderStatus']['notPaid'] && $this->_model['STATUS'] >= \Yii::$app->params['orderStatus']['delivery']) {
  132. $this->addError($attribute, '订单已经进入物流状态不能改为未支付');
  133. return ;
  134. }
  135. elseif($this->status == \Yii::$app->params['orderStatus']['paid'] && $this->_model['STATUS'] >= \Yii::$app->params['orderStatus']['cancel']) {
  136. $this->addError($attribute, '订单已失效不能处理');
  137. return ;
  138. }
  139. elseif($this->status == \Yii::$app->params['orderStatus']['delivery']) {
  140. $this->addError($attribute, '订单不能单独处理为物流状态');
  141. return ;
  142. }
  143. elseif($this->status == \Yii::$app->params['orderStatus']['complete'] && $this->_model['STATUS'] > \Yii::$app->params['orderStatus']['cancel']) {
  144. $this->addError($attribute, '订单已失效不能处理');
  145. return ;
  146. }
  147. elseif($this->status == \Yii::$app->params['orderStatus']['cancel']) {
  148. if($this->_model['STATUS'] == \Yii::$app->params['orderStatus']['complete']) {
  149. $this->addError($attribute, '订单已完成不能取消');
  150. return ;
  151. }
  152. if($this->_model['STATUS'] == \Yii::$app->params['orderStatus']['del']) {
  153. $this->addError($attribute, '订单已删除不能取消');
  154. return ;
  155. }
  156. }
  157. elseif($this->status == \Yii::$app->params['orderStatus']['del']) {
  158. if($this->_model['STATUS'] == \Yii::$app->params['orderStatus']['complete']) {
  159. $this->addError($attribute, '订单已完成不能删除');
  160. return ;
  161. }
  162. }
  163. }
  164. }
  165. /**
  166. * 帮会员复销
  167. * @return bool|null
  168. * @throws Exception
  169. * @throws \yii\db\Exception
  170. */
  171. public function reconsumeAdd(){
  172. if(!$this->validate()){
  173. return null;
  174. }
  175. $ids = $this->goodsId;
  176. $totalAmount = 0;
  177. $totalPv = 0;
  178. $goodsType = ShopGoods::GOODS_TYPE;
  179. foreach ($this->goodsNum as $k => $v) {
  180. if ($v) {
  181. $goods = ShopGoods::findOneAsArray('ID=:ID AND STATUS=1',[':ID'=> $ids[$k]]);
  182. if($goods['STORE_NUMS']>0){
  183. if ($goods['TYPE'] == 1 || $goods['TYPE'] == 2) {
  184. $discount = $goodsType[$goods['TYPE']]['discount'];
  185. $realPrice = $goods['SELL_PRICE'] * $discount/100;
  186. $realPv = $goods['PRICE_PV'] * $discount/100;
  187. } else {
  188. $discount = $goods['SELL_DISCOUNT'];
  189. $realPrice = $goods['SELL_PRICE'] * $discount;
  190. $realPv = $goods['PRICE_PV'] * $discount;
  191. }
  192. $totalAmount += $realPrice * intval($v);
  193. $totalPv += $realPv * intval($v);
  194. $this->_orderGoods[] = [
  195. 'GOODS_ID' => $goods['ID'],
  196. 'PRICE' => $goods['SELL_PRICE'],
  197. 'PV' => $goods['PRICE_PV'],
  198. 'REAL_PRICE' => $realPrice,
  199. 'REAL_PV' => $realPv,
  200. 'POINT' => $goods['POINT'],
  201. 'BUY_NUMS' => intval($v),
  202. 'SKU_CODE' => $goods['GOODS_NO'],
  203. 'GOODS_TITLE' => $goods['GOODS_NAME']
  204. ];
  205. }
  206. }
  207. }
  208. $this->_decAmount = $totalAmount;
  209. $this->_decPv = $totalPv;
  210. $this->_freight = ($totalAmount>=300) ? 0 : 15;
  211. $this->_payAmount = $this->_decAmount + $this->_freight;
  212. $db = \Yii::$app->db;
  213. $transaction = $db->beginTransaction();
  214. try {
  215. $loginUserId = \Yii::$app->user->id;
  216. //是否开启伞下会员限制
  217. $isResaleUmbrella = Cache::getSystemConfig()['isResaleUmbrella']['VALUE'];
  218. if($isResaleUmbrella){
  219. $userId = Info::getUserIdByUserName($this->userName);
  220. $userNetwork = UserNetwork::find()->where("USER_ID=:USER_ID AND INSTR(PARENT_UIDS,'{$loginUserId}')>0", ['USER_ID'=>$userId])->count();
  221. if(!$userNetwork){
  222. throw new Exception($this->userName.'不是您的伞下会员,不能为其复消!');
  223. }
  224. }
  225. //判断用户余额是否充足
  226. if($this->payType=='cash') {
  227. if (Cash::getAvailableBalance($loginUserId) < $this->_payAmount) {
  228. throw new Exception('余额不足,无法购买商品');
  229. }
  230. }else{
  231. if ($this->_payAmount > Balance::getBalanceReconsumePoints($loginUserId)) {
  232. throw new Exception('复消积分不足,无法购买商品');
  233. }
  234. }
  235. //写入订单
  236. if (!$orderResult = $this->addUserOrder()) {
  237. throw new Exception(Form::formatErrorsForApi($orderResult->getErrors()));
  238. }
  239. $transaction->commit();
  240. }catch (\Exception $e){
  241. $transaction->rollBack();
  242. $this->addError('add', $e->getMessage());
  243. return null;
  244. }
  245. return true;
  246. }
  247. /**
  248. * 帮会员复消的订单
  249. */
  250. public function addUserOrder(){
  251. $periodObj = Period::instance();
  252. $nowPeriodNum = $periodObj->getNowPeriodNum();
  253. $nowCalcMonth = $periodObj->getYearMonth($nowPeriodNum);
  254. //帮复消会员Id(登陆会员)
  255. $loginUserId = \Yii::$app->user->id;
  256. $loginUserName = Info::getUserNameByUserId($loginUserId);
  257. //订单会员Id
  258. $userId = Info::getUserIdByUserName($this->userName);
  259. // 加入订单信息
  260. $warehouse = Region::getWarehouseByCode($this->province);//仓库
  261. if(!$warehouse){
  262. throw new Exception('地区暂时不支持配送,具体联系客服');
  263. }
  264. $ordNo = $this->_generateSn();
  265. $orderModel = new Order();
  266. $orderModel->SN = 'OS'.$ordNo;
  267. $orderModel->DEC_SN = 'DS'.$ordNo;
  268. $orderModel->ORDER_TYPE = $this->type;
  269. $orderModel->USER_ID = $userId;
  270. $orderModel->USER_NAME = $this->userName;
  271. $orderModel->ORDER_AMOUNT = $this->_decAmount;
  272. $orderModel->PV = $this->_decPv;
  273. $orderModel->PAY_AMOUNT = $this->_payAmount;
  274. $orderModel->PAY_PV = $this->_decPv;
  275. $orderModel->PAY_AT = Date::nowTime();
  276. $orderModel->PAY_TYPE = $this->payType;
  277. $orderModel->PERIOD_NUM = $nowPeriodNum;
  278. $orderModel->P_CALC_MONTH = Date::ociToDate($nowCalcMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH);
  279. $orderModel->FREIGHT = $this->_freight;
  280. $orderModel->PAY_FREIGHT = $this->_freight;
  281. $orderModel->CONSIGNEE = $this->consignee;
  282. $orderModel->MOBILE = $this->acceptMobile;
  283. $orderModel->PROVINCE = $this->province;
  284. $orderModel->CITY = $this->city;
  285. $orderModel->COUNTY = $this->county;
  286. $orderModel->ADDRESS = $this->detailaddress;
  287. $orderModel->FRONT_REMARK = $this->remark;
  288. $orderModel->WAREHOUSE = $warehouse;
  289. $orderModel->STATUS = 1;
  290. $orderModel->CREATED_AT = Date::nowTime();
  291. $orderModel->CREATE_USER = $loginUserName;
  292. if(!$orderModel->save()){
  293. $this->addErrors($orderModel->getErrors());
  294. return false;
  295. }
  296. // 加入商品到订单商品表
  297. foreach($this->_orderGoods as $key=>$value){
  298. $this->_orderGoods[$key]['ORDER_SN'] = $orderModel->SN;
  299. $this->_orderGoods[$key]['P_CALC_MONTH'] = Date::ociToDate($nowCalcMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH);
  300. }
  301. OrderGoods::batchInsert($this->_orderGoods);
  302. //扣除会员余额/积分
  303. if($this->payType=='cash') {
  304. Cash::changeUserCash($loginUserId, 'CASH', -abs($this->_payAmount), ['REMARK' => '会员复销余额支付']);
  305. }else{
  306. Balance::changeUserBonus($loginUserId,'reconsume_points', -abs($this->_payAmount),['DEAL_TYPE_ID' => DealType::RECONSUME_POINTS_EXCHANGE, 'REMARK' => '会员复销积分兑换']);
  307. }
  308. return $orderModel;
  309. }
  310. /**
  311. * 生成流水号
  312. * @return string
  313. */
  314. private function _generateSn() {
  315. return Date::today('Ymd') . $this->_random(10, 1);
  316. }
  317. /**
  318. * 生成随机数
  319. * @param $length
  320. * @param int $numeric
  321. * @return string
  322. */
  323. private function _random($length, $numeric = 0) {
  324. $seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
  325. $seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed));
  326. $hash = '';
  327. $max = strlen($seed) - 1;
  328. for ($i = 0; $i < $length; $i++) {
  329. $hash .= $seed[mt_rand(0, $max)];
  330. }
  331. return $hash;
  332. }
  333. }