diff --git a/MySQL_change.sql b/MySQL_change.sql
index 5a3a75e..5b00304 100644
--- a/MySQL_change.sql
+++ b/MySQL_change.sql
@@ -241,3 +241,11 @@ ENGINE=InnoDB;
ALTER TABLE `order_product_items`
ADD COLUMN `num` INT(10) NOT NULL COMMENT '购买数量' AFTER `product_id`,
ADD COLUMN `price` DECIMAL(20,2) NOT NULL COMMENT '销售价格' AFTER `num`;
+
+# 16:42 2021/9/2
+ALTER TABLE `agent_products`
+ CHANGE COLUMN `type` `type` TINYINT(3) NOT NULL DEFAULT '0' COMMENT '0:单品销售;1:组合销售;2:组团旅行社的云产品;' AFTER `is_rec`,
+ ADD COLUMN `is_cloud` TINYINT NOT NULL DEFAULT 0 COMMENT '是否是(组团旅行社特有)云产品,。0:否;1:是;' AFTER `earnest_timeout`,
+ ADD COLUMN `agent_cloud_pid` INT(10) NOT NULL DEFAULT '0' COMMENT '组团版旅行社的云产品ID' AFTER `is_cloud`,
+ ADD INDEX `agent_cloud_pid` (`agent_cloud_pid`);
+UPDATE `agent_products` ap SET `is_cloud`=1 WHERE EXISTS(SELECT 1 FROM `agents` WHERE `id`=ap.`agent_id` AND `type`=3);
diff --git a/app/AdminAgent/Controllers/AgentProductController.php b/app/AdminAgent/Controllers/AgentProductController.php
index f7d1529..067d52d 100644
--- a/app/AdminAgent/Controllers/AgentProductController.php
+++ b/app/AdminAgent/Controllers/AgentProductController.php
@@ -2,6 +2,7 @@
namespace App\AdminAgent\Controllers;
+use App\AdminAgent\Renderable\SelectAgentCloudProduct;
use App\AdminAgent\Renderable\SelectGuide;
use App\AdminAgent\Renderable\SelectProduct;
use App\AdminAgent\Repositories\AgentProduct;
@@ -163,13 +164,19 @@ class AgentProductController extends AdminController
}
$form->display('id');
+
+ //组团版旅行社不允许选择组团云产品
+ $options = Admin::user()->type == AgentType::CLUSTER ? [1 => '组合销售'] : ['单品销售', '组合销售', '组团云产品'];
$form->radio('type')
- ->options(['单品销售', '组合销售'])
- ->default(0)->required()
+ ->options($options)
+ ->default(Admin::user()->type == AgentType::CLUSTER ? 1 : 0)->required()
->help('单品销售无需审核,组合销售需要审核才能上架')
->when(0, function (Form $form) {
+ //组团版没有单品选择功能
+ if (Admin::user()->type == AgentType::CLUSTER) return;
+
/** 单品销售 **/
- $form->selectTable('product_id', '选择产品')
+ $form->selectTable('product_id', '供应商产品')
->help('产品列表显示的是该产品的标题和图片')
->title('选择产品')
->dialogWidth('80%;min-width:825px;')
@@ -177,7 +184,7 @@ class AgentProductController extends AdminController
->model(Product::class);
})->when(1, function (Form $form) {
/** 组合销售 **/
- $form->multipleSelectTable('product_ids', '选择产品')
+ $form->multipleSelectTable('product_ids', '供应商产品')
->help('可单选或多选组合销售')
->title('选择产品')
->dialogWidth('80%;min-width:825px;')
@@ -189,6 +196,17 @@ class AgentProductController extends AdminController
$form->multipleImage('pictures')->removable(false)->uniqueName();
$form->editor('know');
$form->editor('content');
+ })->when(2, function (Form $form) {
+ //组团版旅行社不允许选择组团云产品
+ if (Admin::user()->type == AgentType::CLUSTER) return;
+
+ /** 组团云产品 **/
+ $form->selectTable('agent_cloud_pid', '组团云产品')
+ ->help('产品列表显示的是该产品的标题和图片')
+ ->title('选择产品')
+ ->dialogWidth('80%;min-width:825px;')
+ ->from(SelectAgentCloudProduct::make())
+ ->model(Product::class);
});
$form->text('price')->required();
$form->text('original_price')->required();
@@ -214,7 +232,7 @@ class AgentProductController extends AdminController
])
->required();
}
- $form->switch('is_rec')->help('推荐后将在“我的”页面下方显示');
+ $form->switch('is_rec')->help('推荐后将在小程序“我的”页面下方显示');
//$form->selectTable('verifier')
// ->title('选择核销人员')
// ->dialogWidth('50%;min-width:600px;') //不起作用
@@ -232,10 +250,14 @@ class AgentProductController extends AdminController
->model(Guide::class, 'id', 'name');
}
- $form->number('earnest')->width(2)->default(0)->help('单位:元。不输入或输入 0 则不支持定金支付,必须和定金超时时间同时设置才会生效');
- $form->number('earnest_timeout')->width(2)->default(0)->help('单位:分钟。超过这个时间未支付,订单将自动关闭');
- $form->number('deposit')->default(0)->help('单位:元。不输入或输入 0 则不支持订金支付,必须和订金超时时间同时设置才会生效');
- $form->number('deposit_timeout')->default(0)->help('单位:分钟。超过这个时间未支付,订单将自动关闭');
+ $form->number('earnest')->min(0)
+ ->default(0)->help('单位:元。不输入或输入 0 则不支持定金支付,必须和定金超时时间同时设置才会生效');
+ $form->number('earnest_timeout')->min(0)
+ ->default(0)->help('单位:分钟。超过这个时间未支付,订单将自动关闭');
+ $form->number('deposit')->min(0)
+ ->default(0)->help('单位:元。不输入或输入 0 则不支持订金支付,必须和订金超时时间同时设置才会生效');
+ $form->number('deposit_timeout')->min(0)
+ ->default(0)->help('单位:分钟。超过这个时间未支付,订单将自动关闭');
})->saving(function (Form $form) {
//不允许修改非自己的数据
if ($form->isEditing() && $form->model()->agent_id != Admin::user()->id) {
@@ -331,6 +353,43 @@ class AgentProductController extends AdminController
if ($not_in_id) {
return $form->response()->error('产品ID ' . join(',', $not_in_id) . ' 库存小于你设置的库存' . $form->stock . ',或不存在、已下架等');
}
+
+ //如果是组团版旅行社,标记为是云产品
+ if (Admin::user()->type == AgentType::CLUSTER) {
+ $form->hidden('is_cloud');
+ $form->is_cloud = 1;
+ }
+ }
+ //组团云产品
+ else if ($form->type == 2) {
+ $form->agent_cloud_pid = (int)$form->agent_cloud_pid;
+ if (!$form->agent_cloud_pid) {
+ return $form->response()->error('请选择产品');
+ }
+
+ //产品信息预判断
+ $cloud_product = \App\Models\AgentProduct::where([
+ ['stock', '>', 0],
+ ['status', '=', ProductStatus::ON_SALE],
+ ['is_cloud', '=', 1],
+ ['type', '=', 1],
+ ['agent_id', '<>', Admin::user()->id],
+ ])->find($form->agent_cloud_pid);
+
+ if (!$cloud_product) {
+ return $form->response()->error('你选择的组团云产品库存不足或已下架,请重新选择');
+ } else if ($cloud_product->stock < $form->stock) {
+ return $form->response()->error("组团云产品当前库存为{$cloud_product->stock},你设置的库存不能超过该数值");
+ }
+
+ //同步关键字段信息
+ $form->product_id = $cloud_product->product_id;
+ $form->product_ids = $cloud_product->product_ids;
+ $form->guide_id = $cloud_product->guide_id;
+ $form->title = $cloud_product->title;
+ $form->pictures = $cloud_product->pictures;
+ $form->know = $cloud_product->know;
+ $form->content = $cloud_product->content;
} else {
return $form->response()->error('不存在此销售方式');
}
@@ -339,6 +398,7 @@ class AgentProductController extends AdminController
//处理特殊字段
$form->hidden(['agent_id', 'status']); //表单没有的字段,必须加这句才能够重写
$form->agent_id = $agent_id;
+ $form->agent_cloud_pid = $form->type ==2 ? ($form->agent_cloud_pid ?? 0) : 0;
if (array_key_exists('guide_id', $form->input())) {
$form->guide_id = $form->guide_id ?? 0;
}
@@ -381,8 +441,8 @@ class AgentProductController extends AdminController
if ($form->isEditing()) {
$where[] = ['id', '<>', $form->getKey()];
}
- if ($form->repository()->model()->where($where)->exists()) {
- return $form->response()->error('该产品已经存在,请勿重复发布');
+ if ($id = $form->repository()->model()->where($where)->value('id')) {
+ return $form->response()->error("你发布的产品ID {$id} 与本产品重复,请检查");
}
})->saved(function (Form $form) {
/** 保存到组合产品明细,先查询出之前明细,再跟新的比较,若没有则删除,新的产品原来明细表没有的,则插入 **/
@@ -419,6 +479,21 @@ class AgentProductController extends AdminController
);
}
}
+
+ //如果是组团云产品,同步信息到其它产品
+ if ($form->is_cloud) {
+ \App\Models\AgentProduct::query()
+ ->where(['agent_cloud_pid' => $form->getKey(), 'type' => 2])
+ ->update([
+ 'product_id' => $form->product_id,
+ 'product_ids' => $form->product_ids,
+ 'guide_id' => $form->guide_id,
+ 'title' => $form->title,
+ 'pictures' => explode(',', $form->pictures),
+ 'know' => $form->know,
+ 'content' => $form->content,
+ ]);
+ }
})->deleting(function (Form $form) {
//不允许删除非自己的数据
if (array_filter($form->model()->toArray(), fn($v) => $v['agent_id'] != Admin::user()->id)) {
diff --git a/app/AdminAgent/Controllers/OrderController.php b/app/AdminAgent/Controllers/OrderController.php
index 37e452f..12771c5 100644
--- a/app/AdminAgent/Controllers/OrderController.php
+++ b/app/AdminAgent/Controllers/OrderController.php
@@ -7,6 +7,8 @@ use App\AdminAgent\Extensions\Grid\ChangeOrderStatus;
use App\AdminAgent\Repositories\Order;
use App\Common\OrderStatus;
use App\Common\PayType;
+use App\Models\OrderProductItem;
+use App\Models\Product;
use App\Models\Supplier;
use Dcat\Admin\Admin;
use Dcat\Admin\Form;
@@ -14,6 +16,7 @@ use Dcat\Admin\Grid;
use Dcat\Admin\Show;
use Dcat\Admin\Http\Controllers\AdminController;
use Dcat\Admin\Widgets\Table;
+use Illuminate\Support\Facades\Storage;
class OrderController extends AdminController
{
@@ -29,6 +32,8 @@ class OrderController extends AdminController
$grid->disableBatchDelete();
$grid->disableCreateButton();
$grid->disableRowSelector();
+ $grid->disableEditButton();
+ $grid->disableQuickEditButton(false);
$grid->model()->where('agent_id', Admin::user()->id);
@@ -39,13 +44,21 @@ class OrderController extends AdminController
$grid->column('product', '产品信息')
->display('查看')
->modal('购买产品信息', function ($modal) {
- return Table::make(['产品名称', '产品图片', '购买数量', '所属供应商'],
- [[
- $this->title,
- '
',
- $this->num,
- $this->product->supplier->name,
- ]]);
+ $item = OrderProductItem::with(['supplier:id,name', 'product:id,title,pictures'])
+ ->where('order_id', $this->id)
+ ->get(['num', 'supplier_id', 'product_id']);
+
+ $row = [];
+ foreach($item as $v) {
+ $picture = $v->product->picture ? Storage::disk('public')->url($v->product->picture) : '';
+ $row[] = [
+ $v->product->title ?? '',
+ '
',
+ $v->num ?? '',
+ $v->supplier->name ?? '',
+ ];
+ }
+ return Table::make(['产品名称', '产品图片', '购买数量', '所属供应商'], $row);
})->xl();
//状态及退款处理
@@ -125,6 +138,7 @@ class OrderController extends AdminController
{
return Show::make($id, new Order(['product.supplier:id,name']), function (Show $show) {
$show->disableDeleteButton();
+ $show->disableEditButton();
//不允许查看非自己的数据
if ($show->model()->agent_id != Admin::user()->id) {
@@ -178,15 +192,18 @@ class OrderController extends AdminController
return $form->response()->error('数据不存在');
}
- //不允许编辑的字段
- $form->ignore(['id', 'user_id', 'agent_id', 'agent_product_id', 'product_id', 'product_ids', 'order_no',
- 'pay_type', 'paid_money', 'created_at', 'updated_at', 'deleted_at']);
+ //仅允许编辑name,mobile字段
+ $forbid_field = array_diff(array_keys($form->input()), ['name', 'mobile']);
+ $form->ignore($forbid_field);
+ $form->deleteInput($forbid_field);
//退款不能直接编辑
- if (in_array($form->status, [OrderStatus::REFUNDED, OrderStatus::REFUSED_REFUND])) {
- return $form->response()->error('请通过订单列表的”通过“和”拒绝“按钮来审核退款');
- } else if ($form->status != OrderStatus::OFFLINE_PAID) {
- return $form->response()->error('操作禁止');
+ if ($form->status !== null) {
+ if (in_array($form->status, [OrderStatus::REFUNDED, OrderStatus::REFUSED_REFUND])) {
+ return $form->response()->error('请通过订单列表的”通过“和”拒绝“按钮来审核退款');
+ } else if ($form->status != OrderStatus::OFFLINE_PAID) {
+ return $form->response()->error('操作禁止');
+ }
}
})->saved(function (Form $form) {
return $form->response()->success('更新成功')->refresh();
diff --git a/app/AdminAgent/Renderable/SelectAgentCloudProduct.php b/app/AdminAgent/Renderable/SelectAgentCloudProduct.php
new file mode 100644
index 0000000..28a9779
--- /dev/null
+++ b/app/AdminAgent/Renderable/SelectAgentCloudProduct.php
@@ -0,0 +1,53 @@
+id;
+ Admin::translation('agent-product');
+ return Grid::make(new AgentProduct(), function (Grid $grid) {
+ $grid->disableActions();
+ $grid->disableBatchDelete();
+ $grid->disableBatchActions();
+
+ $grid->model()->where([
+ ['stock', '>', 0],
+ ['status', '=', ProductStatus::ON_SALE],
+ ['is_cloud', '=', 1],
+ ['type', '=', 1],
+ ['agent_id', '<>', Admin::user()->id],
+ ]);
+
+ $grid->quickSearch(['title'])->placeholder('搜索产品名称');
+
+ $grid->column('id');
+ $grid->column('title');
+ $grid->column('picture')->image('', 60, 60);
+ $grid->column('sale');
+ $grid->column('stock');
+ $grid->column('updated_at');
+
+ $grid->paginate(15);
+
+ $grid->filter(function (Grid\Filter $filter) {
+ $filter->panel();
+
+ $filter->like('title')->width(4);
+ });
+ });
+ }
+}
diff --git a/app/Common/OrderStatus.php b/app/Common/OrderStatus.php
index 2efde99..7e170f5 100644
--- a/app/Common/OrderStatus.php
+++ b/app/Common/OrderStatus.php
@@ -16,7 +16,7 @@ class OrderStatus
/** @var int 待付款 */
const UNPAID = 0;
- /** @var int 已付定金 */
+ /** @var int 已付(订)定金 */
const PAY_EARNEST = 1;
/** @var int 已付全款 */
@@ -48,7 +48,7 @@ class OrderStatus
return [
self::CANCEL => '已取消',
self::UNPAID => '待付款',
- self::PAY_EARNEST => '已付定金',
+ self::PAY_EARNEST => '已付定(订)金',
self::PAID => '已付款',
self::PAID_RETAINAGE => '已付尾款',
self::OFFLINE_UNPAID => '[线下]未付款',
diff --git a/app/Http/Controllers/Api/OrderController.php b/app/Http/Controllers/Api/OrderController.php
index 18be8cc..0f9bb70 100644
--- a/app/Http/Controllers/Api/OrderController.php
+++ b/app/Http/Controllers/Api/OrderController.php
@@ -58,7 +58,7 @@ class OrderController extends Controller
->toArray();
$time = time();
- $timeout_ids = [];
+
$prefix = Storage::disk('public')->url('');
foreach ($order_list['data'] as &$v) {
//图片加上域名
@@ -77,26 +77,23 @@ class OrderController extends Controller
}
//未付款订单提示剩余付款时间
- if ($v['timeout'] !== null && $v['status'] == Status::UNPAID) {
+ if ($v['timeout'] !== null) {
$second = strtotime($v['timeout']) - $time;
- if ($second > 0) {
+ if ($second > 0 && $v['status'] == Status::UNPAID) {
$v['status_text'] = '请在' . ceil($second / 60) . '分钟内付款';
- } /*else { //TODO 此部分由定时
+ } else if ($second < 0 && $v['status'] == Status::PAY_EARNEST) {
+ $v['status_text'] = '尾款支付已超时';
+ } /*else { //此部分由定时处理
$timeout_ids[] = $v['id'];
$v['status'] = Status::CANCEL;
$v['status_text'] = '已取消';
- //TODO 加回库存,未考虑到几天/几个月后再打开订单列表页的情况,需要定时任务处理
+ //此部分已由定时任务处理
Product::query()->find($v['product_id'])->increment('stock', $v['num']);
}*/
}
}
- //超时订单设置为已取消 TODO 测试阶段暂时注释
- if ($timeout_ids) {
- Order::query()->whereIn('id', $timeout_ids)->update(['status' => Status::CANCEL]);
- }
-
return $this->success($order_list);
}
@@ -325,10 +322,11 @@ class OrderController extends Controller
$order = Order::query()
->with('agentProduct')
->where(['user_id' => $this->user_id, 'agent_id' => $this->agent_id])
+ ->whereRaw('`timeout` >= NOW()')
->whereIn('status', [Status::UNPAID, Status::PAY_EARNEST])
->find($id);
if (!$order) {
- return $this->error('订单不存在或已支付');
+ return $this->error('订单已支付或已超时');
}
$ap = AgentProduct::with('coupon')->find($order->agent_product_id);
diff --git a/app/Models/OrderProductItem.php b/app/Models/OrderProductItem.php
index 799ef5d..67d9e3c 100644
--- a/app/Models/OrderProductItem.php
+++ b/app/Models/OrderProductItem.php
@@ -16,13 +16,23 @@ class OrderProductItem extends BaseModel
//$this->timestamps = false;
}
- function order()
+ public function order()
{
return $this->belongsTo(Order::class,'order_id','id');
}
- function product()
+ public function product()
{
return $this->belongsTo(Product::class,'product_id','id');
}
+
+ public function supplier()
+ {
+ return $this->belongsTo(Supplier::class);
+ }
+
+ public function agent()
+ {
+ return $this->belongsTo(Agent::class);
+ }
}