You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
7.9 KiB
228 lines
7.9 KiB
<?php
|
|
|
|
|
|
namespace backend\modules\shop\logic\delivery;
|
|
|
|
use backend\modules\shop\models\ars\Delivery;
|
|
use backend\modules\shop\models\ars\DeliveryGoods;
|
|
use backend\modules\shop\models\ars\Order;
|
|
use backend\modules\shop\models\ars\OrderGoods;
|
|
use Yii;
|
|
use yii\db\Exception;
|
|
use yii\helpers\ArrayHelper;
|
|
use yii\helpers\Json;
|
|
use yii\web\NotFoundHttpException;
|
|
|
|
class DeliveryManager
|
|
{
|
|
const LOGISTICS_URL = 'http://route.showapi.com/64-19';
|
|
|
|
/**
|
|
* @param Order $order
|
|
* @param Delivery $delivery
|
|
* @return array
|
|
* 订单发货
|
|
*/
|
|
public static function orderDelivery($order, $delivery)
|
|
{
|
|
$transaction = Yii::$app->db->beginTransaction();
|
|
try {
|
|
$data = Yii::$app->request->post();
|
|
if (empty($data['deliveryGoods'])) {
|
|
throw new Exception('缺少发货商品信息');
|
|
}
|
|
$delivery->load($data);
|
|
$delivery->order_id = $order->id;
|
|
if (!$delivery->save()) {
|
|
throw new Exception('保存物流信息失败');
|
|
}
|
|
|
|
/*发货商品数据*/
|
|
$orderStatus = self::saveDeliveryGoods($data['deliveryGoods'], $delivery->id);
|
|
$order->status = $orderStatus;
|
|
if (!$order->save()) {
|
|
throw new Exception('order shipping_status update false');
|
|
}
|
|
|
|
if ($orderStatus == Order::STATUS_SHIPMENT_PORTION || Delivery::find()->where(['!=', 'id', $delivery->id])->andWhere(['order_id' => $delivery->order_id])->one()) {
|
|
$delivery->type = Delivery::TYPE_SHIPMENT_PORTION;
|
|
} else {
|
|
$delivery->type = Delivery::TYPE_SHIPMENT_ALL;
|
|
}
|
|
if (!$delivery->save()) {
|
|
throw new Exception('保存物流信息失败');
|
|
}
|
|
|
|
$transaction->commit();
|
|
return ['status' => true];
|
|
} catch (Exception $e) {
|
|
$transaction->rollBack();
|
|
return ['status' => false, 'info' => $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $deliveryGoods
|
|
* @param $delivery_id
|
|
* @return int
|
|
* @throws Exception
|
|
* 保存发货商品信息
|
|
*/
|
|
private static function saveDeliveryGoods($deliveryGoods, $delivery_id)
|
|
{
|
|
$status = Order::STATUS_SHIPMENT_ALL;
|
|
foreach ($deliveryGoods as $id => $goodsCount) {
|
|
if ($goodsCount < 0) {
|
|
throw new Exception('操作异常,发货数量不能小于0');
|
|
} elseif ($goodsCount == 0) {
|
|
continue;
|
|
}
|
|
$orderGoods = OrderGoods::findOne($id);
|
|
|
|
/*如果是发货数量不是全部,订单状态为部分发货*/
|
|
$deliveryGoodsCount = DeliveryGoods::find()->where(['order_goods_id' => $id])->sum('goods_count');
|
|
if (($deliveryGoodsCount + $goodsCount) < $orderGoods->goods_count) { //如果已发货数量未达到order_goods里的数量
|
|
$status = Order::STATUS_SHIPMENT_PORTION;
|
|
} elseif (($deliveryGoodsCount + $goodsCount) > $orderGoods->goods_count) {
|
|
throw new Exception('操作异常,现发货数量超过之前缺少的发货数量');
|
|
}
|
|
|
|
$model = new DeliveryGoods();
|
|
$model->delivery_id = $delivery_id;
|
|
$model->order_goods_id = $orderGoods->id;
|
|
$model->goods_id = $orderGoods->goods_id;
|
|
$model->goods_name = $orderGoods->goods_name;
|
|
$model->goods_count = $goodsCount;
|
|
if (!$model->save()) {
|
|
throw new Exception('delivery_goods save false');
|
|
}
|
|
}
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* @param $order_id
|
|
* @return array
|
|
* 查询订单发货商品信息
|
|
*/
|
|
public static function deliveryGoodsInfo($order_id)
|
|
{
|
|
$delivery = Delivery::findAll(['order_id' => $order_id]);
|
|
/*如果该订单是首次发货*/
|
|
if ($delivery) {
|
|
/*获取订单已发的商品和未发的商品*/
|
|
return self::getDeliveryGoodsInfo($delivery);
|
|
} else {
|
|
$unShippedGoods = OrderGoods::find()->where(['order_id' => $order_id])->all();
|
|
return ['unShipped' => $unShippedGoods];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $delivery
|
|
* @return array
|
|
* 获取订单已发的商品和未发的商品
|
|
*/
|
|
public static function getDeliveryGoodsInfo($delivery)
|
|
{
|
|
$data = [];
|
|
$deliveryIds = [];
|
|
foreach ($delivery as $k => $value) {
|
|
$deliveryIds[] = $value->id;
|
|
$orderGoodsIds = DeliveryGoods::find()
|
|
->select('order_goods_id')
|
|
->where(['delivery_id' => $value->id])
|
|
->andWhere(['>', 'goods_count', 0])
|
|
->column();
|
|
$value->deliveryGoods = OrderGoods::findAll($orderGoodsIds);
|
|
}
|
|
$data['shipped'] = $delivery;
|
|
|
|
$deliveryGoodsData = [];
|
|
$deliveryGoods = DeliveryGoods::find()
|
|
->select(['order_goods_id', 'goods_count'])
|
|
->where(['delivery_id' => $deliveryIds])
|
|
->andWhere(['>', 'goods_count', 0])
|
|
->all();
|
|
foreach ($deliveryGoods as $k => $value) {
|
|
$orderGoods = $value->order_goods_id;
|
|
if (isset($deliveryGoodsData[$orderGoods])) {
|
|
$deliveryGoodsData[$orderGoods] += $value->goods_count;
|
|
} else {
|
|
$deliveryGoodsData[$orderGoods] = $value->goods_count;
|
|
}
|
|
}
|
|
foreach ($deliveryGoodsData as $k => $value) { //键名为order_goods_id,键值为对应的已发货数量
|
|
$orderGoods = OrderGoods::findOne($k); //通过orderGoods_id找到订单商品
|
|
if ($value < $orderGoods->goods_count) { //如果已发货数量未达到order_goods里的数量
|
|
$orderGoods->lack_number = $orderGoods->goods_count - $value;
|
|
$data['unShipped'][] = $orderGoods;
|
|
}
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @param $orderId
|
|
* @return array|mixed
|
|
* @throws NotFoundHttpException
|
|
* 查询物流接口
|
|
*/
|
|
public static function queryLogistics($orderId)
|
|
{
|
|
$delivery = Delivery::findOne(['order_id' => $orderId]);
|
|
if (!$delivery) {
|
|
throw new NotFoundHttpException('发货信息未找到');
|
|
}
|
|
|
|
$cache = Yii::$app->cache;
|
|
if ($cache->exists($delivery->shipping_id)) {
|
|
return $cache->get($delivery->shipping_id);
|
|
}
|
|
|
|
$logisticsParams = self::createLogisticsParam($delivery); //创建参数(包括签名的处理)
|
|
$url = self::LOGISTICS_URL . '?' . $logisticsParams;
|
|
$result = Json::decode(file_get_contents($url), false);
|
|
if (isset($result->showapi_res_body)) {
|
|
$cache->set($delivery->shipping_id, $result->showapi_res_body, 7200); //设置缓存2个小时
|
|
return $result->showapi_res_body;
|
|
} else {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Delivery $delivery
|
|
* @return string
|
|
* 查询物流 创建参数(包括签名的处理)
|
|
*/
|
|
private static function createLogisticsParam($delivery)
|
|
{
|
|
$params = [
|
|
'showapi_appid' => Yii::$app->params['logistics_config']['logistics_appid'],
|
|
'com' => $delivery->shipping_name , //物流单位
|
|
'nu' => $delivery->invoice_sn, //运单号
|
|
//添加其他参数
|
|
];
|
|
|
|
$paraStr = "";
|
|
$signStr = "";
|
|
ksort($params);
|
|
foreach ($params as $key => $val) {
|
|
if ($key != '' && $val != '') {
|
|
$signStr .= $key.$val;
|
|
$paraStr .= $key . '=' . urlencode($val) . '&';
|
|
}
|
|
}
|
|
$signStr .= Yii::$app->params['logistics_config']['logistics_secret'];
|
|
|
|
//排好序的参数加上secret,进行md5,将md5后的值作为参数,便于服务器的效验
|
|
$sign = strtolower(md5($signStr));
|
|
$paraStr .= 'showapi_sign=' . $sign;
|
|
return $paraStr;
|
|
}
|
|
|
|
|
|
}
|