| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786 |
- <?php
- namespace app\common\service;
- use app\api\services\ExpressServices;
- use app\common\model\ShopCartModel;
- use app\common\model\ShopGoods;
- use app\common\model\ShopGoodsModel;
- use app\common\model\ShopGoodsSpec;
- use app\common\model\ShopOrder;
- use app\common\model\ShopOrderGoodsModel;
- use app\common\model\ShopOrderShippingModel;
- use app\common\model\UserAddressModel;
- use jobs\ShopOrderJob;
- use think\Exception;
- use think\facade\Db;
- use utils\Queue;
- use utils\RedisCache;
- /**
- * 商城订单服务 by wes
- * Class ShopOrderService
- * @package app\common\service
- */
- class ShopOrderService
- {
- protected static $instance = null;
- protected $model = null;
- public function __construct()
- {
- $this->model = new ShopOrder();
- }
- /**
- * 静态化入口
- * @return static|null
- */
- public static function make()
- {
- if (!self::$instance) {
- self::$instance = new static();
- }
- return self::$instance;
- }
- /**
- * 商城下单
- * @param $uid 用户ID
- * @param $buyGoods 购买的商品数组
- * @param $payType 支付方式
- * @param $request 请求数据
- * @param int $cartIds 购物车ID数组
- * @param int $cls 赠送月卡功能开关
- * @return array
- * @throws Exception
- */
- public function createOrder($uid, $buyGoods, $payType, $request, $cartIds = 0, $cls = 0)
- {
- // 获取收货地址信息
- $orderType = 1; // 订单类型 1商城订单 2积分订单 3.兑换券 4.锁定积分兑换 5.福袋发货订单
- $addressId = $request->post('address', '');
- $remark = $request->post('order_remark', '');
- if (!$addressId || !$userAddress = UserAddressModel::getAddressIdDetails((int)$addressId)) {
- throw new Exception('获取收货地址失败');
- }
- $addressUid = isset($userAddress['uid']) ? $userAddress['uid'] : 0;
- if ($addressUid != $uid) {
- throw new Exception('收货地址信息异常');
- }
- if (empty($buyGoods)) {
- throw new Exception('商品参数错误');
- }
- // 未支付订单数量验证
- $count = ShopOrderService::make()->checkBuyCountByTime($uid, 1, 0);
- $noPayLimit = env('common.ORDER_NO_PAY_LIMIT', 5);
- if ($count >= $noPayLimit) {
- throw new Exception("2小时内未支付的订单不能超过{$noPayLimit}个,下单失败");
- }
- // 订单商品数据处理
- $i = 0;
- $nowTime = time();
- $orderId = $this->model->max('order_id') + 1;
- $orderDatas = $orderGoods = $orders = $shippingList = [];
- $expireTime = time() + intval(env('common.ORDER_EXPIRES_TIME'));
- Db::startTrans();
- try {
- foreach ($buyGoods as $k => $v) {
- $goodsSn = isset($v['goods_sn']) ? trim($v['goods_sn']) : 0;
- $specId = isset($v['spec_id']) ? trim($v['spec_id']) : 0;
- $num = isset($v['num']) ? intval($v['num']) : 0;
- if ($num < 1) {
- throw new Exception('请先选择商品数量哦');
- }
- // 商品信息验证
- $goodsInfo = ShopGoodsService::make()->getCacheInfo($v['goods_sn']);
- if (!$goodsInfo) {
- throw new Exception('商品参数错误或已下架,请返回刷新列表');
- }
- if ($goodsInfo['goods_type'] == 2) {
- throw new Exception('商福袋商品不能购买');
- }
- // 商品限购验证
- if ($goodsInfo['restrictions_num'] > 0) {
- $count = ShopOrderGoodsService::make()->getCountByUserAndGoods($uid, $goodsSn);
- if ($count > $goodsInfo['restrictions_num']) {
- throw new Exception('超过限购');
- }
- if ($v['num'] + $count > $goodsInfo['restrictions_num']) {
- throw new Exception('超过限购数量,还可购买:' . ($goodsInfo['restrictions_num'] - $count) . '件');
- }
- }
- // 商品库存验证
- if ($goodsSn && $specId && $num > 0) {
- $stock = ShopGoodsSpecService::make()->getStock($goodsSn, $specId);
- if ($num > $stock) {
- throw new Exception('下单失败,所选商品含有库存不足的商品:SN-' . $goodsSn);
- }
- }
- // 是否赠送月卡
- $giveVip = 0;
- $goodsGiveVip = isset($goodsInfo['give_vip']) ? $goodsInfo['give_vip'] : 0;
- if ($cls == 1 && $goodsGiveVip) {
- $giveVip = $goodsGiveVip;
- }
- // 同商品订单数据
- if (!isset($orderDatas[$goodsSn]) || empty($orderDatas[$goodsSn])) {
- $orderSn = createdOrderSn();
- $orders[] = $orderSn;
- $orderId = $orderId + $i;
- $orderDatas[$goodsSn] = [
- 'order_id' => $orderId,
- 'order_sn' => $orderSn,
- 'total_price' => 0,
- 'payment' => 0,
- 'user_id' => $uid,
- 'status' => 0, // 待付款
- 'ship_postfee' => 0,
- 'rebate_score' => 0, //总返利积分
- 'created_time' => date('Y-m-d H:i:s', $nowTime + $i),
- 'updated_time' => date('Y-m-d H:i:s', $nowTime + $i),
- 'give_vip' => $giveVip,
- 'order_remark' => $remark,
- 'pay_type' => $payType,
- 'order_type' => $orderType,
- 'coupon_number' => '',
- 'expires_time' => sr_getcurtime($expireTime + $i),
- 'supplier_name' => isset($goodsInfo['supplier_name']) ? $goodsInfo['supplier_name'] : '',
- ];
- // 构建订单配送数据
- $shippingList[$orderSn] = [
- 'order_id' => $orderId,
- 'sp_name' => $userAddress['name'],
- 'sp_mobile' => $userAddress['mobile'],
- 'sp_province' => $userAddress['sp_province'],
- 'sp_city' => $userAddress['sp_city'],
- 'sp_county' => $userAddress['sp_county'],
- 'sp_remark' => $userAddress['remark'],
- 'sp_mergename' => $userAddress['mergename'],
- 'created_time' => date('Y-m-d H:i:s', $nowTime + $i),
- 'updated_time' => date('Y-m-d H:i:s', $nowTime + $i),
- ];
- $i++;
- }
- // 订单商品规格数据
- $goodsSpec = ShopGoodsSpecService::make()->getDataByGoods($goodsInfo['goods_id'], $specId);
- $goodsSpecId = isset($goodsSpec['goods_spec_id']) ? $goodsSpec['goods_spec_id'] : 0;
- $weight = isset($goodsSpec['weight']) ? $goodsSpec['weight'] : 0;
- $price = isset($goodsSpec['price']) ? $goodsSpec['price'] : 0;
- // 同一个商品数据合计
- $totalFee = bcmul($num, $price, 3);
- $totalWeight = bcmul($num, $weight, 3);
- $orderDatas[$goodsSn]['total_weight'] = isset($orderDatas[$goodsSn]['total_weight']) ? bcadd($orderDatas[$goodsSn]['total_weight'], $totalWeight, 3) : $totalWeight;
- $orderDatas[$goodsSn]['total_price'] = isset($orderDatas[$goodsSn]['total_price']) ? bcadd($orderDatas[$goodsSn]['total_price'], $totalFee, 3) : $totalFee;
- $orderDatas[$goodsSn]['num'] = isset($orderDatas[$goodsSn]['num']) ? intval($orderDatas[$goodsSn]['num'] + $num) : $num;
- // 返还积分/金额合计
- $rebateScore = isset($goodsInfo['rebate_score']) ? bcmul($num, $goodsInfo['rebate_score'], 3) : 0;
- $rebateMoney = isset($goodsInfo['rebate_money']) ? bcmul($num, $goodsInfo['rebate_money'], 3) : 0;
- $orderDatas[$goodsSn]['rebate_score'] = isset($orderDatas[$goodsSn]['rebate_score']) ? bcadd($orderDatas[$goodsSn]['rebate_score'], $rebateScore, 3) : $rebateScore;
- $orderDatas[$goodsSn]['rebate_money'] = isset($orderDatas[$goodsSn]['rebate_money']) ? bcadd($orderDatas[$goodsSn]['rebate_money'], $rebateScore, 3) : $rebateMoney;
- $orderDatas[$goodsSn]['rebate_money'] = 0; // 临时覆盖值
- // 邮费计算合计
- $postFee = 0;
- $costPostFee = true;
- if ($costPostFee) {
- $city = isset($userAddress['city']) ? $userAddress['city'] : '';
- $postData = [
- 'goods_sn' => $goodsInfo['goods_sn'],
- 'num' => $orderDatas[$goodsSn]['num'],
- 'total_price' => $orderDatas[$goodsSn]['total_price'],
- 'total_weight' => $orderDatas[$goodsSn]['total_weight'],
- ];
- $postTemplateId = isset($goodsInfo['post_template_id']) ? $goodsInfo['post_template_id'] : 0;
- $postFee = ShopOrderService::make()->postFee($city, $postData, $postTemplateId); // 邮费
- }
- $orderDatas[$goodsSn]['ship_postfee'] = $postFee;
- $orderDatas[$goodsSn]['payment'] = bcadd($orderDatas[$goodsSn]['total_price'], $postFee, 3);
- // 订单商品
- $orderGoods[] = [
- 'order_id' => $orderDatas[$goodsSn]['order_id'],
- 'goods_id' => $goodsInfo['goods_id'],
- 'goods_name' => $goodsInfo['goods_name'],
- 'goods_category' => $goodsInfo['category'],
- 'goods_img' => isset($goodsSpec['picture']) && $goodsSpec['picture'] ? $goodsSpec['picture'] : $goodsInfo['goods_img'],
- 'num' => $num,
- 'price' => $price,
- 'total_fee' => $totalFee,
- 'goods_spec_id' => $goodsSpecId,
- 'spec_ids' => isset($goodsSpec['spec_ids']) ? $goodsSpec['spec_ids'] : '',
- 'spec_text' => isset($goodsSpec['spec_text']) ? $goodsSpec['spec_text'] : '',
- 'rebate_score' => isset($goodsSpec['rebate_score']) ? $goodsSpec['rebate_score'] : 0,
- 'total_rebate_score' => $orderDatas[$goodsSn]['rebate_score'],
- 'uid' => $uid
- ];
- // 扣库存
- if (!ShopGoodsSpec::where(['goods_spec_id' => $goodsSpecId])->dec('stock', $num)->update()) {
- throw new Exception('商品库存处理失败');
- }
- // 扣除商品总库存
- if (!ShopGoods::where(['goods_id' => $goodsInfo['goods_id']])->dec('inventory', $num)->update()) {
- throw new Exception('商品库存处理失败');
- }
- // 增加销量
- if (in_array($orderType, [3, 4, 5])) {
- if (!ShopGoodsModel::where(['goods_id' => $goodsInfo['goods_id']])
- ->inc('sales_volume', $num)
- ->inc('real_sales_volume', $num)
- ->update()) {
- throw new Exception('商品销量处理失败');
- }
- }
- // 清除商品相关实时数据缓存
- RedisCache::keyDel('caches:goods:list_*');
- RedisCache::keyDel('caches:goodsSpec:list_*');
- }
- if (empty($orders) || empty($orderGoods)) {
- throw new Exception('订单数据错误,下单失败');
- }
- // 批量写入订单数据
- $data = array_values($orderDatas);
- if (!$this->model->insertAll($data)) {
- Db::rollback();
- throw new Exception('下单失败');
- }
- // 批量写入订单商品数据
- $data = array_values($orderGoods);
- if (!ShopOrderGoodsModel::insertAll($data)) {
- Db::rollback();
- throw new Exception('下单失败,订单商品处理错误');
- }
- // 写入配送单数据
- $data = array_values($shippingList);
- if (!ShopOrderShippingModel::insertAll($data)) {
- Db::rollback();
- throw new Exception('下单失败,订单配送数据处理错误');
- }
- // 超时过期订单队列任务处理
- if (in_array($orderType, [1, 3]) && $orders) {
- $ex_time = intval(env('common.ORDER_EXPIRES_TIME', 60 * 60));
- Queue::instance()->log('订单过期执行成功')
- ->job(ShopOrderJob::class)
- ->do('ShopOrderExpired')
- ->secs($ex_time)
- ->push([$orders[0]]);
- }
- // 验证检查购物车数据
- if ($cartIds && is_array($cartIds)) {
- ShopCartModel::where('id', 'in', $cartIds)->where(['user_id' => $uid])->delete();
- }
- // 清除单一购物车数据
- $cartId = $request->post('cart_id', 0);
- if ($cartId) {
- ShopCartModel::where('id', $cartId)->delete();
- }
- $cacheKey = "caches:orders:u_{$uid}_{$orderType}:create_{$payType}_" . date('YmdHis') . rand(10, 99);
- RedisCache::set($cacheKey, ['uid' => $uid, 'orderDatas' => $orderDatas, 'shipping' => $shippingList, 'orderGoods' => $orderGoods, 'post' => $request->post()], 7200);
- Db::commit();
- return $orders;
- } catch (\Exception $e) {
- throw new Exception($e->getMessage());
- }
- }
- /**
- * 下单数据
- * @param $buyGoods 购买商品
- * @param $request
- * @return array
- * @throws Exception
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\DbException
- * @throws \think\db\exception\ModelNotFoundException
- */
- public function buyDetail($buyGoods, $request)
- {
- $addressId = $request->post('address_id', 0);
- if (!$address = UserAddressModel::getAddressIdDetails($addressId, $request->uid, 1)) {
- throw new Exception('订单地址错误');
- }
- $details = $goodsSnArr = [];
- $paymentTotal = 0; // 总订单金额
- $totalRebateScore = 0; // 总返还积分
- $totalNum = 0; // 商品总数量
- $curXzmoney = SystemConfigService::make()->getConfigByName('xz_cur_money', '', 'xzconfig');
- foreach ($buyGoods as $k => $v) {
- $goodsSn = isset($v['goods_sn']) ? $v['goods_sn'] : '';
- $specId = isset($v['spec_id']) ? $v['spec_id'] : 0;
- $num = isset($v['num']) ? intval($v['num']) : 0;
- $totalNum += $num;
- if ($num <= 0) {
- throw new Exception('下单失败,请先选择商品数量');
- }
- // 商品信息
- if (!$goodsSn || !$goodsInfo = ShopGoodsService::make()->getCacheInfo($goodsSn)) {
- throw new Exception('下单失败,商品参数错误');
- }
- // 订单商品规格数据
- $goodsSnArr[] = $goodsSn;
- $goodsSpec = ShopGoodsSpecService::make()->getDataByGoods($goodsInfo['goods_id'], $specId);
- $weight = isset($goodsSpec['weight']) ? $goodsSpec['weight'] : 0;
- $price = isset($goodsSpec['price']) ? $goodsSpec['price'] : 0;
- if (empty($goodsSpec)) {
- throw new Exception('下单失败,存在无效商品');
- }
- // 商品数据
- $postFee = '0.00';
- $rebateScore = bcmul($num, $goodsSpec['rebate_score'], 2);
- $totalFee = bcmul($num, $price, 2);
- $totalWeight = bcmul($num, $weight, 3);
- // 组装订单商品数据
- $details[$goodsSn]['total_rebate_score'] = isset($details[$goodsSn]['total_rebate_score']) ? bcadd($details[$goodsSn]['total_rebate_score'], $rebateScore, 3) : $rebateScore; //总返利积分
- $details[$goodsSn]['total_num'] = isset($details[$goodsSn]['total_num']) ? bcadd($details[$goodsSn]['total_num'], $num, 3) : $num; //总数量
- $details[$goodsSn]['total_price'] = isset($details[$goodsSn]['total_price']) ? bcadd($details[$goodsSn]['total_price'], $totalFee, 3) : $totalFee; // 总金额
- $details[$goodsSn]['total_weight'] = isset($details[$goodsSn]['total_weight']) ? bcadd($details[$goodsSn]['total_weight'], $totalWeight, 3) : $totalWeight; // 总重量
- $details[$goodsSn]['post_fee'] = $postFee;
- $details[$goodsSn]['payment'] = bcadd($details[$goodsSn]['total_price'], $details[$goodsSn]['post_fee'], 2);
- $details[$goodsSn]['supplier_name'] = $goodsInfo['supplier_name'];
- $goodsName = isset($goodsInfo['goods_name']) ? $goodsInfo['goods_name'] : '';
- $goodsName = $goodsName ? str_replace(' ', '', $goodsName) : '';
- $goodsName = mb_strlen($goodsName, 'utf-8') > 20 ? mb_substr($goodsName, 0, 19, 'utf-8') : $goodsName;
- $goodsType = isset($goodsInfo['goods_type']) ? $goodsInfo['goods_type'] : 0;
- if ($goodsType == 5) {
- $price = getXzPirceWithPrice($curXzmoney, $price);
- $totalFee = getXzPirceWithPrice($curXzmoney, $totalFee);
- }
- $goods = [
- 'goods_sn' => $goodsInfo['goods_sn'],
- 'goods_id' => $goodsInfo['goods_id'],
- 'goods_type' => $goodsType,
- 'goods_name' => $goodsName,
- 'picture' => $goodsSpec['picture'] ?: $goodsInfo['goods_img'],
- 'num' => $num, //数量
- 'price' => $price,//单价
- 'weight' => $goodsSpec['weight'], //重量
- 'total_fee' => $totalFee, //总价
- 'rebate_score' => $goodsSpec['rebate_score'],//单个返利积分
- 'total_items_rebate_score' => $rebateScore,//总返利积分
- 'spec_ids' => $goodsSpec['spec_ids'],
- 'spec_text' => $goodsSpec['spec_text'],
- 'post_template_id' => $goodsInfo['post_template_id'], //是否包邮,否就是运费模板ID
- 'stock' => $goodsSpec['stock'],
- 'supplier_name' => $goodsInfo['supplier_name']
- ];
- // 参数合计
- $totalNum += $num;
- $paymentTotal += bcadd($totalFee, $postFee, 3);
- $totalRebateScore = bcadd($totalRebateScore, $rebateScore, 3);
- $details[$goodsSn]['goods'][] = $goods;
- }
- $total = [
- 'count_payment' => sprintf("%.2f", $paymentTotal),
- 'count_rebate_score' => $totalRebateScore,
- 'count_num' => $totalNum,
- ];
- return ['address' => $address, 'buyDetail' => array_values($details), 'total' => $total];
- }
- /**
- * 取消订单
- */
- public function cancelOrder($data, $userId)
- {
- $nowTime = date('Y-m-d H:i:s', time());
- $data = $this->model->where(['order_sn' => $data['order_sn'], 'user_id' => $userId])->field('order_id,status,order_sn')->findOrEmpty();
- if (empty($data)) {
- throw new Exception('参数错误');
- }
- if ($data['status'] != 0) {
- throw new Exception('订单状态错误');
- }
- Db::startTrans();
- if (!$this->model->where(['order_sn' => $data['order_sn']])->save(['status' => 3, 'updated_time' => $nowTime])) {
- Db::rollback();
- throw new Exception('取消失败');
- }
- // 恢复库存
- $updateStock = $this->model->alias('a')->where(['a.order_sn' => $data['order_sn'], 'a.user_id' => $userId])
- ->leftJoin('shop_order_goods og', 'og.order_id=a.order_id')
- ->leftJoin('shop_goods_spec gs', 'gs.goods_spec_id=og.goods_spec_id')
- ->leftJoin('shop_goods g', 'g.goods_id=og.goods_id')
- ->update([
- 'g.inventory'=> Db::raw('g.inventory + og.num'),
- 'gs.stock'=> Db::raw('gs.stock + og.num'),
- ]);
- if (!$updateStock) {
- Db::rollback();
- throw new Exception('取消失败,库存处理错误');
- }
- Db::commit();
- return true;
- }
- /**
- * 确定订单
- */
- public function receiveOrder($data, $userId)
- {
- $nowTime = date('Y-m-d H:i:s', time());
- $data = $this->model->where(['order_sn' => $data['order_sn'], 'user_id' => $userId])->findOrEmpty()->toArray();
- if (empty($data)) {
- throw new Exception('参数错误');
- }
- if ($data['status'] != 2) {
- throw new Exception('订单状态错误');
- }
- return $this->model->where(['order_sn' => $data['order_sn']])->save(['status' => 4, 'updated_time' => $nowTime]);
- }
- /**
- * 计算运费
- * @param $address 用户地址
- * @param $data 商品数据
- * @param $express_template_id 模板ID
- * 获取运费
- */
- public function postFee($address, $data, $express_template_id)
- {
- //获取运费模板
- $expressDelivery = ExpressDeliveryService::make()->getDataByTemplate($express_template_id);
- //获取运费模板列表
- $expressDeliveryItems = ExpressShippingMethodService::make()->getListByTemplate($express_template_id);
- $price_method_field = '';
- switch ($expressDelivery['price_method']) {
- case 1:
- $price_method_field = $data['total_price']; //按金额
- break;
- case 2:
- $price_method_field = $data['num']; //按件数
- break;
- case 3:
- $price_method_field = $data['total_weight']; //按重量
- break;
- default:
- break;
- }
- if ($expressDelivery['price_method'] == 1) {
- //计算默认运费 【配送区域、免运费金额、达标时运费、未达标时运费;】
- if ($price_method_field < $expressDelivery['default_free_price']) {
- $default_postfee = $expressDelivery['default_fastandard_price'];
- } else {
- //达标时运费
- $default_postfee = $expressDelivery['default_price'];
- }
- if (empty($expressDeliveryItems)) {
- return $default_postfee;
- }
- //按指定地区计算邮费
- foreach ($expressDeliveryItems as $k => $node) {
- if (in_array($address, explode(',', $node['address_items_ids']))) {
- //未达标运费
- if ($price_method_field < $node['free_price']) {
- return $node['fastandard_price'];
- } else {
- //达标时运费
- return $node['price'];
- }
- } else {
- return $default_postfee;
- }
- }
- } else {
- //按件数 重量计费 【配送区域、首件、达标时运费、续件、未达标时运费】
- //计算默认运费
- if ($price_method_field <= $expressDelivery['default_pieces']) {
- $default_postfee = $expressDelivery['default_price'];
- } else {
- //达到续件条件时的运费
- if ($expressDelivery['add_pieces']) {
- //配置过续件费用
- //续件数 = (下单件数 - 首件) /续件数
- //总运费 = 首件运费 + (续件数 * 续件费用)
- $add_pieces = bcdiv(($price_method_field - $expressDelivery['default_pieces']), $expressDelivery['add_pieces'], 2);
- $default_postfee = bcadd($expressDelivery['default_price'], bcmul($add_pieces, $expressDelivery['add_price'], 2), 2);
- } else {
- //未配置过续件,按首件价格
- $default_postfee = $expressDelivery['default_price'];
- }
- }
- if (empty($expressDeliveryItems)) {
- return $default_postfee;
- }
- //按指定地区计算邮费
- foreach ($expressDeliveryItems as $k => $node) {
- if (in_array($address, explode(',', $node['address_items_ids']))) {
- //未达到续件条件时的运费
- if ($price_method_field <= $node['pieces']) {
- return $node['price'];
- } else {
- //达到续件条件时的运费
- if ($node['add_pieces']) {
- //配置过续件费用
- //续件数 = (下单件数 - 首件) /续件数
- //总运费 = 首件运费 + (续件数 * 续件费用)
- $add_pieces = bcdiv(($price_method_field - $node['pieces']), $node['add_pieces'], 2);
- return bcadd($node['price'], bcmul($add_pieces, $node['add_price'], 2), 2);
- } else {
- //未配置过续件,按首件价格
- return $node['price'];
- }
- }
- } else {
- return $default_postfee;
- }
- }
- }
- }
- /**
- * 验证商品库存
- * @param $data
- * @return bool
- */
- public function checkStock($data)
- {
- foreach ($data as $key => $value) {
- $num = array_sum(array_column($value, 'num'));
- $goodsSn = isset($value[0]['goods_sn']) ? $value[0]['goods_sn'] : 0;
- $specId = isset($value[0]['spec_id']) ? $value[0]['spec_id'] : 0;
- if ($goodsSn && $specId && $num > 0) {
- $stock = ShopGoodsSpecService::make()->getStock($goodsSn, $specId);
- if ($num > $stock) {
- return false;
- }
- } else {
- return false;
- }
- }
- return true;
- }
- /**
- * 2小时内未付款订单数
- * @param $uid
- * @param int $orderType
- * @param int $status
- * @return array|int|mixed
- * @throws \think\db\exception\DbException
- */
- public function checkBuyCountByTime($uid, $orderType = 1, $status = 0)
- {
- $cacheKey = "caches:orders:unpayCount:{$uid}_{$orderType}_{$status}";
- $data = RedisCache::get($cacheKey);
- if ($data) {
- return $data;
- }
- $data = $this->model->where(['user_id' => $uid, 'order_type' => $orderType, 'status' => $status])
- ->whereTime('created_time', '-2 hours')
- ->count('order_id');
- if ($data) {
- RedisCache::set($cacheKey, $data, rand(3, 5));
- }
- return $data;
- }
- /**
- * 根据单号获取订单信息(有缓存)
- * @param $orderSn 订单号
- * @param int $uid 所属用户ID
- * @param int $status 状态
- * @param string $field 返沪字段
- * @param bool $cache 是否缓存,默认是
- * @return array|mixed
- */
- public function getInfoBySn($orderSn, $uid=0, $status=0, $field='', $cache=false)
- {
- $cacheKey = "caches:orders:info:sn{$orderSn}_{$uid}".($field? '_'.md5($field):'');
- $data = RedisCache::get($cacheKey);
- if($data && $cache){
- return $data;
- }
- $where = ['order_sn'=> $orderSn];
- if($uid>0){
- $where['user_id'] = $uid;
- }
- if($status>0){
- $where['status'] = $status;
- }
- $field = $field? $field : 'order_id,order_sn,user_id,payment,total_price,status,pay_type,rebate_score,rebate_money,num,order_type,give_vip';
- $data = $this->model->where($where)->field($field)->findOrEmpty();
- $data = $data? $data->toArray() : [];
- if($data && $cache){
- RedisCache::set($cacheKey, $data, rand(5,10));
- }
- return $data;
- }
- /**
- * 根据单号获取订单信息(有缓存)
- * @param $orderSn 订单号
- * @param int $uid 所属用户ID
- * @param string $field 返沪字段
- * @param bool $cache 是否缓存,默认是
- * @return array|mixed
- */
- public function getInfoById($orderId, $uid=0, $field='', $cache=true)
- {
- $cacheKey = "caches:orders:info:id{$orderId}_{$uid}".($field? '_'.md5($field):'');
- $data = RedisCache::get($cacheKey);
- if($data && $cache){
- return $data;
- }
- $where = ['order_id'=> $orderId,'user_id'=> 0,'status'=>1];
- if($uid>0){
- $where['user_id'] = $uid;
- }else{
- unset($where['user_id']);
- }
- $field = $field? $field : 'order_id,order_sn,user_id,payment,total_price,status,pay_type,rebate_score,rebate_money,num,order_type,give_vip,coupon_number,hg_status,hg_enable';
- $data = $this->model->where($where)->field($field)->findOrEmpty();
- $data = $data? $data->toArray() : [];
- if($data && $cache){
- RedisCache::set($cacheKey, $data, rand(5,10));
- }
- return $data;
- }
- /**
- * 订单列表
- */
- public function getList ($params, $pageSize, $field = '')
- {
- $page = request()->post('page', 1);
- $userId = isset($params['user_id'])? $params['user_id'] : 0;
- $cacheKey = "caches:orders:list:{$userId}_{$page}_{$pageSize}".($field? '_'.md5($field):'');
- $data = RedisCache::get($cacheKey);
- if($data){
- return $data;
- }
- $where['user_id'] = $userId;
- $status = isset($params['status'])? $params['status'] : '-1';
- if($status>=0){
- $where['status'] = $status;
- }
- $orderType = isset($params['order_type'])? $params['order_type'] : 0;
- if($orderType){
- $where['order_type'] = $orderType;
- }
- $field = $field? $field:'order_id,status,order_sn,order_type,coupon_number,created_time,order_remark,payment,ship_postfee,rebate_score,ship_name,ship_code,ship_number,expires_time,rebate_lock_score';
- $data = $this->model->where($where)
- ->whereNotIn('status', [3])
- ->relation(['withOrderGoods'])
- ->field($field)
- ->order('order_id desc')
- ->paginate($pageSize)
- ->each(function($v, $k){
- foreach ($v['withOrderGoods'] as $key=>$val){
- $goods_sn = ShopGoods::where('goods_id', $val['goods_id'])->value('goods_sn');
- $v['withOrderGoods'][$key]['goods_sn'] = $goods_sn;
- }
- $v['withOrderShipping'] = ShopOrderShippingService::make()->getInfo($v['order_id']);
- $v['withOrderExpress'] = ExpressServices::instance()->orderId($v['order_id'])
- ->code($v['ship_code'])
- ->number($v['ship_number'])
- ->find();
- if (intval($v['status']) == 2){
- $v['express_url'] = "https://m.kuaidi100.com/result.jsp?nu=".$v['ship_number'];
- }else{
- $v['express_url'] = "";
- }
- if ($v['status'] == 1){
- if ($v['order_type'] == 1){
- $v['can_hg'] = 1;
- }
- }else{
- $v['can_hg'] = 2;
- }
- switch ($v['status']){
- case 0:
- $v['status_title'] = '待付款';
- break;
- case 1:
- $v['status_title'] = '待发货';
- break;
- case 2:
- $v['status_title'] = '已发货';
- break;
- case 3:
- $v['status_title'] = '已过期';
- break;
- case 4:
- $v['status_title'] = '已完成';
- break;
- case 5:
- $v['status_title'] = '已完成';
- break;
- case 6:
- $v['status_title'] = '已完成';
- break;
- }
- });
- $data = $data? $data->toArray() : [];
- if($data['data']){
- RedisCache::set($cacheKey, $data['data'], rand(2,3));
- }
- return $data['data'];
- }
- }
|