Browse Source

feat: 发货功能第一版(部分发货待完善)

wechat_public_accounts
travis 5 years ago
parent
commit
436144dbe8
  1. 34
      backend/modules/shop/controllers/OrderController.php
  2. 242
      backend/modules/shop/logic/delivery/DeliveryManager.php
  3. 37
      backend/modules/shop/migrations/m191206_024047_create_table_delivery_goods.php
  4. 79
      backend/modules/shop/models/ars/DeliveryGoods.php
  5. 2
      backend/modules/shop/models/searchs/DeliverySearch.php
  6. 5
      backend/modules/shop/models/searchs/OrderSearch.php
  7. 56
      backend/modules/shop/views/order/delivery.php
  8. 130
      backend/modules/shop/views/order/delivery_goods.php
  9. 11
      backend/modules/shop/views/order/logistics.php
  10. 5
      backend/modules/shop/views/order/shipping_info.php
  11. 50
      console/controllers/TestController.php

34
backend/modules/shop/controllers/OrderController.php

@ -2,6 +2,8 @@
namespace backend\modules\shop\controllers;
use backend\modules\shop\logic\delivery\DeliveryManager;
use backend\modules\shop\models\ars\Delivery;
use Yii;
use backend\modules\shop\models\ars\Order;
use backend\modules\shop\models\searchs\OrderSearch;
@ -146,4 +148,36 @@ class OrderController extends Controller
'columns' => $searchModel->columns()
]);
}
/**
* @param $id
* @return string|\yii\web\Response
* @throws NotFoundHttpException
* @throws \yii\db\Exception
* 订单发货
*/
public function actionDelivery($id)
{
$order = $this->findModel($id);
$delivery = new Delivery();
if (Yii::$app->request->isPost) {
$res = DeliveryManager::orderDelivery($order, $delivery);
if ($res['status']) {
return $this->redirect(['index']);
} else {
Yii::$app->session->setFlash('error', $res['info']);
}
}
/*获取发货商品信息(包括已发货和未发货)*/
$deliveryGoods = DeliveryManager::deliveryGoodsInfo($id);
return $this->render('delivery', [
'order' => $order,
'delivery' => $delivery,
'deliveryGoods' => json_encode($deliveryGoods)
]);
}
}

242
backend/modules/shop/logic/delivery/DeliveryManager.php

@ -0,0 +1,242 @@
<?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\ExpressTemplate;
use backend\modules\shop\models\ars\Order;
use backend\modules\shop\models\ars\OrderGoods;
use Yii;
use yii\db\Exception;
class DeliveryManager
{
/**
* @param $order
* @param $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('缺少发货商品信息');
}
$deliveryGoods = json_decode($data['deliveryGoods']);
$delivery->load($data);
$delivery->order_id = $order->id;
if (!$delivery->save()) {
throw new Exception('保存物流信息失败');
}
/*发货商品数据*/
self::deliveryGoods($delivery->id, $order, $deliveryGoods);
$transaction->commit();
return ['status' => true];
} catch (Exception $e) {
$transaction->rollBack();
return ['status' => false, 'info' => $e->getMessage()];
}
}
/**
* @param $delivery_id
* @param $order
* @param $deliveryGoods
* @throws Exception
* 发货商品数据
*/
public static function deliveryGoods($delivery_id, $order, $deliveryGoods)
{
foreach ($deliveryGoods as $k => $value) {
$model = new DeliveryGoods();
$model->delivery_id = $delivery_id;
$model->order_goods_id = $value->id;
$model->goods_id = $value->goods_id;
$model->goods_name = $value->goods_name;
$model->goods_number = $value->goods_number;
if ($model->goods_number < $value->lack_number) {
$order->status = Order::STATUS_SHIPMENT_PORTION;
} else {
$order->status = Order::STATUS_SHIPMENT_ALL;
}
if (!$order->save()) {
throw new Exception('order shipping_status update false');
}
if (!$model->save()) {
throw new Exception('delivery_goods save false');
}
}
}
/**
* @param $order
* @param $goodsStatus
* @throws Exception
* @name '修改发货状态'
*/
public function updateShippedStatus($order, $goodsStatus){
}
/**
* @param $order_id
* @return array
* @throws Exception
* 获取发货全部商品信息
*/
public static function deliveryGoodsInfo($order_id)
{
$delivery = Delivery::find()->select('id')->where(['order_id' => $order_id])->all();
/*如果该订单是首次发货*/
if (!$delivery) {
$unShippend = self::firstDelivery($order_id);
return ['unShipped' => $unShippend];
}
$deliveryIds = [];
foreach ($delivery as $value) {
$deliveryIds[] = $value->id;
}
$filter = [];
$deliveryGoods = DeliveryGoods::find()->where(['delivery_id' => $deliveryIds])->all();
for ($i = 0; $i < count($deliveryGoods); $i++) {
$orderGoodsId = $deliveryGoods[$i]['order_goods_id'];
//以orderGoods的id为键名,以orderGoods的数量为键值,先保存到filter数组中
$filter[$orderGoodsId] = $deliveryGoods[$i]['goods_number'];
for ($j = 0; $j < count($deliveryGoods); $j++) {
//如果发货商品中有其他相同orderGoods的商品
if ($orderGoodsId == $deliveryGoods[$j]['order_goods_id'] && $i !== $j) {
//商品数量叠加起来并保存
$filter[$orderGoodsId] += $deliveryGoods[$j]['goods_number'];
}
}
}
/*获取订单已发的商品和未发的商品*/
return self::getDeliveryGoodsInfo($filter, $order_id);
}
/**
* @param $order_id
* @return array
* 首次发货直接获取orderGoods的内容
*/
public static function firstDelivery($order_id)
{
$unShippedGoods = [];
$orderGoods = OrderGoods::find()->where(['order_id' => $order_id])->all();
foreach ($orderGoods as $k => $v) {
$unShippedGoods[] = [
'id' => $v->id,
'goods_id' => $v->goods_id,
'goods_img' => $v->goods_img,
'goods_name' => $v->goods_name,
'price' => $v->price,
'market_price' => $v->market_price,
'goods_number' => $v->goods_count,
'lack_number' => $v->goods_count,
'sku_value' => $v->sku_value,
];
}
return $unShippedGoods;
}
/**
* @param $filter
* @param $order_id
* @return array
* @throws Exception
* 获取订单已发的商品和未发的商品
*/
public static function getDeliveryGoodsInfo($filter,$order_id)
{
$unShipped = []; //未发货商品
foreach ($filter as $k => $value) { //键名为ordergoods_id,键值为对应的已发货数量
$goodsData = self::getOrderGoodsInfo($k);
if ($value < $goodsData['goods_number']) { //如果已发货数量未达到order_goods里的数量
$lack_number = $goodsData['goods_number'] - $value;
$goodsData['lack_number'] = $lack_number;
$goodsData['goods_number'] = $lack_number;
$unShipped[] = $goodsData;
}
}
$shipped = self::getDeliveryInfo($order_id); //已发货商品信息
return ['shipped' => $shipped, 'unShipped' => $unShipped];
}
/**
* @param $order_id
* @return array
* @throws Exception
* 通过订单号获取发货信息
*/
public static function getDeliveryInfo($order_id)
{
$deliveryInfo = [];
$delivery = Delivery::findAll(['order_id' => $order_id]);
foreach ($delivery as $k => $value) {
$expressTemplate = ExpressTemplate::find()->select('name')->where(['id' => $value->shipping_id])->one();
$deliveryInfo[$k]['logisticInfo'] = [
'exp_name'=> $expressTemplate ? $expressTemplate->name : '',
'invoice_no'=> $value->invoice_no
]; //物流公司和运单号
$deliveryInfo[$k]['goodsInfo'] = self::getDeliverGoodsInfo($value->id); //获取商品信息
}
return $deliveryInfo;
}
/**
* @param $delivery_id
* @return array
* @throws Exception
* 通过获取订单已发货的商品信息
*/
public static function getDeliverGoodsInfo($delivery_id)
{
$goodsInfo = [];
$deliveryGoods = DeliveryGoods::find()->where(['delivery_id'=>$delivery_id])->andWhere(['>','goods_number',0])->all();
foreach ($deliveryGoods as $value) {
$goodsData = self::getOrderGoodsInfo($value->order_goods_id);
$goodsData['delivery_number'] = $value->goods_number;
$goodsInfo[] = $goodsData;
}
return $goodsInfo;
}
/**
* @param $orderGoodsId
* @return array
* @throws Exception
* 获取订单商品信息
*/
private static function getOrderGoodsInfo($orderGoodsId)
{
$orderGoods = OrderGoods::findOne($orderGoodsId); //通过orderGoods_id找到订单商品
if ($orderGoods) {
$goodsData = [
'id' => $orderGoods->id,
'goods_id' => $orderGoods->goods_id,
'goods_name' => $orderGoods->goods_name,
'shop_price' => $orderGoods->shop_price,
'goods_number' => $orderGoods->goods_number,
'goods_img' => $orderGoods->goods_img,
'sku_type' => $orderGoods->sku_type,
];
return $goodsData;
} else {
throw new Exception('order_goods not found');
}
}
}

37
backend/modules/shop/migrations/m191206_024047_create_table_delivery_goods.php

@ -0,0 +1,37 @@
<?php
use yii\db\Migration;
/**
* Class m191206_024047_create_table_delivery_goods
*/
class m191206_024047_create_table_delivery_goods extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB COMMENT="物流商品表"';
$this->createTable('ats_delivery_goods', [
'id' => $this->primaryKey(),
'delivery_id' => $this->integer()->notNull()->defaultValue(0)->comment('物流id'),
'order_goods_id' => $this->integer()->notNull()->defaultValue(0)->comment('订单商品id'),
'goods_id' => $this->integer()->notNull()->defaultValue(0)->comment('商品id'),
'goods_name' => $this->string()->notNull()->defaultValue('')->comment('商品名称'),
'goods_number' => $this->integer()->notNull()->defaultValue(0)->comment('商品数量'),
'created_at' => $this->integer()->notNull()->defaultValue(0)->comment('创建时间'),
'updated_at' => $this->integer()->notNull()->defaultValue(0)->comment('更新时间'),
], $tableOptions);
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropTable('ats_delivery_goods');
return true;
}
}

79
backend/modules/shop/models/ars/DeliveryGoods.php

@ -0,0 +1,79 @@
<?php
namespace backend\modules\shop\models\ars;
use Yii;
use yii\behaviors\TimestampBehavior;
/**
* This is the model class for table "ats_delivery_goods".
*
* @property int $id
* @property int $delivery_id 物流id
* @property int $order_goods_id 订单商品id
* @property int $goods_id 商品id
* @property int $goods_name 商品名称
* @property int $goods_number 商品数量
* @property int $created_at 创建时间
* @property int $updated_at 更新时间
*/
class DeliveryGoods extends \yii\db\ActiveRecord
{
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'ats_delivery_goods';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['delivery_id', 'order_goods_id', 'goods_id', 'goods_number'], 'integer'],
[['goods_name'], 'string'],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'id',
'delivery_id' => '物流id',
'order_goods_id' => '订单商品id',
'goods_id' => '商品id',
'goods_name' => '商品名称',
'goods_number' => '商品数量',
'created_at' => '创建时间',
'updated_at' => '更新时间',
];
}
/**
* @author linyao
* @email 602604991@qq.com
* @created Nov 8, 2019
*
* 行为存储创建时间和更新时间
*/
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => function() {
return time();
},
],
];
}
}

2
backend/modules/shop/models/searchs/DeliverySearch.php

@ -57,7 +57,7 @@ class DeliverySearch extends Delivery
'shipping_name',
'shipping_id',
'type',
'goods',
// 'goods',
'status',
'decription',
//'updated_at',

5
backend/modules/shop/models/searchs/OrderSearch.php

@ -127,6 +127,11 @@ class OrderSearch extends Order
'icon' => 'list',
'title' => '详情',
],
[
'name' => 'delivery',
'icon' => 'box',
'title' => '发货',
],
[
'name' => 'update',
'icon' => 'pencil',

56
backend/modules/shop/views/order/delivery.php

@ -0,0 +1,56 @@
<?php
use yii\helpers\Html;
use yii\bootstrap4\ActiveForm;
use kartik\tabs\TabsX;
/* @var $this yii\web\View */
/* @var $order backend\modules\shop\models\ars\Order */
/* @var $delivery backend\modules\shop\models\ars\Delivery */
/* @var $form yii\widgets\ActiveForm */
/* @var $deliveryGoods */
$this->title = '订单发货:'. $order->order_sn;
$this->params['breadcrumbs'][] = ['label' => '订单列表', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
Yii::$app->params['bsVersion'] = '4.x';
?>
<div class="delivery-form">
<?php
$form = ActiveForm::begin(['options' => ['class' => 'container-fluid']]);
echo TabsX::widget([
'bordered' => true,
'items' => [
[
'label' => '<i class="fas fa-user"></i> 物流信息',
'content' => $this->render('logistics', [
'order' => $order,
'delivery' => $delivery,
'form' => $form,
]),
],
[
'label' => '<i class="fas fa-ad"></i> 订单商品信息',
'content' => $this->render('delivery_goods', [
'form' => $form,
'deliveryGoods' => $deliveryGoods,
]),
],
],
'position' => TabsX::POS_ABOVE,
'encodeLabels' => false
]);
?>
<div class="form-group">
<?= Html::submitButton('保存', ['class' => 'btn btn-success']) ?>
<?= Html::a('返回', ['index'], ['class' => 'btn btn-info']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>

130
backend/modules/shop/views/order/delivery_goods.php

@ -0,0 +1,130 @@
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/9/4
* Time: 19:59
*/
?>
<style>
.box {
margin-top: 20px;
}
.unShipped-table,.shipped-table {
margin:15px;
width:90%;
padding:5px;
border-radius: 10px;
box-shadow:0 4px 30px 2px rgba(223, 225, 230, 0.5) !important;
}
</style>
<div>
<div class="box unShipped-box">
<h5>未发货商品</h5>
<table class="table unShipped-table">
<tr>
<th>商品名称</th>
<th>商品sku</th>
<th>还需发货数量</th>
<th>发货数量</th>
</tr>
</table>
</div>
<div class="box shipped-box">
<h5>已发货商品</h5>
</div>
<input type="hidden" id="deliveryGoods" name="deliveryGoods"><!-- 用于保存商品json -->
</div>
<script src="/js/jquery.js"></script>
<script>
//初始化订单商品数据
var data = <?= $deliveryGoods ?>;
console.log(data);
function init() {
var unShipped = data.unShipped;
showUnShipped(unShipped);
if(data.shipped){
var shipped = data.shipped;
showShipped(shipped)
}
unShipped = JSON.stringify(unShipped);
$('#deliveryGoods').val(unShipped)
}
init();
//显示未发货商品
function showUnShipped(unShipped) {
unShipped.forEach(function (item,index) {
var tr = "<tr data-index='" + index +"'>" +
"<td class='goods_name'>" + item.goods_name + "</td>" +
"<td class='goods_sku'>" + item.sku_value + "</td>" +
"<td class='lack_number'>" + item.lack_number + "</td>" +
"<td><input type='text' class='goods_number' value='"+item.lack_number+"' disabled/></td>" +
"<td>" +
"<input type='button' class='btn btn-primary' value='编辑' onclick='updateGoods(this)'/>" +
"<input type='button' class='btn btn-primary' value='保存' onclick='saveGoods(this)' style='display: none' />" +
"</td>" +
"</tr>";
$('.unShipped-table').append(tr)
});
}
//显示已发货商品
function showShipped(shipped) {
shipped.forEach(function(item,index){
var table = ' <table class="table shipped-table">' +
'<tr>' +
'<th>商品名称</th>' +
'<th>商品sku</th>' +
'<th>发货数量</th>' +
'</tr>\n' +
'</table>';
var div = document.createElement('div');
div.innerText = '运单号:' + item.logisticInfo.invoice_no + '快递公司:'+ item.logisticInfo.exp_name;
$('.shipped-box').append(div);
$('.shipped-box').append(table);
table = $('.shipped-table').eq(index);
item.goodsInfo.forEach(function (item,index) {
var tr = "<tr data-index='" + index +"'>" +
"<td class='goods_name'>" + item.goods_name + "</td>" +
"<td class='goods_sku'>" + item.sku_type + "</td>" +
"<td class='goods_number'>" + item.delivery_number + "</td>" +
"</tr>";
$(table).append(tr);
});
})
}
//编辑发货数量
function updateGoods(ref){
$(ref).hide();
$(ref).next().show();
$(ref).parent().parent().find('.goods_number').removeAttr('disabled')
}
//保存编辑
function saveGoods(ref) {
if(typeof unShipped =='string'){
unShipped = JSON.parse(unShipped)
}
var tr = $(ref).parent().parent();
tr.find('.goods_number').attr('disabled','disabled');
var index = tr.attr('data-index');
var number = tr.find('.goods_number').val();
if (number < 0) {
alert('发货数量不能低于0');
tr.find('.goods_number').val(0);
return false;
}
unShipped[index].goods_number = number;
unShipped = JSON.stringify(unShipped);
$('#deliveryGoods').val(unShipped);
$(ref).hide();
$(ref).prev().show();
}
</script>

11
backend/modules/shop/views/order/logistics.php

@ -0,0 +1,11 @@
<div class="logistics">
<?= $form->field($delivery, 'shipping_name')->textInput(['maxlength' => true]) ?>
<?= $form->field($delivery, 'shipping_id')->textInput(['maxlength' => true]) ?>
<?= $form->field($delivery, 'type')->textInput() ?>
<?= $form->field($delivery, 'status')->textInput() ?>
<?= $form->field($delivery, 'decription')->textarea(['rows' => 6]) ?>
</div>

5
backend/modules/shop/views/order/shipping_info.php

@ -1,3 +1,6 @@
<?php
use backend\modules\shop\models\ars\Order;
?>
<style>
.info td:nth-child(1) {
white-space: nowrap;
@ -10,7 +13,7 @@
<table class="info">
<tr>
<td>物流类型:</td>
<td><?= \backend\modules\shop\models\ars\Order::dropDown('shipping_type', $model->shipping_type) ?></td>
<td><?= $model->shipping_type ? Order::dropDown('shipping_type', $model->shipping_type) : '无' ?></td>
</tr>
<tr>
<td>商品金额:</td>

50
console/controllers/TestController.php

@ -2,8 +2,11 @@
namespace console\controllers;
use backend\modules\shop\models\ars\Order;
use backend\modules\shop\models\ars\OrderGoods;
use Yii;
use yii\console\Controller;
use yii\db\Exception;
use yii\helpers\Console;
/**
@ -32,4 +35,51 @@ class TestController extends Controller {
}
}
}
public function actionOrderGoods()
{
$transaction = Yii::$app->db->beginTransaction();
try {
$order = new Order();
$order->user_id = 1;
$order->type = Order::TYPE_SHOPPING;
$order->order_sn = date('Ymd', time()) . rand(0, 100);
$order->invoice_id = date('Ymd', time()) . rand(0, 100);
$order->consignee = '温xx';
$order->phone = '17727716697';
$order->goods_count = rand(10, 33);
$order->goods_amount = rand(10, 100);
$order->shipping_type = 0;
$order->shipping_amount = rand(10, 100);
$order->address = '地址地址测试地址';
if (!$order->save()) {
throw new Exception('save order false');
}
for ($i = 1; $i <= 3; $i++) {
$orderGoods = new OrderGoods();
$orderGoods->order_id = $order->id;
$orderGoods->goods_id = $i;
$orderGoods->goods_name = '测试商品' . $i;
$orderGoods->goods_count = rand(1, 10);
$orderGoods->sku_value = 'sku值1';
$orderGoods->price = rand(100, 999);
$orderGoods->market_price = $orderGoods->price + 166;
$orderGoods->weight = rand(1, 10);
$orderGoods->sku_id = 0;
if (!$orderGoods->save()) {
throw new Exception('orderGoods save false');
}
}
$transaction->commit();
echo "ok\n";
} catch (Exception $e) {
$transaction->rollBack();
print_r($e->getMessage());
}
}
}
Loading…
Cancel
Save