Browse Source

Merge remote-tracking branch 'origin/master'

master
李可松 4 years ago
parent
commit
b8c997c1e4
  1. 2
      app/Admin/Controllers/DemandProductController.php
  2. 3
      app/AdminSupplier/Controllers/DemandBiddingController.php
  3. 125
      app/AdminSupplier/Controllers/DemandProductController.php
  4. 5
      app/AdminSupplier/Controllers/FinanceStatisticsController.php
  5. 3
      app/Console/Commands/BalanceDue.php
  6. 38
      app/Events/OrderUpdated.php
  7. 10
      app/Http/Controllers/Api/VerificationController.php
  8. 77
      app/Listeners/OrderEventSubscriber.php
  9. 5
      app/Models/Order.php
  10. 2
      app/Providers/EventServiceProvider.php
  11. 4
      config/sms.php
  12. 32
      database/migrations/2021_09_17_182618_update_demand_product_table.php

2
app/Admin/Controllers/DemandProductController.php

@ -34,7 +34,7 @@ class DemandProductController extends AdminController
$grid->column('category.name', '分类'); $grid->column('category.name', '分类');
$grid->column('picture')->image('', 60, 60); $grid->column('picture')->image('', 60, 60);
$grid->column('title'); $grid->column('title');
$grid->column('sale');
//$grid->column('sale');
$grid->column('supplier.name', '供应商'); $grid->column('supplier.name', '供应商');
$grid->column('status') $grid->column('status')
->if(fn() => $this->status == ProductStatus::UNAUDITED) ->if(fn() => $this->status == ProductStatus::UNAUDITED)

3
app/AdminSupplier/Controllers/DemandBiddingController.php

@ -178,6 +178,9 @@ class DemandBiddingController extends AdminController
$product->know = $demandProduct->know; $product->know = $demandProduct->know;
$product->content = $demandProduct->content; $product->content = $demandProduct->content;
$product->agent_id = $form->model()->bidding_user_id; $product->agent_id = $form->model()->bidding_user_id;
$product->type = $demandProduct->type;
$product->extends = $demandProduct->extends;
$product->service_persons = $demandProduct->service_persons;
$product->save(); $product->save();
//处理需求 //处理需求
$demand = Demand::find($form->model()->demand_id); $demand = Demand::find($form->model()->demand_id);

125
app/AdminSupplier/Controllers/DemandProductController.php

@ -3,11 +3,14 @@
namespace App\AdminSupplier\Controllers; namespace App\AdminSupplier\Controllers;
use App\AdminSupplier\Repositories\DemandProduct; use App\AdminSupplier\Repositories\DemandProduct;
use App\AdminSupplier\Repositories\Product;
use App\Common\ProductStatus; use App\Common\ProductStatus;
use App\Models\AgentProduct; use App\Models\AgentProduct;
use App\Models\AgentProductItem;
use App\Models\Category; use App\Models\Category;
use Dcat\Admin\Admin; use Dcat\Admin\Admin;
use Dcat\Admin\Form; use Dcat\Admin\Form;
use Dcat\Admin\Form\NestedForm;
use Dcat\Admin\Grid; use Dcat\Admin\Grid;
use Dcat\Admin\Repositories\EloquentRepository; use Dcat\Admin\Repositories\EloquentRepository;
use Dcat\Admin\Show; use Dcat\Admin\Show;
@ -28,20 +31,20 @@ class DemandProductController extends AdminController
$grid->model()->where('supplier_id', Admin::user()->id); $grid->model()->where('supplier_id', Admin::user()->id);
$grid->column('id')->sortable(); $grid->column('id')->sortable();
$grid->column('type')->using(admin_trans('product.options.publish_type'));
$grid->column('category.name', '产品分类'); $grid->column('category.name', '产品分类');
$grid->column('title');
$grid->column('title')->limit(15);
$grid->column('picture')->image('', 60, 60); $grid->column('picture')->image('', 60, 60);
//$grid->column('price');
//$grid->column('original_price');
//$grid->column('stock');
$grid->column('sale');
//$grid->column('sale');
$grid->column('status')->using(ProductStatus::array()); $grid->column('status')->using(ProductStatus::array());
$grid->column('created_at'); $grid->column('created_at');
$grid->column('updated_at'); $grid->column('updated_at');
$grid->disableRowSelector();
$grid->filter(function (Grid\Filter $filter) { $grid->filter(function (Grid\Filter $filter) {
$filter->equal('id');
$filter->panel();
$filter->equal('id')->width(2);
$filter->equal('type')->select(admin_trans('product.options.publish_type'))->width(2);
}); });
}); });
} }
@ -55,17 +58,13 @@ class DemandProductController extends AdminController
*/ */
protected function detail($id) protected function detail($id)
{ {
return Show::make($id, new DemandProduct(), function (Show $show) {
return Show::make($id, new DemandProduct(['category:id,name']), function (Show $show) {
$show->field('id'); $show->field('id');
$show->field('supplier_id');
$show->field('category_id');
$show->field('category.name','分类');
$show->field('title'); $show->field('title');
//$show->field('price');
//$show->field('original_price');
$show->field('pictures')->image('', 80, 80); $show->field('pictures')->image('', 80, 80);
//$show->field('stock');
$show->field('sale');
$show->field('status');
$show->field('service_persons','涉及用户数');
$show->field('status')->using(ProductStatus::array());
$show->field('know')->unescape()->as(fn($v) => preg_replace('/<script.*?>.*?<\/script>/is', '', $v)); $show->field('know')->unescape()->as(fn($v) => preg_replace('/<script.*?>.*?<\/script>/is', '', $v));
$show->field('content')->unescape()->as(fn($v) => preg_replace('/<script.*?>.*?<\/script>/is', '', $v)); $show->field('content')->unescape()->as(fn($v) => preg_replace('/<script.*?>.*?<\/script>/is', '', $v));
$show->field('created_at'); $show->field('created_at');
@ -80,6 +79,8 @@ class DemandProductController extends AdminController
*/ */
protected function form() protected function form()
{ {
Admin::user()->publish_type = json_decode(Admin::user()->publish_type, true);
return Form::make(new DemandProduct(), function (Form $form) { return Form::make(new DemandProduct(), function (Form $form) {
//不允许编辑非自己数据 //不允许编辑非自己数据
if ($form->isEditing() && $form->model()->supplier_id != Admin::user()->id) { if ($form->isEditing() && $form->model()->supplier_id != Admin::user()->id) {
@ -91,15 +92,81 @@ class DemandProductController extends AdminController
$options = Category::selectOptions(fn($query) => $query->where('agent_id', 0)); $options = Category::selectOptions(fn($query) => $query->where('agent_id', 0));
$form->select('category_id')->options(array_slice($options, 1, null, true))->required(); $form->select('category_id')->options(array_slice($options, 1, null, true))->required();
$form->text('title')->required(); $form->text('title')->required();
//$form->text('price')->required();
//$form->text('original_price')->required();
//$form->currency('price')->symbol('¥')->required();
//$form->currency('original_price')->symbol('¥')->required();
$form->number('service_persons','涉及用户数')->required();
//$form->number('stock')->required();
$form->multipleImage('pictures')->required()->removable(false)->retainable()->uniqueName(); $form->multipleImage('pictures')->required()->removable(false)->retainable()->uniqueName();
//$form->text('stock')->default(9999)->required();
$form->editor('know'); $form->editor('know');
$form->editor('content')->required(); $form->editor('content')->required();
//扩展字段
$publish_type = array_intersect_key(
admin_trans('product.options.publish_type'),
array_flip(Admin::user()->publish_type)
);
$form->radio('type', '产品类型')
->options($publish_type)
->default(current(Admin::user()->publish_type))
->when(0, function (Form $form) { //旅游线路
$form->table('extends.field_0.project', '包含项目', function (NestedForm $table) {
$table->text('name', '字段1');
$table->text('num', '字段2');
$table->text('price', '字段3');
})->help('第一行数据默认是表头,如:项目名称、数量、额外费用');
$form->dateRange('extends.field_0.date.start', 'extends.field_0.date.end', '行程时间');
})->when(1, function (Form $form) { //酒店
$default = [
['tag' => '行李寄存'], ['tag' => '24小时前台'], ['tag' => '前台保险柜'], ['tag' => '唤醒服务'],
['tag' => '早餐'], ['tag' => '送餐服务'], ['tag' => '电梯'], ['tag' => '空调'],
['tag' => '新风系统'], ['tag' => '24小时热水'], ['tag' => '吹风机'], ['tag' => '加湿器'],
['tag' => '自动售货机'], ['tag' => '健身房'], ['tag' => '桌球室'], ['tag' => '洗衣服务']
];
$form->table('extends.field_1.tags', '酒店设施', function (NestedForm $table) {
$table->text('tag', '包含项目')->placeholder('如:24小时热水、干洗服务等');
})->value($default)->help('首次创建时,系统会默认填充基本服务,请根据本酒店情况进行删减或新增');
$form->text('extends.field_1.name', '酒店名');
$form->text('extends.field_1.address', '地址');
$form->map('extends.field_1.latitude', 'extends.field_1.longitude', '位置');
})->when(2, function (Form $form) { //景区
$form->table('extends.field_2.open_time', '开放时间', function (NestedForm $table) {
$table->text('node', '字段1')->placeholder('如:周一至周五');
$table->text('summer', '字段2')->placeholder('如:08:00~19:00');
$table->text('winter', '字段3')->placeholder('如:08:00~18:00');
})->help('第一行数据默认是表头,如:项目名称、数量、额外费用');
$form->table('extends.field_2.project', '包含项目', function (NestedForm $table) {
$table->text('name', '字段1');
$table->text('num', '字段2');
$table->text('price', '字段3');
})->help('第一行数据默认是表头,如:项目名称、数量、额外费用');
$form->text('extends.field_2.name', '景区名');
$form->text('extends.field_2.address', '地址');
$form->map('extends.field_2.latitude', 'extends.field_2.longitude', '位置');
})->when(3, function (Form $form) { //餐厅
$form->table('extends.field_3.open_time', '开放时间', function (NestedForm $table) {
$table->text('week', '字段1')->placeholder('如:周一至周五');
$table->text('section', '字段2')->placeholder('如:上午/下午');
$table->text('time', '字段3')->placeholder('如:08:00~18:00');
})->help('第一行数据默认是表头,如:项目名称、数量、额外费用');
$form->table('extends.field_3.package', '包含套餐', function (NestedForm $table) {
$table->text('name', '字段1')->placeholder('如:清蒸鱿鱼');
$table->text('num', '字段2')->placeholder('如:1条');
$table->text('price', '字段3')->placeholder('如:99元');
})->help('第一行数据默认是表头,如:项目名称、数量、额外费用');
$form->text('extends.field_3.name', '餐厅名');
$form->text('extends.field_3.address', '地址');
$form->map('extends.field_3.latitude', 'extends.field_3.longitude', '位置');
});
if ($form->isEditing()) { if ($form->isEditing()) {
$form->confirm('提示', '编辑产品需要重新审核,同时<span class="btn-danger">下架所有</span>关联的代理商产品,是否继续?');
$form->confirm('提示', '修改标题、价格、产品图片、旅游须知、产品详情、产品类型及信息需要重新审核,同时<span class="btn-danger">下架所有</span>关联的代理商产品,是否继续?');
} }
})->saving(function (Form $form) { })->saving(function (Form $form) {
//不允许编辑非自己数据 //不允许编辑非自己数据
@ -107,7 +174,11 @@ class DemandProductController extends AdminController
return $form->response()->error('数据不存在'); return $form->response()->error('数据不存在');
} }
//不允许编辑的字段 TODO 忽略字段不起作用
if (!Admin::user()->publish_type || !in_array($form->type, Admin::user()->publish_type)) {
return $form->response()->error('对不起,你没有此类产品的发布、编辑权限');
}
//不允许编辑的字段,忽略字段不起作用?
$form->ignore(['id', 'supplier_id', 'sale', 'status', 'created_at', 'updated_at', 'deleted_at']); $form->ignore(['id', 'supplier_id', 'sale', 'status', 'created_at', 'updated_at', 'deleted_at']);
//null字段转为'' //null字段转为''
@ -118,16 +189,10 @@ class DemandProductController extends AdminController
} }
//特殊字段处理 //特殊字段处理
$form->hidden(['status', 'supplier_id']); //表单没有的字段,必须加上这句才能重置值
$form->status = ProductStatus::UNAUDITED;
$form->supplier_id = Admin::user()->id;
})->saved(function (Form $form, $result) {
//下架代理商产品
if ($result) {
$id = $form->getKey();
AgentProduct::where('product_id', $id)
->orWhere(DB::raw('FIND_IN_SET(' . $id . ', product_ids)')) //TODO product_ids字段可能会去掉
->update(['status' => ProductStatus::SOLD_OUT]);
if ($form->isCreating()) {
$form->hidden(['status', 'supplier_id']); //表单没有的字段,必须加上这句才能重置值
$form->supplier_id = Admin::user()->id;
$form->status = ProductStatus::UNAUDITED;
} }
})->deleting(function (Form $form) { })->deleting(function (Form $form) {
//不允许删除非自己的数据 //不允许删除非自己的数据

5
app/AdminSupplier/Controllers/FinanceStatisticsController.php

@ -109,10 +109,11 @@ HTML;
}); });
$row->column(3, function (Column $column) use ($profit) { $row->column(3, function (Column $column) use ($profit) {
$column->row(Card::make('利润', function () use ($profit) {
$column->row(Card::make('交易费', function () use ($profit) {
$price = Admin::user()->deposit_used;
return <<<HTML return <<<HTML
<div class="d-flex justify-content-between align-items-center mt-1" style="margin-bottom: 2px"> <div class="d-flex justify-content-between align-items-center mt-1" style="margin-bottom: 2px">
<h2 class="ml-1 font-large-1 text-primary">$profit</h2>
<h2 class="ml-1 font-large-1 text-primary">$price</h2>
</div> </div>
HTML; HTML;
})); }));

3
app/Console/Commands/BalanceDue.php

@ -8,6 +8,7 @@ use App\Models\Demand;
use App\Models\Order; use App\Models\Order;
use App\Service\SmsService; use App\Service\SmsService;
use App\Traits\DemandTraits; use App\Traits\DemandTraits;
use App\Traits\SmsTraits;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@ -52,7 +53,7 @@ class BalanceDue extends Command
foreach ($orders as $order) { foreach ($orders as $order) {
if (!empty($order->mobile)) { if (!empty($order->mobile)) {
$type = $order->pay_type == PayType::DEPOSIT_PAY ? '订金' : '定金'; $type = $order->pay_type == PayType::DEPOSIT_PAY ? '订金' : '定金';
$sms->send('pay',['订单号:'.$order->orderNumber,$type,$order->timeout,$type,'小程序'],[$order->mobile]);
$sms->send('pay',['订单号:'.$order->orderNumber,$type,$order->timeout,$type,SmsTraits::$systeaNameText['user']],[$order->mobile]);
} }
} }
} }

38
app/Events/OrderUpdated.php

@ -0,0 +1,38 @@
<?php
namespace App\Events;
use App\Models\Order;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class OrderUpdated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $order;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
///**
// * Get the channels the event should broadcast on.
// *
// * @return \Illuminate\Broadcasting\Channel|array
// */
//public function broadcastOn()
//{
// return new PrivateChannel('channel-name');
//}
}

10
app/Http/Controllers/Api/VerificationController.php

@ -57,16 +57,6 @@ class VerificationController extends Controller
if ($order->pay_type != PayType::OFFLINE) { if ($order->pay_type != PayType::OFFLINE) {
$this->fund($order); $this->fund($order);
} }
//短信
if (env('SMS_SWITCH', '') == true) {
if (!empty($order->user->mobile)) {
(new SmsService)->send('verify', [$order->order_no, SmsTraits::$systeaNameText['user']], [$order->user->mobile]);//用户
}
$supplierIds = OrderProductItem::query()->with('supplier')->where('order_id', $order->id)->distinct()->pluck('supplier_id');
$phone = Supplier::query()->whereIn('id', $supplierIds)->pluck('contact_phone')->toArray();
(new SmsService)->send('verify', [$order->order_no, SmsTraits::$systeaNameText['supplier']], $phone);//供应商
(new SmsService)->send('verify', [$order->order_no, SmsTraits::$systeaNameText['agent']], [$order->agent->contact_phone]);//代理商
}
} }
return $this->success(); return $this->success();

77
app/Listeners/OrderEventSubscriber.php

@ -0,0 +1,77 @@
<?php
namespace App\Listeners;
use App\Common\OrderStatus;
use App\Events\OrderUpdated;
use App\Models\Agent;
use App\Models\OrderProductItem;
use App\Models\Supplier;
use App\Service\SmsService;
use App\Traits\SmsTraits;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
class OrderEventSubscriber
{
public function onOrderUpdated($event)
{
if (env('SMS_SWITCH', '') == true) {
$order = $event->order;
$sms = new SmsService();
//退款通知
if ($order->isDirty('status') && $order->status == OrderStatus::REFUNDING) {
$mobile = Agent::query()->where('id',$order->agent_id)->value('contact_phone');
$sms->send('refund', [$order->order_no, SmsTraits::$systeaNameText['agent']], [$mobile]);
}
//付款通知
if ($order->isDirty('status') && ($order->status == OrderStatus::PAY_EARNEST || $order->status == OrderStatus::PAID)) {
//通知代理商
$mobile = Agent::query()->where('id',$order->agent_id)->value('contact_phone');
if (!empty($mobile)) {
$sms->send('order', [$order->order_no, SmsTraits::$systeaNameText['agent']], [$mobile]);
}
//通知供应商
$supplierIds = OrderProductItem::query()->with('supplier')->where('order_id', $order->id)->distinct()->pluck('supplier_id');
$phone = Supplier::query()->whereIn('id', $supplierIds)->pluck('contact_phone')->toArray();
if (!empty($phone)) {
$sms->send('order', [$order->order_no, SmsTraits::$systeaNameText['supplier']], $phone);//供应商
}
}
//核销
if ($order->isDirty('status') && $order->status == OrderStatus::SUCCESS) {
//通知用户
if (!empty($order->mobile)) {
$sms->send('verify', [$order->order_no, SmsTraits::$systeaNameText['user']], [$order->mobile]);//用户
}
//通知供应商
$supplierIds = OrderProductItem::query()->with('supplier')->where('order_id', $order->id)->distinct()->pluck('supplier_id');
$phone = Supplier::query()->whereIn('id', $supplierIds)->pluck('contact_phone')->toArray();
if(!empty($phone)) {
$sms->send('verify', [$order->order_no, SmsTraits::$systeaNameText['supplier']], $phone);//供应商
}
//通知代理商
$mobile = Agent::query()->where('id',$order->agent_id)->value('contact_phone');
if (!empty($mobile)) {
$sms->send('verify', [$order->order_no, SmsTraits::$systeaNameText['agent']], [$mobile]);//代理商
}
}
}
}
/**
* 为订阅者注册监听器
*
* @param Illuminate\Events\Dispatcher $events
*/
public function subscribe($events)
{
$events->listen(
OrderUpdated::class,
OrderEventSubscriber::class . '@onOrderUpdated'
);
}
}

5
app/Models/Order.php

@ -4,6 +4,7 @@ namespace App\Models;
use App\Common\OrderStatus; use App\Common\OrderStatus;
use App\Common\PayType; use App\Common\PayType;
use App\Events\OrderUpdated;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use App\Common\OrderStatus as Status; use App\Common\OrderStatus as Status;
@ -14,6 +15,10 @@ class Order extends BaseModel
use HasFactory, SoftDeletes; use HasFactory, SoftDeletes;
protected $guarded = ['created_at', 'updated_at']; //不可批量赋值的属性 protected $guarded = ['created_at', 'updated_at']; //不可批量赋值的属性
protected $dispatchesEvents = [
'updated' => OrderUpdated::class,
];
public function scopeComplete($query) public function scopeComplete($query)
{ {
return $query->where('status',OrderStatus::SUCCESS); return $query->where('status',OrderStatus::SUCCESS);

2
app/Providers/EventServiceProvider.php

@ -2,6 +2,7 @@
namespace App\Providers; namespace App\Providers;
use App\Listeners\OrderEventSubscriber;
use App\Listeners\SupplierEventSubscriber; use App\Listeners\SupplierEventSubscriber;
use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
@ -33,5 +34,6 @@ class EventServiceProvider extends ServiceProvider
protected $subscribe = [ protected $subscribe = [
SupplierEventSubscriber::class, SupplierEventSubscriber::class,
OrderEventSubscriber::class,
]; ];
} }

4
config/sms.php

@ -15,6 +15,8 @@ return [
'auto_shelves' => '1120254', //供应商[{供应商名称}]在{时间}上传了一件新的产品,已为您自动上架,如需修改产品利润,请登录{系统名称}查看并修改。 'auto_shelves' => '1120254', //供应商[{供应商名称}]在{时间}上传了一件新的产品,已为您自动上架,如需修改产品利润,请登录{系统名称}查看并修改。
'verify' => '1119775', //您有一笔订单[{订单号}]已成功核销,详情请登录{系统名称}查看 'verify' => '1119775', //您有一笔订单[{订单号}]已成功核销,详情请登录{系统名称}查看
'pay' => '1120244', //您有一笔订单{1}已支付了{2},请在{3}之前支付尾款,未按时支付尾款订单将会失效,且{4}将不做退还,详情请登录{5}系统查看 'pay' => '1120244', //您有一笔订单{1}已支付了{2},请在{3}之前支付尾款,未按时支付尾款订单将会失效,且{4}将不做退还,详情请登录{5}系统查看
]
'order' => '1127625', //您有一笔新成交的订单{1},请及时登录{2}系统查看。
'refund' => '1127630', //您有一笔新的退款订单{1},请及时处理,详情请登录{2}系统查看。
]
], ],
]; ];

32
database/migrations/2021_09_17_182618_update_demand_product_table.php

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class UpdateDemandProductTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('demand_products', function (Blueprint $table) {
$table->json('extends')->default(null)->comment('扩展字段,根据type不同,字段名不同');
$table->tinyInteger('type')->default(0)->comment('0:旅游线路、1:洒店、2:景区、3:餐厅、4:车队、5:单项');
$table->integer('service_persons')->default(1)->comment('service_persons');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}
Loading…
Cancel
Save