Compare commits
133 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 954de121b8 | |||
| 0a01cd95bd | |||
| 5b0ffa0c15 | |||
| 662acf7018 | |||
| 4e7f17091f | |||
| f31019bb0a | |||
| 12aafe8a94 | |||
| 58c0f5637a | |||
| 2d47be7291 | |||
| b1e715c481 | |||
| 025a8538eb | |||
| 393c3acde7 | |||
| e9ad57ad46 | |||
| e54b1515db | |||
| a6475d7d45 | |||
| ba93c0c0cc | |||
| fe97904de0 | |||
| 9a4c0ba09e | |||
| 3057c389ea | |||
| a9f5b39ce9 | |||
| afb6886640 | |||
| b478fd2d65 | |||
| 10535b560a | |||
| e25b97f8bd | |||
| 7b9a40651f | |||
| 5bcbd7f626 | |||
| 94b674d7d8 | |||
| 3f03d292ca | |||
| 24337e8427 | |||
| ccee406ea9 | |||
| 1d693cef96 | |||
| 088840db5e | |||
| 40bf72a4b6 | |||
| 7ac34fcc13 | |||
| feddef6278 | |||
| 1b02f90047 | |||
| c3a5f39ae6 | |||
| ab9e209910 | |||
| 9c5a962c70 | |||
| 5ea7e26b97 | |||
| 3fc36352a1 | |||
| 7f1220ceb3 | |||
| 50db77fc84 | |||
| 6b8c70311b | |||
| 4928479795 | |||
| 016f78f7f9 | |||
| 6753a97806 | |||
| 916741cb54 | |||
| 4dd9c85616 | |||
| fddb5ac67e | |||
| 2b7fcc998a | |||
| 282d055f33 | |||
| a96cc3b518 | |||
| 75d940868b | |||
| c6e7f7edb6 | |||
| 7dc861db0d | |||
| b242208992 | |||
| b2b3def740 | |||
| 0f2e4c3a42 | |||
| 9c398e154f | |||
| 63ab1b7745 | |||
| f90df4c55c | |||
| 93dc936020 | |||
| 68f0f1ddd5 | |||
| 8361a470af | |||
| 2bd62e2d09 | |||
| 11d6565ba4 | |||
| 496d46ee76 | |||
| c6092a4fc2 | |||
| 6380543412 | |||
| 27e6d329cc | |||
| 80fa23f2d3 | |||
| bf32c4607c | |||
| 11d4d6425b | |||
| 72d3066fe6 | |||
| 118b0e31cf | |||
| d526129667 | |||
| 41a809e763 | |||
| c8a8baefdb | |||
| 9c86453d7c | |||
| 37c213e58d | |||
| 0555b4a536 | |||
| c221f8f9ae | |||
| 7baa81ec71 | |||
| c342859b37 | |||
| 003728f6cc | |||
| 31108d613d | |||
| 625ff396a0 | |||
| d7ed54fefe | |||
| 964a5aa6f3 | |||
| c606193665 | |||
| b6988e1746 | |||
| 132364e306 | |||
| e60366b848 | |||
| d10d924e4f | |||
| 01b3c68bec | |||
| 345ae56fe0 | |||
| c286f4467e | |||
| cbba53ca8b | |||
| 98f4fcd98b | |||
| 6aad8eecc4 | |||
| 4ade0e6c35 | |||
| cc54025b9b | |||
| 7d4a84ba5c | |||
| ca3a032058 | |||
| ee864ea5f6 | |||
| 3c0a65b08e | |||
| 259d55b578 | |||
| 2d93ba12f5 | |||
| 3227d5019e | |||
| b457428d7f | |||
| 323ed0fdc4 | |||
| 390c94a6a9 | |||
| 06bf1e01b3 | |||
| 862489e7db | |||
| c7f1aba6fe | |||
| 3a092da3e5 | |||
| 5caaa00b5b | |||
| d293c200e4 | |||
| edc6c77af3 | |||
| 622304ebf0 | |||
| cc779a52f0 | |||
| e92c460ad0 | |||
| b3f2537768 | |||
| 2ed22b91b5 | |||
| e35114f842 | |||
| 6d8adb0700 | |||
| 0cd5af981d | |||
| 880b8717d7 | |||
| 660fd24ed0 | |||
| eb4200a617 | |||
| 15395085cf | |||
| a2d34b9fc9 |
@ -20,6 +20,11 @@
|
||||
6. `php artisan key:generate`
|
||||
7. `php artisan update:super_admin_permissions` 更新超级管理员角色权限
|
||||
|
||||
#### 日常更新
|
||||
1. 更新文件 resources/lang/zh-CN/permission.php
|
||||
2. `php artisan db:seed --class=MenusTableSeeder` 更新菜单
|
||||
3. `php artisan db:seed --class=PermissionsTableSeeder` 更新权限
|
||||
|
||||
#### 更新权限
|
||||
`php artisan db:seed --class=PermissionsTableSeeder`
|
||||
|
||||
|
||||
178
app/Console/Commands/DailySalesReport.php
Normal file
178
app/Console/Commands/DailySalesReport.php
Normal file
@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\BusinessOrder;
|
||||
use App\Models\BusinessOrderItem;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Utils\ArrayUtils;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\DailySalesReport as DailySalesReportModel;
|
||||
|
||||
class DailySalesReport extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'daily:report:sales {S}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '每日销量数据记录';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$s = $this->argument('S');
|
||||
$map = [
|
||||
'S1' => [
|
||||
'startTime' => date('Y-m-d 11:00:00'),
|
||||
'endTime' => date('Y-m-d 12:00:00'),
|
||||
],
|
||||
'S2' => [
|
||||
'startTime' => date('Y-m-d 11:00:00'),
|
||||
'endTime' => date('Y-m-d 13:30:00'),
|
||||
],
|
||||
'S3' => [
|
||||
'startTime' => date('Y-m-d 11:00:00'),
|
||||
'endTime' => date('Y-m-d 15:00:00'),
|
||||
],
|
||||
'S4' => [
|
||||
'startTime' => date('Y-m-d 15:00:00'),
|
||||
'endTime' => date('Y-m-d 16:00:00'),
|
||||
|
||||
],
|
||||
'S5' => [
|
||||
'startTime' => date('Y-m-d 11:00:00'),
|
||||
'endTime' => date('Y-m-d 17:30:00'),
|
||||
],
|
||||
'S6' => [
|
||||
'startTime' => date('Y-m-d 11:00:00'),
|
||||
'endTime' => date('Y-m-d 20:00:00'),
|
||||
],
|
||||
'S7' => [
|
||||
'startTime' => Carbon::yesterday()->format('Y-m-d 11:00:00'),
|
||||
'endTime' => date('Y-m-d 09:30:00'),
|
||||
],
|
||||
];
|
||||
if (!isset($map[$s])) {
|
||||
return;
|
||||
}
|
||||
$startTime = $map[$s]['startTime'];
|
||||
$endTime = $map[$s]['endTime'];
|
||||
|
||||
$businessOrderIds = BusinessOrder::query()
|
||||
->where('confirm_at', '>=', Carbon::parse($startTime)->getPreciseTimestamp(3))
|
||||
->where('confirm_at', '<=', Carbon::parse($endTime)->getPreciseTimestamp(3))
|
||||
->pluck('id');
|
||||
$businessOrderIds = $businessOrderIds->chunk(200);
|
||||
$fields = implode(',', [
|
||||
'external_sku_id',
|
||||
'SUM(already_cancel_number) as total_already_cancel_number',
|
||||
'SUM(goods_number) as total_goods_number',
|
||||
]);
|
||||
|
||||
$data = [];
|
||||
foreach ($businessOrderIds as $ids) {
|
||||
$businessOrderItems = BusinessOrderItem::query()
|
||||
->select(DB::raw($fields))
|
||||
->whereIn('business_order_id', $ids)
|
||||
->where('external_sku_id', '<>', '')
|
||||
->groupBy('external_sku_id')
|
||||
->get();
|
||||
if ($businessOrderItems->isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
foreach ($businessOrderItems as $businessOrderItem) {
|
||||
$arr = explode('_', $businessOrderItem['external_sku_id']);
|
||||
if (2 !== count($arr)) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($data[$businessOrderItem['external_sku_id']])) {
|
||||
$data[$businessOrderItem['external_sku_id']] = [
|
||||
'total_already_cancel_number' => 0,
|
||||
'total_goods_number' => 0,
|
||||
];
|
||||
}
|
||||
$data[$businessOrderItem['external_sku_id']]['total_already_cancel_number'] += $businessOrderItem['total_already_cancel_number'];
|
||||
$data[$businessOrderItem['external_sku_id']]['total_goods_number'] += $businessOrderItem['total_goods_number'];
|
||||
}
|
||||
}
|
||||
|
||||
$date = Carbon::parse($startTime)->format('Y-m-d');
|
||||
$goodsSkus = GoodsSku::query()
|
||||
->select(['goods_id', 'external_sku_id', 'name', 'id', 'goal_rate'])
|
||||
->with(['daily' => function ($query) use ($date) {
|
||||
$query->where('day', $date);
|
||||
}])
|
||||
->whereIn('external_sku_id', array_keys($data))
|
||||
->get();
|
||||
$goodsSkus = ArrayUtils::index($goodsSkus->toArray(), 'external_sku_id');
|
||||
foreach ($data as $externalSkuId => $datum) {
|
||||
if (!isset($goodsSkus[$externalSkuId])) {
|
||||
continue;
|
||||
}
|
||||
$dailySalesReport = DailySalesReportModel::query()
|
||||
->where('date', $date)
|
||||
->where('external_sku_id', $externalSkuId)
|
||||
->first();
|
||||
$sVal = $datum['total_goods_number'] - $datum['total_already_cancel_number'];
|
||||
$sRate = $s . '_rate';
|
||||
$stock = $goodsSkus[$externalSkuId]['daily']['inventory'] + $goodsSkus[$externalSkuId]['daily']['arrived_today_num'];
|
||||
$sRateVal = $stock ? bcdiv($sVal, $stock, 4) : 0;
|
||||
if (is_null($dailySalesReport)) {
|
||||
DailySalesReportModel::query()->updateOrCreate([
|
||||
'date' => $date,
|
||||
'external_sku_id' => $externalSkuId,
|
||||
], [
|
||||
'goods_id' => $goodsSkus[$externalSkuId]['goods_id'],
|
||||
'goods_sku_id' => $goodsSkus[$externalSkuId]['id'],
|
||||
'name' => $goodsSkus[$externalSkuId]['name'],
|
||||
'inventory' => $goodsSkus[$externalSkuId]['daily']['inventory'],
|
||||
'arrived_today_num' => $goodsSkus[$externalSkuId]['daily']['arrived_today_num'],
|
||||
'sales_num' => $sVal,
|
||||
'loss_num' => $goodsSkus[$externalSkuId]['daily']['loss_num'],
|
||||
$s => $sVal,
|
||||
$sRate => $sRateVal,
|
||||
'already_cancel_number' => $datum['total_already_cancel_number'],
|
||||
]);
|
||||
} else {
|
||||
$num = 0;
|
||||
foreach ($map as $key => $val) {
|
||||
if ($key !== $s) {
|
||||
$num += $dailySalesReport->$key;
|
||||
}
|
||||
}
|
||||
$dailySalesReport->update([
|
||||
'inventory' => $goodsSkus[$externalSkuId]['daily']['inventory'],
|
||||
'arrived_today_num' => $goodsSkus[$externalSkuId]['daily']['arrived_today_num'],
|
||||
'sales_num' => $num + $sVal,
|
||||
'loss_num' => $goodsSkus[$externalSkuId]['daily']['loss_num'],
|
||||
$s => $sVal,
|
||||
$sRate => $sRateVal,
|
||||
'already_cancel_number' => $datum['total_already_cancel_number'],
|
||||
'goal_rate' => $goodsSkus[$externalSkuId]['goal_rate'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
127
app/Console/Commands/GoodsSkuDailyReport.php
Normal file
127
app/Console/Commands/GoodsSkuDailyReport.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\BusinessOrderItem;
|
||||
use App\Models\DailyReport;
|
||||
use App\Models\GoodsSku;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class GoodsSkuDailyReport extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'daily:report:goods_sku {date?}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '每日商品数据记录';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$date = $this->argument('date');
|
||||
if (is_null($date)) {
|
||||
$date = Carbon::yesterday()->format('Y-m-d');
|
||||
}
|
||||
$startDateTime = Carbon::parse($date)->startOfDay()->toDateTimeString();
|
||||
$endDateTime = Carbon::parse($date)->endOfDay()->toDateTimeString();
|
||||
|
||||
$orderItems = BusinessOrderItem::query()
|
||||
->select(['shop_id', 'already_cancel_number', 'external_sku_id', 'goods_amount', 'goods_cost_price', 'goods_number', 'goods_price'])
|
||||
->where('external_sku_id', '<>', '')
|
||||
->where('created_at', '>=', $startDateTime)
|
||||
->where('created_at', '<=', $endDateTime)
|
||||
->get();
|
||||
if ($orderItems->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$externalSkuIds = array_unique(array_column($orderItems->toArray(), 'external_sku_id'));
|
||||
$goodsSkus = GoodsSku::query()
|
||||
->select(['id', 'goods_id', 'cost', 'external_sku_id'])
|
||||
->with([
|
||||
'goods:id,type_id,brand_id'
|
||||
])
|
||||
->where('is_combination', 0)
|
||||
->whereIn('external_sku_id', $externalSkuIds)
|
||||
->get()
|
||||
->pluck(null, 'external_sku_id')
|
||||
->toArray();
|
||||
if (empty($goodsSkus)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = [];
|
||||
foreach ($orderItems as $orderItem) {
|
||||
if (!isset($goodsSkus[$orderItem->external_sku_id])) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($data[$orderItem->external_sku_id])) {
|
||||
$data[$orderItem->external_sku_id] = [
|
||||
'goods_id' => $goodsSkus[$orderItem->external_sku_id]['goods']['id'],
|
||||
'type_id' => $goodsSkus[$orderItem->external_sku_id]['goods']['type_id'],
|
||||
'brand_id' => $goodsSkus[$orderItem->external_sku_id]['goods']['brand_id'],
|
||||
'goods_sku_id' => $goodsSkus[$orderItem->external_sku_id]['id'],
|
||||
'cost' => $goodsSkus[$orderItem->external_sku_id]['cost'],
|
||||
'total_goods_price' => 0,
|
||||
'total_goods_cost_price' => 0,
|
||||
'total_goods_amount' => 0,
|
||||
'total_goods_number' => 0,
|
||||
'total_cancel_number' => 0,
|
||||
'shop_data' => [],
|
||||
];
|
||||
}
|
||||
|
||||
$data[$orderItem->external_sku_id]['total_goods_price'] += $orderItem->goods_price;
|
||||
$data[$orderItem->external_sku_id]['total_goods_cost_price'] += $orderItem->goods_cost_price;
|
||||
$data[$orderItem->external_sku_id]['total_goods_amount'] += $orderItem->goods_amount;
|
||||
$data[$orderItem->external_sku_id]['total_goods_number'] += $orderItem->goods_number;
|
||||
$data[$orderItem->external_sku_id]['total_cancel_number'] += $orderItem->already_cancel_number;
|
||||
|
||||
if (!isset($data[$orderItem->external_sku_id]['shop_data'][$orderItem->shop_id])) {
|
||||
$data[$orderItem->external_sku_id]['shop_data'][$orderItem->shop_id] = [
|
||||
'total_goods_price' => 0,
|
||||
'total_goods_cost_price' => 0,
|
||||
'total_goods_amount' => 0,
|
||||
'total_goods_number' => 0,
|
||||
'total_cancel_number' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
$data[$orderItem->external_sku_id]['shop_data'][$orderItem->shop_id]['total_goods_price'] += $orderItem->goods_price;
|
||||
$data[$orderItem->external_sku_id]['shop_data'][$orderItem->shop_id]['total_goods_cost_price'] += $orderItem->goods_cost_price;
|
||||
$data[$orderItem->external_sku_id]['shop_data'][$orderItem->shop_id]['total_goods_amount'] += $orderItem->goods_amount;
|
||||
$data[$orderItem->external_sku_id]['shop_data'][$orderItem->shop_id]['total_goods_number'] += $orderItem->goods_number;
|
||||
$data[$orderItem->external_sku_id]['shop_data'][$orderItem->shop_id]['total_cancel_number'] += $orderItem->already_cancel_number;
|
||||
}
|
||||
|
||||
foreach ($data as $externalSkuId => $datum) {
|
||||
DailyReport::query()->firstOrCreate([
|
||||
'date' => $date,
|
||||
'external_sku_id' => $externalSkuId
|
||||
], $datum);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,18 +2,24 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Events\CreateLogisticEvent;
|
||||
use App\Events\StockUpdateEvent;
|
||||
use App\Exports\DiffTodayPriceGoodsExport;
|
||||
use App\Jobs\SyncCostToMiaoXuan;
|
||||
use App\Models\BusinessGoodsSku;
|
||||
use App\Models\BusinessOrder;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Models\GoodsType;
|
||||
use App\Models\Log;
|
||||
use App\Models\Shop;
|
||||
use App\Models\ShopSender;
|
||||
use App\Models\ShopShip;
|
||||
use App\Models\TodayPrice;
|
||||
use App\Services\Business\BusinessFactory;
|
||||
use App\Services\Business\KuaiTuanTuan\FaceSheet;
|
||||
use App\Services\Ship\WayBillService;
|
||||
use App\Utils\DateTimeUtils;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Jobs\BusinessGoodsSkuIncrQuantity;
|
||||
@ -46,23 +52,7 @@ class Test extends Command
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$shops = Shop::query()->where('plat_id', Shop::$PLAT_KTT)->where('status', Shop::$STATUS_AUTHORIZED)->where('id', 6)->get();
|
||||
foreach ($shops as $shop) {
|
||||
$faceSheet = new FaceSheet();
|
||||
$faceSheet->setShop($shop);
|
||||
var_dump($faceSheet->searchWayBill());
|
||||
}
|
||||
}
|
||||
|
||||
public function getAuthUrl()
|
||||
{
|
||||
return "https://wb.pinduoduo.com/logistics/auth?client_id=24f25877aca447c5830a6aa896301d5e&redirect_uri=http://erp.chutang66.com/pdd/ship";
|
||||
}
|
||||
}
|
||||
|
||||
49
app/Console/Commands/UpdateGoodsSkuName.php
Normal file
49
app/Console/Commands/UpdateGoodsSkuName.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\GoodsSku;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class UpdateGoodsSkuName extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'update:goods_skus:name';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = '更新goods_sku的完整名称';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
GoodsSku::query()
|
||||
->where('name', '')
|
||||
->where('is_combination', 0)
|
||||
->chunk(500, static function ($skus) {
|
||||
foreach ($skus as $sku) {
|
||||
$sku->name = $sku->goods->title . $sku->title;
|
||||
$sku->save();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Console;
|
||||
|
||||
use App\Console\Commands\DailySalesReport;
|
||||
use App\Console\Commands\GoodsSkuDailyReport;
|
||||
use App\Console\Commands\Inventory;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
@ -29,8 +31,19 @@ class Kernel extends ConsoleKernel
|
||||
{
|
||||
// 服务器/etc/crontab添加cron入口
|
||||
// * * * * * cd /home/wwwroot/erp.chutang66.com && php artisan schedule:run >> /dev/null 2>&1
|
||||
$schedule->command(Inventory::class)->dailyAt('07:00');
|
||||
$schedule->command(KttOrderQuery::class)->everyMinute();
|
||||
|
||||
$schedule->command(GoodsSkuDailyReport::class)->dailyAt('06:00');
|
||||
$schedule->command(Inventory::class)->dailyAt('07:00');
|
||||
|
||||
$schedule->command(DailySalesReport::class, ['S1'])->dailyAt('12:00');
|
||||
$schedule->command(DailySalesReport::class, ['S2'])->dailyAt('13:30');
|
||||
$schedule->command(DailySalesReport::class, ['S3'])->dailyAt('15:00');
|
||||
$schedule->command(DailySalesReport::class, ['S4'])->dailyAt('16:00');
|
||||
$schedule->command(DailySalesReport::class, ['S5'])->dailyAt('17:30');
|
||||
$schedule->command(DailySalesReport::class, ['S6'])->dailyAt('20:00');
|
||||
$schedule->command(DailySalesReport::class, ['S7'])->dailyAt('09:30');
|
||||
|
||||
$schedule->command(DeleteKttQuery::class)->daily();
|
||||
}
|
||||
|
||||
|
||||
42
app/Events/BatchStockUpdateEvent.php
Normal file
42
app/Events/BatchStockUpdateEvent.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\GoodsSku;
|
||||
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 BatchStockUpdateEvent
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $goodsSkus;
|
||||
public $combinationGoodsUpdate;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $goodsSkuIds
|
||||
* @param bool $combinationGoodsUpdate
|
||||
*/
|
||||
public function __construct($goodsSkuIds, bool $combinationGoodsUpdate = true)
|
||||
{
|
||||
$this->goodsSkus = GoodsSku::query()->whereIn('id', $goodsSkuIds)->get();
|
||||
$this->combinationGoodsUpdate = $combinationGoodsUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return \Illuminate\Broadcasting\Channel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
}
|
||||
40
app/Events/BusinessOrderCancelEvent.php
Normal file
40
app/Events/BusinessOrderCancelEvent.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
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 BusinessOrderCancelEvent
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $shopId;
|
||||
public $orderSn;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($shopId, $orderSn)
|
||||
{
|
||||
$this->shopId = $shopId;
|
||||
$this->orderSn = $orderSn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return \Illuminate\Broadcasting\Channel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,9 @@
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\DailyStockRecord;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Utils\DateTimeUtils;
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
@ -16,39 +18,51 @@ class BusinessOrdersUpdate
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $businessGoodSku;
|
||||
public $num;
|
||||
public $businessGoods;
|
||||
public $goodsSku;
|
||||
public $goodsSkus;
|
||||
public $combinationGoodsUpdate;
|
||||
public $combinationGoodsUpdate = true;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($item, $num)
|
||||
public function __construct($businessGoodSku, $num)
|
||||
{
|
||||
$this->combinationGoodsUpdate = false;
|
||||
$this->businessGoods = $item->toArray();
|
||||
$this->businessGoodSku = $businessGoodSku->toArray();
|
||||
$this->num = $num;
|
||||
$this->updateStock();
|
||||
}
|
||||
|
||||
private function updateStock()
|
||||
{
|
||||
try {
|
||||
$this->goodsSku = GoodsSku::query()
|
||||
->where('external_sku_id', $this->businessGoods['external_sku_id'])
|
||||
->first();
|
||||
} catch (\Exception $e) {
|
||||
Log::error('事件库存更新失败: ' . $e->getMessage());
|
||||
$this->goodsSku = GoodsSku::query()
|
||||
->where('external_sku_id', $this->businessGoodSku['external_sku_id'])
|
||||
->first();
|
||||
if (is_null($this->goodsSku)) {
|
||||
return false;
|
||||
}
|
||||
if ($this->goodsSku) {
|
||||
$this->goodsSku->stock += $this->num;
|
||||
$this->goodsSku->save();
|
||||
$stock = $this->goodsSku->stock + $this->num;
|
||||
|
||||
if (0 >= $stock) {
|
||||
$this->goodsSku->status = GoodsSku::$STATUS_DOWN;
|
||||
} else {
|
||||
$this->goodsSku->status = GoodsSku::$STATUS_ON_SALE;
|
||||
}
|
||||
|
||||
// 今日到货 + 1T 大于20,且当前剩余库存小于4时 直接下架
|
||||
$arrivedTodayNum = DailyStockRecord::query()
|
||||
->where('day', DateTimeUtils::getToday())
|
||||
->where('sku_id', $this->goodsSku->id)
|
||||
->value('arrived_today_num');
|
||||
if (20 < $arrivedTodayNum + $this->goodsSku->yesterday_num && 4 > $stock) {
|
||||
$this->goodsSku->status = GoodsSku::$STATUS_DOWN;
|
||||
$stock = 0;
|
||||
}
|
||||
|
||||
$this->goodsSku->stock = $stock;
|
||||
$this->goodsSku->save();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
42
app/Events/CreateLogisticEvent.php
Normal file
42
app/Events/CreateLogisticEvent.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
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 CreateLogisticEvent
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $shopId;
|
||||
public $orderSn;
|
||||
public $waybillNo;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($shopId, $orderSn, $waybillNo)
|
||||
{
|
||||
$this->shopId = $shopId;
|
||||
$this->orderSn = $orderSn;
|
||||
$this->waybillNo = $waybillNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return \Illuminate\Broadcasting\Channel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,9 @@
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\DailyStockRecord;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Utils\DateTimeUtils;
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
@ -16,28 +18,38 @@ class StockUpdateEvent
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $goodsSku;
|
||||
public $goodsSkus;
|
||||
public $isBatch;
|
||||
public $combinationGoodsUpdate;
|
||||
public $combinationGoodsUpdate = true;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $data array|object
|
||||
*
|
||||
* @return void
|
||||
* @param $goodsSku
|
||||
*/
|
||||
public function __construct($data, $isBatch = 0, $combinationGoodsUpdate = false)
|
||||
public function __construct($goodsSku)
|
||||
{
|
||||
$this->isBatch = $isBatch;
|
||||
$this->combinationGoodsUpdate = $combinationGoodsUpdate;
|
||||
if (is_array($data)) {
|
||||
// ids集合
|
||||
$this->goodsSkus = GoodsSku::query()->whereIn('id', $data)->get();
|
||||
$this->goodsSku = $goodsSku;
|
||||
$this->checkStatusAndStock($goodsSku);
|
||||
}
|
||||
|
||||
private function checkStatusAndStock($goodsSku)
|
||||
{
|
||||
$stock = $goodsSku->stock;
|
||||
if (0 >= $goodsSku->stock) {
|
||||
$status = GoodsSku::$STATUS_DOWN;
|
||||
} else {
|
||||
// GoodsSku Elo模型对象
|
||||
$this->goodsSku = $data;
|
||||
$status = GoodsSku::$STATUS_ON_SALE;
|
||||
}
|
||||
$arrivedTodayNum = DailyStockRecord::query()
|
||||
->where('day', DateTimeUtils::getToday())
|
||||
->where('sku_id', $goodsSku->id)
|
||||
->value('arrived_today_num');
|
||||
if (20 < $arrivedTodayNum + $goodsSku->yesterday_num && 4 > $goodsSku->stock) {
|
||||
$status = GoodsSku::$STATUS_DOWN;
|
||||
$stock = 0;
|
||||
}
|
||||
$goodsSku->status = $status;
|
||||
$goodsSku->stock = $stock;
|
||||
$goodsSku->save();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
111
app/Exports/WeekDataExport.php
Normal file
111
app/Exports/WeekDataExport.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exports;
|
||||
|
||||
use App\Models\DailyReport;
|
||||
use App\Models\Shop;
|
||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class WeekDataExport implements FromCollection, ShouldAutoSize
|
||||
{
|
||||
private $startDate;
|
||||
private $endDate;
|
||||
private $data;
|
||||
|
||||
public function __construct($startDate, $endDate)
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
$this->endDate = $endDate;
|
||||
$this->data = $this->createData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function collection()
|
||||
{
|
||||
return new Collection($this->data);
|
||||
}
|
||||
|
||||
private function createData()
|
||||
{
|
||||
$headTitle = [
|
||||
'商品名称',
|
||||
'品类',
|
||||
'规格',
|
||||
'品牌',
|
||||
'商品编码',
|
||||
'成本',
|
||||
'销售数量',
|
||||
];
|
||||
$shops = Shop::query()
|
||||
->whereNotIn('id', [7, 9, 10, 11, 17, 18])
|
||||
->orderBy('id')
|
||||
->pluck('name', 'id')
|
||||
->toArray();
|
||||
$headTitle = array_merge($headTitle, array_values($shops));
|
||||
|
||||
$dailyReports = DailyReport::query()
|
||||
->with([
|
||||
'goods:id,title',
|
||||
'goodsType:id,name',
|
||||
'goodsSku:id,title',
|
||||
'goodsBrand:id,name',
|
||||
])
|
||||
->where('date', '>=', $this->startDate)
|
||||
->where('date', '<=', $this->endDate)
|
||||
->get();
|
||||
if ($dailyReports->isEmpty()) {
|
||||
return [$headTitle];
|
||||
}
|
||||
|
||||
$arr = [];
|
||||
foreach ($dailyReports as $item) {
|
||||
$number = $item->total_goods_number - $item->total_cancel_number;
|
||||
if (!isset($arr[$item->external_sku_id])) {
|
||||
$arr[$item->external_sku_id] = [
|
||||
'goodsTitle' => $item->goods->title,
|
||||
'goodsTypeName' => $item->goodsType->name,
|
||||
'goodsSkuTitle' => $item->goodsSku->title,
|
||||
'goodsBrandName' => $item->goodsBrand->name,
|
||||
'external_sku_id' => $item->external_sku_id,
|
||||
'cost' => [],
|
||||
'number' => [],
|
||||
'shops' => []
|
||||
];
|
||||
}
|
||||
$arr[$item->external_sku_id]['cost'][] = $item->cost;
|
||||
$arr[$item->external_sku_id]['number'][] = $number;
|
||||
foreach ($item->shop_data as $shopId => $shopData) {
|
||||
$number = $shopData['total_goods_number'] - $shopData['total_cancel_number'];
|
||||
if (!isset($arr[$item->external_sku_id]['shops'][$shopId])) {
|
||||
$arr[$item->external_sku_id]['shops'][$shopId] = 0;
|
||||
}
|
||||
$arr[$item->external_sku_id]['shops'][$shopId] += $number;
|
||||
}
|
||||
}
|
||||
$bodyData = [];
|
||||
foreach ($arr as $item) {
|
||||
$cost = array_sum($item['cost']) / count($item['cost']);
|
||||
$shopData = [];
|
||||
foreach ($shops as $shopId => $shopName) {
|
||||
$shopData[] = $item['shops'][$shopId] ?? 0;
|
||||
}
|
||||
$data = [
|
||||
$item['goodsTitle'],
|
||||
$item['goodsTypeName'],
|
||||
$item['goodsSkuTitle'],
|
||||
$item['goodsBrandName'],
|
||||
$item['external_sku_id'],
|
||||
$cost,
|
||||
array_sum($item['number']),
|
||||
];
|
||||
|
||||
$bodyData[] = array_merge($data, $shopData);
|
||||
}
|
||||
|
||||
return [$headTitle, $bodyData];
|
||||
}
|
||||
}
|
||||
@ -2,8 +2,17 @@
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\BusinessOrderItem;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class BusinessOrderFilter extends Filters
|
||||
{
|
||||
protected function ids($value)
|
||||
{
|
||||
return $this->builder->whereIn('id', $value);
|
||||
}
|
||||
|
||||
protected function participateNo($value)
|
||||
{
|
||||
return $this->builder->where('participate_no', trim($value));
|
||||
@ -14,6 +23,14 @@ class BusinessOrderFilter extends Filters
|
||||
return $this->builder->where('supply_participate_no', trim($value));
|
||||
}
|
||||
|
||||
protected function pno($value)
|
||||
{
|
||||
return $this->builder->where(function (Builder $builder) use ($value) {
|
||||
$builder->where('participate_no', $value)
|
||||
->orWhere('supply_participate_no', $value);
|
||||
});
|
||||
}
|
||||
|
||||
protected function shopId($value)
|
||||
{
|
||||
return $this->builder->where('shop_id', $value);
|
||||
@ -43,4 +60,39 @@ class BusinessOrderFilter extends Filters
|
||||
{
|
||||
return $this->builder->where('after_sales_status', $value);
|
||||
}
|
||||
|
||||
protected function confirmAtStart($value)
|
||||
{
|
||||
$start = Carbon::parse($value)->timestamp;
|
||||
$start *= 1000;
|
||||
|
||||
return $this->builder->where('confirm_at', '>=', $start);
|
||||
}
|
||||
|
||||
protected function confirmAtEnd($value)
|
||||
{
|
||||
$end = Carbon::parse($value)->timestamp;
|
||||
$end *= 1000;
|
||||
|
||||
return $this->builder->where('confirm_at', '<=', $end);
|
||||
}
|
||||
|
||||
protected function goodsSkuNum($value)
|
||||
{
|
||||
if (1 === $value) {
|
||||
return $this->builder->where('goods_sku_num', '=', 1);
|
||||
}
|
||||
if (2 === $value) {
|
||||
return $this->builder->where('goods_sku_num', '<=', 5)
|
||||
->where('goods_sku_num', '>=', 2);
|
||||
}
|
||||
if (6 === $value) {
|
||||
return $this->builder->where('goods_sku_num', '>=', 6);
|
||||
}
|
||||
}
|
||||
|
||||
protected function printStatus($value)
|
||||
{
|
||||
return $this->builder->where('print_status', $value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,11 +4,6 @@ namespace App\Filters;
|
||||
|
||||
class GoodsFilter extends Filters
|
||||
{
|
||||
protected function goodsTitle($value)
|
||||
{
|
||||
return $this->builder->where('title', 'like', "%$value%");
|
||||
}
|
||||
|
||||
protected function typeId($value)
|
||||
{
|
||||
if($value){
|
||||
|
||||
@ -23,4 +23,9 @@ class GoodsSkuFilter extends Filters
|
||||
{
|
||||
return $this->builder->where('external_sku_id', $value);
|
||||
}
|
||||
|
||||
protected function isCombination($value)
|
||||
{
|
||||
return $this->builder->where('is_combination', $value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,87 +5,111 @@ namespace App\Http\Controllers\Business;
|
||||
use App\Exports\OrderBlankExport;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\BusinessOrder;
|
||||
use App\Models\BusinessOrderItem;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Models\Shop;
|
||||
use App\Services\Ship\WayBillService;
|
||||
use App\Utils\DateTimeUtils;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Resources\BusinessOrderResource;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
|
||||
class BusinessOrderController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$businessOrders = BusinessOrder::query()
|
||||
->where('shop_id', '<>', 8)
|
||||
$shopIds = Shop::query()
|
||||
->where('plat_id', Shop::$PLAT_KTT)
|
||||
->pluck('id');
|
||||
$builder = BusinessOrder::query()
|
||||
->with([
|
||||
'shop:id,name',
|
||||
'items:id,business_order_id,goods_name,goods_number,external_sku_id'
|
||||
])
|
||||
->orderByDesc('confirm_at')
|
||||
->filter()
|
||||
->whereIn('shop_id', $shopIds)
|
||||
->filter();
|
||||
$externalSkuIds = $request->get('external_sku_ids');
|
||||
if ($externalSkuIds) {
|
||||
$ids = BusinessOrderItem::query()->whereIn('external_sku_id', $externalSkuIds)->pluck('business_order_id');
|
||||
$builder->whereIn('id', $ids);
|
||||
}
|
||||
$businessOrders = $builder->orderByDesc('confirm_at')
|
||||
->paginate($request->get('per_page'));
|
||||
|
||||
return BusinessOrderResource::collection($businessOrders);
|
||||
}
|
||||
|
||||
private function getOrderIdsWitmGoodsNum($goodsSkuNum, $orders)
|
||||
{
|
||||
$map = [
|
||||
1 => [
|
||||
'min' => 1,
|
||||
'max' => 1
|
||||
],
|
||||
2 => [
|
||||
'min' => 2,
|
||||
'max' => 5
|
||||
],
|
||||
6 => [
|
||||
'min' => 6,
|
||||
'max' => 999999
|
||||
],
|
||||
];
|
||||
$numMap = $map[$goodsSkuNum];
|
||||
|
||||
// 获取订单商品编码
|
||||
$externalSkuIds = [];
|
||||
foreach ($orders as $order) {
|
||||
foreach ($order->items as $item) {
|
||||
if ($item['external_sku_id']) {
|
||||
$externalSkuIds [] = $item['external_sku_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$goodsSkus = GoodsSku::query()
|
||||
->with('combinationGoods')
|
||||
->whereIn('external_sku_id', $externalSkuIds)
|
||||
->get('external_sku_id');
|
||||
$goodsSkuItems = [];
|
||||
foreach ($goodsSkus as $goodsSku) {
|
||||
$goodsSkuItems[$goodsSku['external_sku_id']] = $goodsSku->combinationGoods->count() ?: 1;
|
||||
}
|
||||
|
||||
$ids = [];
|
||||
foreach ($orders as $order) {
|
||||
$itemNum = 0;
|
||||
foreach ($order->items as $item) {
|
||||
if (0 === $item['cancel_status']) {
|
||||
$itemNum = isset($goodsSkuItems[$item['external_sku_id']]) ? $itemNum + $goodsSkuItems[$item['external_sku_id']] : $itemNum + 1;
|
||||
}
|
||||
}
|
||||
if ($itemNum >= $numMap['min'] && $itemNum <= $numMap['max']) {
|
||||
$ids[] = $order['id'];
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
public function exportOrderBlank(Request $request)
|
||||
{
|
||||
$shopId = $request->get('shop_id');
|
||||
$startNo = $request->get('start_no');
|
||||
$endNo = $request->get('end_no');
|
||||
$isSupplier = $request->get('is_supplier');
|
||||
$field = 'participate_no';
|
||||
if ($isSupplier) {
|
||||
$field = 'supply_participate_no';
|
||||
}
|
||||
$startTime = BusinessOrder::query()
|
||||
->where('shop_id', $shopId)
|
||||
->where('is_supplier', $isSupplier)
|
||||
->where($field, $startNo)
|
||||
->orderByDesc('id')
|
||||
->value('confirm_at');
|
||||
if (empty($startTime)) {
|
||||
exit('开始跟团号订单未查询到或正在同步中,请稍后再次获取');
|
||||
}
|
||||
$startTime = DateTimeUtils::getMicroTime($startTime);
|
||||
$endTime = BusinessOrder::query()
|
||||
->where('shop_id', $shopId)
|
||||
->where('is_supplier', $isSupplier)
|
||||
->where($field, $endNo)
|
||||
->orderByDesc('id')
|
||||
->value('confirm_at');
|
||||
if (empty($endTime)) {
|
||||
exit('结束跟团号订单未查询到或正在同步中,请稍后再次获取');
|
||||
}
|
||||
$endTime = DateTimeUtils::getMicroTime($endTime);
|
||||
if ($startTime > $endTime) {
|
||||
exit('开始跟团号订单 成交时间 大于 结束跟团号订单时间,请查验后再试!');
|
||||
}
|
||||
$orderIds = $request->get('order_ids');
|
||||
$orders = BusinessOrder::query()
|
||||
->with([
|
||||
'items:id,business_order_id,external_sku_id,goods_number,goods_name,already_cancel_number',
|
||||
'items.goodsSkuLocation:id,external_sku_id,location,goods_name'
|
||||
])
|
||||
->where('shop_id', $shopId)
|
||||
->where('confirm_at', '>=', $startTime)
|
||||
->where('confirm_at', '<=', $endTime)
|
||||
->where('after_sales_status', 0)
|
||||
->where('cancel_status', 0)
|
||||
->where('is_supplier', $isSupplier)
|
||||
->orderByDesc('confirm_at')
|
||||
->get(['id', $field]);
|
||||
->whereIn('id', $orderIds)
|
||||
->get(['id']);
|
||||
$distribution = [];
|
||||
$no = [];
|
||||
foreach ($orders as $key => $order) {
|
||||
$index = $key + 1;
|
||||
$no[] = 'P' . $index . '(' . $order->$field . ')';
|
||||
$no[] = 'P' . $index;
|
||||
foreach ($order->items as $item) {
|
||||
$item = $item->toArray();
|
||||
$num = $item['goods_number'] - $item['already_cancel_number'];
|
||||
if (empty($item['external_sku_id']) || empty($num)) {
|
||||
continue;
|
||||
}
|
||||
$local = $item['goods_sku_location'] ? $item['goods_sku_location']['location'] : '无';
|
||||
$index = $key + 1;
|
||||
$index = "P{$index}*{$num}";
|
||||
@ -105,10 +129,10 @@ class BusinessOrderController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
$shopName = Shop::query()->where('id', $shopId)->value('name');
|
||||
$fileName = time();
|
||||
ob_end_clean();
|
||||
|
||||
return Excel::download(new OrderBlankExport($shopName, $no, $distribution), $shopName . date('Y-m-d H:i:s') . '.xlsx');
|
||||
return Excel::download(new OrderBlankExport($fileName, $no, $distribution), $fileName . date('Y-m-d H:i:s') . '.xlsx');
|
||||
}
|
||||
|
||||
public function groupActivity(Request $request, $shopId)
|
||||
@ -123,4 +147,94 @@ class BusinessOrderController extends Controller
|
||||
->get(['activity_title', 'activity_no'])
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public function print(Request $request)
|
||||
{
|
||||
$shopIds = Shop::query()
|
||||
->where('plat_id', Shop::$PLAT_KTT)
|
||||
->pluck('id');
|
||||
$builder = BusinessOrder::query()
|
||||
->with('items')
|
||||
->whereIn('shop_id', $shopIds)
|
||||
->filter();
|
||||
$externalSkuIds = $request->get('external_sku_ids');
|
||||
if ($externalSkuIds) {
|
||||
$ids = BusinessOrderItem::query()->whereIn('external_sku_id', $externalSkuIds)->pluck('business_order_id');
|
||||
$builder->whereIn('id', $ids);
|
||||
}
|
||||
if ($ids = $request->input('ids')) {
|
||||
$builder->whereIn('id', $ids);
|
||||
}
|
||||
$businessOrders = $builder->get();
|
||||
|
||||
$waybill = new WayBillService();
|
||||
$waybill->setOrders($businessOrders);
|
||||
$contents = $waybill->getContents();
|
||||
// 待打印数据
|
||||
[$documents, $orderIds] = $waybill->getDocumentsAndOrderIds($contents);
|
||||
|
||||
return response([
|
||||
'documents' => $this->combinationPrintDocuments($documents),
|
||||
'order_ids' => implode(',', $orderIds),
|
||||
]);
|
||||
}
|
||||
|
||||
private function combinationPrintDocuments($documents)
|
||||
{
|
||||
$documentData = [
|
||||
'data' => [
|
||||
'height' => 240,
|
||||
'list' => [
|
||||
[
|
||||
'fontSize' => 28,
|
||||
// 'height' => 60, // 外部的height/此处的height
|
||||
'left' => 5,
|
||||
'text' => '', // 备注
|
||||
'top' => 10,
|
||||
'width' => 550
|
||||
]
|
||||
],
|
||||
'waterdata' => [
|
||||
'text' => ''
|
||||
],
|
||||
'width' => 560
|
||||
],
|
||||
'templateURL' => "http://pinduoduoimg.yangkeduo.com/logistics/2019-07-14/5d7e8b5969d954539fcfba3268bbeb3a.xml" // 自定义区域模板
|
||||
];
|
||||
$data = [];
|
||||
foreach ($documents as &$document) {
|
||||
$documentData['data']['list'][0]['text'] = $document['participate_no'] ? '[跟团号: ' . $document['participate_no'] . '] ' : '';
|
||||
$documentID = $document['documentID'];
|
||||
$count = 0;
|
||||
foreach ($document['items'] as $item) {
|
||||
$count += $item['count'];
|
||||
$documentData['data']['list'][0]['text'] .= $item['name'] . ' ' . $item['count'] . '件;';
|
||||
}
|
||||
$documentData['data']['list'][0]['text'] .= ' 总计: ' . $count . '件';
|
||||
if ($document['note']) {
|
||||
$documentData['data']['list'][0]['text'] .= ' 备注:' . $document['note'];
|
||||
}
|
||||
unset($document['documentID'], $document['items'], $document['order_id'], $document['participate_no'], $document['note']);
|
||||
$data[] = [
|
||||
'documentID' => $documentID,
|
||||
'contents' => [
|
||||
$document,
|
||||
$documentData
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function printSuccess(Request $request)
|
||||
{
|
||||
$orderIds = $request->input('order_ids');
|
||||
$orderIds = explode(',', $orderIds);
|
||||
BusinessOrder::query()
|
||||
->where('id', $orderIds)
|
||||
->increment('print_status');
|
||||
|
||||
return response(['message' => 'success']);
|
||||
}
|
||||
}
|
||||
|
||||
40
app/Http/Controllers/DataCenter/DataCenterController.php
Normal file
40
app/Http/Controllers/DataCenter/DataCenterController.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\DataCenter;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\DailySalesReportResource;
|
||||
use App\Models\DailySalesReport;
|
||||
use App\Utils\FormatUtils;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class DataCenterController extends Controller
|
||||
{
|
||||
public function salesReport(Request $request)
|
||||
{
|
||||
$sort = $request->get('sort', 'sales_num');
|
||||
$order = $request->get('sortOrder', 'DESC');
|
||||
if (empty($request->get('date'))) {
|
||||
$request->offsetSet('date', date('Y-m-d'));
|
||||
}
|
||||
|
||||
$dailySalesReports = DailySalesReport::query()
|
||||
->filter()
|
||||
->orderBy($sort, $order)
|
||||
->paginate($request->get('per_page'));
|
||||
|
||||
foreach ($dailySalesReports as &$dailySalesReport) {
|
||||
$dailySalesReport['stock'] = $dailySalesReport['inventory'] + $dailySalesReport['arrived_today_num'];
|
||||
$dailySalesReport['goal_rate'] = FormatUtils::getPercent($dailySalesReport['goal_rate'], 1);
|
||||
$dailySalesReport['S1_rate'] = FormatUtils::getPercent($dailySalesReport['S1_rate'], 1);
|
||||
$dailySalesReport['S2_rate'] = FormatUtils::getPercent($dailySalesReport['S2_rate'], 1);
|
||||
$dailySalesReport['S3_rate'] = FormatUtils::getPercent($dailySalesReport['S3_rate'], 1);
|
||||
$dailySalesReport['S4_rate'] = FormatUtils::getPercent($dailySalesReport['S4_rate'], 1);
|
||||
$dailySalesReport['S5_rate'] = FormatUtils::getPercent($dailySalesReport['S5_rate'], 1);
|
||||
$dailySalesReport['S6_rate'] = FormatUtils::getPercent($dailySalesReport['S6_rate'], 1);
|
||||
$dailySalesReport['S7_rate'] = FormatUtils::getPercent($dailySalesReport['S7_rate'], 1);
|
||||
}
|
||||
|
||||
return DailySalesReportResource::collection($dailySalesReports);
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Http\Controllers\Goods;
|
||||
|
||||
use App\Events\StockUpdateEvent;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\GoodsSkuResource;
|
||||
use App\Imports\CombinationGoodsImport;
|
||||
@ -141,7 +140,6 @@ class GoodsCombinationController extends Controller
|
||||
CombinationGood::query()->create(['goods_sku_id' => $sku->id, 'item_id' => $item['item_id'], 'item_num' => $item['item_num']]);
|
||||
}
|
||||
DB::commit();
|
||||
// event(new StockUpdateEvent($sku, 0, true));
|
||||
} catch (\Exception $exception) {
|
||||
DB::rollBack();
|
||||
$this->res = [
|
||||
|
||||
@ -61,6 +61,7 @@ class GoodsController extends Controller
|
||||
$item['stock'] = $item['num'];
|
||||
$item['reference_price'] = $item['cost'] * 1.5;
|
||||
$item['external_sku_id'] = $goods->goods_code . '_' . $item['sku_code'];
|
||||
$item['name'] = $goods->title . $item['title'];
|
||||
$goodsSkus[] = $item;
|
||||
}
|
||||
$collection = $goods->skus()->createMany($goodsSkus)->toArray();
|
||||
|
||||
@ -2,19 +2,24 @@
|
||||
|
||||
namespace App\Http\Controllers\Goods;
|
||||
|
||||
use App\Events\BatchStockUpdateEvent;
|
||||
use App\Events\StockUpdateEvent;
|
||||
use App\Exports\GoodsSkusExport;
|
||||
use App\Exports\WeekDataExport;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\GoodsRequest;
|
||||
use App\Http\Requests\GoodsSkuRequest;
|
||||
use App\Imports\InventoryImport;
|
||||
use App\Imports\NewSetImport;
|
||||
use App\Models\BusinessOrderItem;
|
||||
use App\Models\DailySalesReport;
|
||||
use App\Models\DeveloperConfig;
|
||||
use App\Models\Goods;
|
||||
use App\Models\Log;
|
||||
use App\Models\Log as LogModel;
|
||||
use App\Utils\ArrayUtils;
|
||||
use App\Utils\DateTimeUtils;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Http\Resources\GoodsSkuResource;
|
||||
@ -40,46 +45,85 @@ class GoodsSkusController extends Controller
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$builder = GoodsSku::query();
|
||||
$this->preparQueryGoodsSkus($request, $builder);
|
||||
$day = DateTimeUtils::getToday();
|
||||
$goodsSkus = $builder->filter()
|
||||
->with(['goods' => function ($query) {
|
||||
$query->with(['type:id,name', 'brand:id,name']);
|
||||
}])
|
||||
->with(['daily' => function ($query) use ($day) {
|
||||
$query->where('day', $day);
|
||||
}])
|
||||
->where('is_combination', 0)
|
||||
->orderBy('stock', 'desc')
|
||||
->paginate($request->get('per_page'));
|
||||
$fields = implode(',', [
|
||||
'shop_id',
|
||||
'external_sku_id',
|
||||
'sum(goods_number) as number',
|
||||
'sum(already_cancel_number) as cancel_number',
|
||||
'SUM(goods_number) - SUM(already_cancel_number) as number',
|
||||
]);
|
||||
$orderRestTime = DeveloperConfig::query()
|
||||
->where('key', DeveloperConfig::$ORDER_RESET_TIME)
|
||||
->value('value');
|
||||
if (is_null($orderRestTime)) {
|
||||
$orderRestTime = date('Y-m-d 07:00:00');
|
||||
}
|
||||
$businessOrderItems = BusinessOrderItem::query()
|
||||
->select(DB::raw($fields))
|
||||
->with([
|
||||
'shop:id,name',
|
||||
'goodsSku:id,external_sku_id'
|
||||
])
|
||||
->where('created_at', '>', $orderRestTime)
|
||||
->where('external_sku_id', '<>', '')
|
||||
->groupBy(['shop_id', 'external_sku_id'])
|
||||
->orderByDesc('number')
|
||||
->get()
|
||||
->toArray();
|
||||
$ids = $externals = [];
|
||||
foreach ($businessOrderItems as $businessOrderItem) {
|
||||
if (is_null($businessOrderItem['goods_sku'])) {
|
||||
continue;
|
||||
}
|
||||
$id = $businessOrderItem['goods_sku']['id'];
|
||||
if (isset($ids[$id])) {
|
||||
$ids[$id] += (int)$businessOrderItem['number'];
|
||||
} else {
|
||||
$ids[$id] = (int)$businessOrderItem['number'];
|
||||
}
|
||||
|
||||
$externals[$businessOrderItem['external_sku_id']][] = $businessOrderItem;
|
||||
}
|
||||
arsort($ids);
|
||||
|
||||
$builder = GoodsSku::query();
|
||||
$this->preparQueryGoodsSkus($request, $builder);
|
||||
$day = DateTimeUtils::getToday();
|
||||
$goodsSkus = (clone $builder)->filter()
|
||||
->where('is_combination', 0)
|
||||
->orderByDesc('stock')
|
||||
->pluck('stock', 'id')
|
||||
->toArray();
|
||||
$finalIds = [];
|
||||
foreach ($ids as $id => $number) {
|
||||
if (isset($goodsSkus[$id])) {
|
||||
$finalIds[] = $id;
|
||||
unset($goodsSkus[$id]);
|
||||
}
|
||||
}
|
||||
$finalIds = array_merge($finalIds, array_keys($goodsSkus));
|
||||
$idField = implode(',', $finalIds);
|
||||
|
||||
$goodsSkus = (clone $builder)->with(['goods' => function ($query) {
|
||||
$query->with(['type:id,name', 'brand:id,name']);
|
||||
}])
|
||||
->with(['daily' => function ($query) use ($day) {
|
||||
$query->where('day', $day);
|
||||
}])
|
||||
->whereIn('id', $finalIds)
|
||||
->orderByRaw("FIELD(id, {$idField})")
|
||||
->paginate($request->get('per_page'));
|
||||
|
||||
$rolesName = $request->user()->getRoleNames()->toArray();
|
||||
foreach ($goodsSkus as &$sku) {
|
||||
$lastInventoryTime = $sku['daily']['inventory_time'];
|
||||
$orderDetail = BusinessOrderItem::query()
|
||||
->select(DB::raw($fields))
|
||||
->with(['shop:id,name'])
|
||||
->where('external_sku_id', $sku['external_sku_id'])
|
||||
->when($lastInventoryTime, function ($query) use ($lastInventoryTime) {
|
||||
$query->where('created_at', '>', $lastInventoryTime);
|
||||
})
|
||||
->groupBy(['shop_id', 'external_sku_id'])
|
||||
->get()
|
||||
->toArray();
|
||||
$addOrderGoodsNum = $reduceOrderGoodsNum = 0;
|
||||
if ($orderDetail) {
|
||||
$addOrderGoodsNum = array_sum(array_column($orderDetail, 'number'));
|
||||
$reduceOrderGoodsNum = array_sum(array_column($orderDetail, 'cancel_number'));
|
||||
$lastInventoryTime = $sku['daily']['inventory_time'] ?: date('Y-m-d 07:00:00');
|
||||
if (isset($externals[$sku['external_sku_id']])) {
|
||||
$sku['order_detail'] = $externals[$sku['external_sku_id']];
|
||||
$sku['order_goods_num'] = array_sum(array_column($externals[$sku['external_sku_id']], 'number'));
|
||||
} else {
|
||||
$sku['order_detail'] = [];
|
||||
$sku['order_goods_num'] = 0;
|
||||
}
|
||||
$sku['order_goods_num'] -= $sku['daily']['reissue_num'];
|
||||
$sku['inventory_time'] = $lastInventoryTime;
|
||||
$sku['order_goods_num'] = $addOrderGoodsNum - $reduceOrderGoodsNum;
|
||||
$sku['order_detail'] = $orderDetail;
|
||||
if ('销售' === $rolesName[0]) {
|
||||
$sku['cost'] = 0;
|
||||
}
|
||||
@ -98,10 +142,13 @@ class GoodsSkusController extends Controller
|
||||
->toArray();
|
||||
$builder->whereIn('id', $skuIds);
|
||||
}
|
||||
if ($request->get('goods_title') || $request->get('type_id') || $request->get('brand_id')) {
|
||||
if ($request->get('type_id') || $request->get('brand_id')) {
|
||||
$goodsIds = Goods::query()->filter()->pluck('id')->toArray();
|
||||
$builder->whereIn('goods_id', $goodsIds);
|
||||
}
|
||||
if ($request->get('goods_title')) {
|
||||
$builder->where('name', 'like', '%' . $request->goods_title . '%');
|
||||
}
|
||||
}
|
||||
|
||||
public function show($id)
|
||||
@ -143,6 +190,7 @@ class GoodsSkusController extends Controller
|
||||
$this->setBeforeUpdateForLog($sku->toArray());
|
||||
$skuInfo = $request->sku;
|
||||
$skuInfo['external_sku_id'] = $request->goods['goods_code'] . '_' . $request->sku['sku_code'];
|
||||
$skuInfo['name'] = $request->goods['title'] . $request->sku['title'];
|
||||
$sku->update($skuInfo);
|
||||
$this->setAfterUpdateForLog($sku->toArray());
|
||||
$this->addLog($id, 'update');
|
||||
@ -234,7 +282,8 @@ class GoodsSkusController extends Controller
|
||||
$log = new LogModel();
|
||||
$log->batchInsert($logs);
|
||||
DB::commit();
|
||||
event(new StockUpdateEvent(array_column($request->skus, 'id')));
|
||||
// 批量更新
|
||||
event(new BatchStockUpdateEvent(array_column($request->skus, 'id')));
|
||||
} catch (\Exception $exception) {
|
||||
DB::rollBack();
|
||||
$this->res = [
|
||||
@ -389,7 +438,7 @@ class GoodsSkusController extends Controller
|
||||
$rules = [
|
||||
'updateField' => [
|
||||
'required',
|
||||
Rule::in(['reference_price', 'reserve', 'loss_num', 'status'])
|
||||
Rule::in(['reference_price', 'reserve', 'loss_num', 'status', 'goal_rate'])
|
||||
],
|
||||
'reference_price' => [
|
||||
'sometimes',
|
||||
@ -413,7 +462,12 @@ class GoodsSkusController extends Controller
|
||||
'sometimes',
|
||||
'required',
|
||||
'integer',
|
||||
Rule::in([0, 1, 2])],
|
||||
Rule::in([0, 1, 2])
|
||||
],
|
||||
'goal_rate' => [
|
||||
'sometimes',
|
||||
'numeric',
|
||||
],
|
||||
];
|
||||
$validator = Validator::make($request->all(), $rules);
|
||||
if ($validator->fails()) {
|
||||
@ -451,6 +505,16 @@ class GoodsSkusController extends Controller
|
||||
if (in_array($updateField, ['reserve', 'loss_num'])) {
|
||||
event(new StockUpdateEvent($sku));
|
||||
}
|
||||
// 更新目标去化率
|
||||
if ('goal_rate' === $updateField) {
|
||||
DailySalesReport::query()
|
||||
->where('date', date('Y-m-d'))
|
||||
->where('goods_sku_id', $sku->id)
|
||||
->update([
|
||||
'goal_rate' => $request->$updateField
|
||||
]);
|
||||
}
|
||||
|
||||
$this->addLog($id, $updateField);
|
||||
end:
|
||||
|
||||
@ -482,6 +546,11 @@ class GoodsSkusController extends Controller
|
||||
{
|
||||
$type = $request->get('exportType');
|
||||
ob_end_clean();
|
||||
if ('week_data' === $type) {
|
||||
$startDate = Carbon::now()->subWeek()->startOfWeek()->toDateString();
|
||||
$endDate = Carbon::now()->subWeek()->endOfWeek()->toDateString();
|
||||
return Excel::download(new WeekDataExport($startDate, $endDate), $startDate . '~' . $endDate . '.xlsx');
|
||||
}
|
||||
return Excel::download(new GoodsSkusExport($type), $type . '.xlsx');
|
||||
}
|
||||
|
||||
@ -541,6 +610,11 @@ class GoodsSkusController extends Controller
|
||||
$roseNum += $stock;
|
||||
continue;
|
||||
}
|
||||
// 多头玫瑰
|
||||
if (false !== strpos($externalSkuId, 'D')) {
|
||||
$roseNum += $stock;
|
||||
continue;
|
||||
}
|
||||
// 草花剔除A开头
|
||||
if (false !== strpos($externalSkuId, 'A')) {
|
||||
continue;
|
||||
@ -549,10 +623,14 @@ class GoodsSkusController extends Controller
|
||||
if (false !== strpos($externalSkuId, 'Z')) {
|
||||
continue;
|
||||
}
|
||||
// 剔除N开头年宵花
|
||||
if (false !== strpos($externalSkuId, 'N')) {
|
||||
// 剔除测试CS
|
||||
if (false !== strpos($externalSkuId, 'CS')) {
|
||||
continue;
|
||||
}
|
||||
// 剔除N开头年宵花
|
||||
// if (false !== strpos($externalSkuId, 'N')) {
|
||||
// continue;
|
||||
// }
|
||||
$otherNum += $stock;
|
||||
}
|
||||
|
||||
@ -561,4 +639,24 @@ class GoodsSkusController extends Controller
|
||||
'other_num' => $otherNum,
|
||||
]);
|
||||
}
|
||||
|
||||
public function goodsSkusList(Request $request)
|
||||
{
|
||||
$title = $request->input('title');
|
||||
$data = [];
|
||||
$goodsSkus = GoodsSku::query()
|
||||
->with('goods:id,title')
|
||||
->whereHas('goods', function ($query) use ($title) {
|
||||
$query->where('title', 'like', '%' . $title . '%');
|
||||
})
|
||||
->get(['title', 'external_sku_id', 'goods_id']);
|
||||
foreach ($goodsSkus as $goodsSku) {
|
||||
$data[] = [
|
||||
'external_sku_id' => $goodsSku['external_sku_id'],
|
||||
'title' => $goodsSku['goods']['title'] . ' ' . $goodsSku['title']
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
65
app/Http/Controllers/Shop/ShipController.php
Normal file
65
app/Http/Controllers/Shop/ShipController.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Shop;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\ShopsResource;
|
||||
use App\Models\Shop;
|
||||
use App\Models\ShopSender;
|
||||
use App\Models\ShopShip;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class ShipController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$shops = Shop::query()
|
||||
->select(['id', 'name', 'plat_id'])
|
||||
->with('ship')
|
||||
// ->where('plat_id', 1)
|
||||
->get();
|
||||
$time = date('Y-m-d H:i:s');
|
||||
foreach ($shops as $shop) {
|
||||
$faceSheet = new FaceSheet();
|
||||
$shop->authUrl = $faceSheet->getAuthUrl($shop->id, $shop->plat_id);
|
||||
$shop->status = 0;
|
||||
if ($shop->ship) {
|
||||
$shop->status = $shop->ship->getOriginal('status');
|
||||
if ($shop->ship->expires_at && $time >= $shop->ship->expires_at) {
|
||||
ShopShip::query()->where('shop_id', $shop->id)->update(['status' => Shop::$STATUS_UNAUTHORIZED]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ShopsResource::collection($shops);
|
||||
}
|
||||
|
||||
public function getSenders(Request $request)
|
||||
{
|
||||
$senders = ShopSender::query()
|
||||
->where('shop_id', $request->get('shop_id'))
|
||||
->where('shop_ship_id', $request->get('shop_ship_id'))
|
||||
->orderBy('sort')
|
||||
->get();
|
||||
|
||||
return JsonResource::collection($senders);
|
||||
}
|
||||
|
||||
public function saveSenders(Request $request)
|
||||
{
|
||||
$senderList = $request->input('senderList');
|
||||
foreach ($senderList as $item) {
|
||||
$item = json_decode($item, true);
|
||||
$sender = ShopSender::query()->findOrFail($item['id']);
|
||||
$sender->name = $item['name'];
|
||||
$sender->mobile = $item['mobile'];
|
||||
$sender->sort = $item['sort'];
|
||||
$sender->status = $item['status'];
|
||||
$sender->timed_delivery_code = $item['timed_delivery_code'];
|
||||
$sender->save();
|
||||
}
|
||||
|
||||
return response(['message' => '保存成功']);
|
||||
}
|
||||
}
|
||||
@ -4,10 +4,12 @@ namespace App\Http\Controllers\Shop;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\BusinessGoodsSku;
|
||||
use App\Models\DeveloperConfig;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Models\Shop;
|
||||
use App\Http\Resources\ShopsResource;
|
||||
use App\Services\PrintModule\Pdd\Ktt;
|
||||
use App\Models\ShopSender;
|
||||
use App\Services\Business\KuaiTuanTuan\FaceSheet;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
@ -23,6 +25,9 @@ class ShopsController extends Controller
|
||||
$time = time();
|
||||
foreach ($shops as $shop) {
|
||||
$shop->authUrl = '';
|
||||
if ('已授权' === $shop->status && ($shop->expires_at - time()) / 3600 <= 72) {
|
||||
$shop->status = '重新授权';
|
||||
}
|
||||
if ('妙选' !== $shop->plat_id && ('未授权' === $shop->status || '重新授权' === $shop->status)) {
|
||||
$shop->authUrl = BusinessFactory::init()->make($shop->plat_id)->getAuthUrl($shop->id, $shop->getOriginal('plat_id'));
|
||||
}
|
||||
@ -222,7 +227,36 @@ class ShopsController extends Controller
|
||||
|
||||
public function pddPrintAuth(Request $request)
|
||||
{
|
||||
$ktt = new Ktt();
|
||||
$ktt->auth($request->get('code'));
|
||||
[$shopId, $type] = explode('_', $request->get('state'));
|
||||
$faceSheet = new FaceSheet();
|
||||
$faceSheet->setCode($request->get('code'));
|
||||
$faceSheet->setShopWithId($shopId);
|
||||
$shopShip = $faceSheet->auth('ship', $type);
|
||||
$resp = $faceSheet->searchWayBill();
|
||||
if (!isset($resp['pdd_waybill_search_response']['waybill_apply_subscription_cols'])) {
|
||||
exit();
|
||||
}
|
||||
foreach ($resp['pdd_waybill_search_response']['waybill_apply_subscription_cols'] as $subCols) {
|
||||
foreach ($subCols['branch_account_cols'] as $accountCols) {
|
||||
foreach ($accountCols['shipp_address_cols'] as $item) {
|
||||
$item['wp_code'] = $subCols['wp_code'];
|
||||
ShopSender::query()->updateOrCreate(
|
||||
['shop_id' => $shopId, 'shop_ship_id' => $shopShip->id, 'detail' => $item['detail']],
|
||||
$item
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function orderReset(Request $request)
|
||||
{
|
||||
DeveloperConfig::query()->updateOrCreate([
|
||||
'key' => DeveloperConfig::$ORDER_RESET_TIME,
|
||||
], [
|
||||
'value' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
|
||||
return response($this->res, $this->res['httpCode']);
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,6 +41,10 @@ class GoodsSkuRequest extends FormRequest
|
||||
'sometimes',
|
||||
'integer',
|
||||
],
|
||||
'goal_rate' => [
|
||||
'sometimes',
|
||||
'numeric',
|
||||
],
|
||||
'loss_num' => [
|
||||
'sometimes',
|
||||
'integer',
|
||||
|
||||
19
app/Http/Resources/DailySalesReportResource.php
Normal file
19
app/Http/Resources/DailySalesReportResource.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class DailySalesReportResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return parent::toArray($request);
|
||||
}
|
||||
}
|
||||
@ -2,10 +2,8 @@
|
||||
|
||||
namespace App\Imports;
|
||||
|
||||
use App\Events\StockUpdateEvent;
|
||||
use App\Models\CombinationGood;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Models\GoodsSkuLocation;
|
||||
use App\Utils\ArrayUtils;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
|
||||
@ -72,7 +70,6 @@ class CombinationGoodsImport implements ToArray, SkipsEmptyRows, WithStartRow
|
||||
CombinationGood::query()->create(['goods_sku_id' => $sku->id, 'item_id' => $skus[$item['item_code']]['id'], 'item_num' => $item['item_num']]);
|
||||
}
|
||||
DB::commit();
|
||||
// event(new StockUpdateEvent($sku, 0, true));
|
||||
} catch (\Exception $exception) {
|
||||
DB::rollBack();
|
||||
}
|
||||
|
||||
@ -45,29 +45,29 @@ class GoodsSkusImport implements ToCollection, SkipsEmptyRows
|
||||
}
|
||||
unset($row);
|
||||
$validator = Validator::make($collection, [
|
||||
'*.0' => ['required', 'string', 'max:191'],
|
||||
'*.1' => ['required', 'string', 'max:191', 'exists:goods_types,name'],
|
||||
'*.2' => ['string', 'max:191', 'exists:goods_brands,name'],
|
||||
'*.3' => ['required', 'alpha_dash', 'max:32'],
|
||||
'*.4' => ['required', 'string', 'max:191'],
|
||||
'*.5' => ['required', 'alpha_dash', 'max:32'],
|
||||
'*.0' => ['required', 'string', 'max:191'], // 商品名称
|
||||
'*.1' => ['required', 'string', 'max:191', 'exists:goods_types,name'], // 分类
|
||||
'*.2' => ['string', 'max:191', 'exists:goods_brands,name'], // 品牌
|
||||
'*.3' => ['required', 'alpha_dash', 'max:32'], // 商品编码
|
||||
'*.4' => ['required', 'string', 'max:191'], // 规格名称
|
||||
'*.5' => ['required', 'alpha_dash', 'max:32'], // 规格编码
|
||||
'*.6' => ['required', 'string', Rule::in(['下架', '在售', '预警'])],
|
||||
'*.7' => ['required', 'max:10'],
|
||||
'*.8' => ['required', 'max:10'],
|
||||
'*.7' => ['required', 'max:10'], // 数量
|
||||
'*.8' => ['required', 'max:10'], // 成本
|
||||
]);
|
||||
if ($validator->fails()) {
|
||||
throw new ValidationException($validator);
|
||||
}
|
||||
$types = GoodsType::query()->whereIn('name', $types)->get(['id', 'name'])->toArray();
|
||||
$types = ArrayUtils::index($types, 'name');
|
||||
$brands = GoodsBrand::query()->whereIn('name', $brands)->get(['id', 'name'])->toArray();
|
||||
$brands = ArrayUtils::index($brands, 'name');
|
||||
$hasGoods = Goods::query()->whereIn('goods_code', $goodsCodes)->get(['id', 'goods_code'])->toArray();
|
||||
$hasGoods = ArrayUtils::index($hasGoods, 'goods_code');
|
||||
$types = GoodsType::query()->whereIn('name', $types)->pluck('id', 'name')->toArray();
|
||||
|
||||
$brands = GoodsBrand::query()->whereIn('name', $brands)->pluck('id', 'name')->toArray();
|
||||
|
||||
$hasGoods = Goods::query()->whereIn('goods_code', $goodsCodes)->pluck('id', 'goods_code')->toArray();
|
||||
|
||||
$newGoods = $skus = [];
|
||||
foreach ($collection as $row) {
|
||||
$sku = [
|
||||
'goods_id' => $row[3],
|
||||
'goods_code' => $row[3],
|
||||
'title' => $row[4],
|
||||
'sku_code' => $row[5],
|
||||
'status' => $this->statusMap[$row[6]],
|
||||
@ -75,15 +75,15 @@ class GoodsSkusImport implements ToCollection, SkipsEmptyRows
|
||||
'cost' => $row[8],
|
||||
];
|
||||
// 主商品已存在
|
||||
if (isset($hasGoods[$row[3]])) {
|
||||
$sku['goods_id'] = $hasGoods[$row[3]]['id'];
|
||||
if (isset($hasGoods[$sku['goods_code']])) {
|
||||
$sku['goods_id'] = $hasGoods[$sku['goods_code']];
|
||||
} else {
|
||||
// 新商品
|
||||
$newGoods[$row[3]] = [
|
||||
$newGoods[$sku['goods_code']] = [
|
||||
'title' => $row[0],
|
||||
'type_id' => $types[$row[1]]['id'],
|
||||
'brand_id' => $brands[$row[2]]['id'],
|
||||
'goods_code' => $row[3],
|
||||
'type_id' => $types[$row[1]],
|
||||
'brand_id' => $brands[$row[2]],
|
||||
'goods_code' => $sku['goods_code'],
|
||||
];
|
||||
}
|
||||
$skus[] = $sku;
|
||||
@ -93,11 +93,16 @@ class GoodsSkusImport implements ToCollection, SkipsEmptyRows
|
||||
if ($newGoods) {
|
||||
$goods = new Goods();
|
||||
$goods->batchInsert(array_values($newGoods));
|
||||
$hasGoods = Goods::query()->whereIn('goods_code', array_column($newGoods, 'goods_code'))->get(['id', 'goods_code'])->toArray();
|
||||
$hasGoods = Goods::query()
|
||||
->whereIn('goods_code', array_column($newGoods, 'goods_code'))
|
||||
->get()
|
||||
->toArray();
|
||||
$hasGoods = ArrayUtils::index($hasGoods, 'goods_code');
|
||||
foreach ($skus as &$newGoodsSku) {
|
||||
$newGoodsSku['goods_id'] = isset($hasGoods[$newGoodsSku['goods_id']]) ? $hasGoods[$newGoodsSku['goods_id']]['id'] : $newGoodsSku['goods_id'];
|
||||
$newGoodsSku['external_sku_id'] = isset($hasGoods[$newGoodsSku['goods_id']]) ? $hasGoods[$newGoodsSku['goods_id']]['goods_code'] . '_' . $newGoodsSku['sku_code'] : '';
|
||||
$newGoodsSku['goods_id'] = $hasGoods[$newGoodsSku['goods_code']]['id'];
|
||||
$newGoodsSku['external_sku_id'] = $newGoodsSku['goods_code'] . '_' . $newGoodsSku['sku_code'];
|
||||
$newGoodsSku['name'] = $hasGoods[$newGoodsSku['goods_code']]['title'] . '_' . $newGoodsSku['title'];
|
||||
unset($newGoodsSku['goods_code']);
|
||||
}
|
||||
unset($newGoodsSku);
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Imports;
|
||||
|
||||
use App\Events\BatchStockUpdateEvent;
|
||||
use App\Jobs\SyncCostToMiaoXuan;
|
||||
use App\Models\DailyStockRecord;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Models\TodayPrice;
|
||||
@ -10,7 +12,6 @@ use Exception;
|
||||
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
|
||||
use Maatwebsite\Excel\Concerns\ToArray;
|
||||
use App\Utils\ArrayUtils;
|
||||
use App\Events\StockUpdateEvent;
|
||||
|
||||
class InventoryImport implements ToArray, SkipsEmptyRows
|
||||
{
|
||||
@ -54,6 +55,7 @@ class InventoryImport implements ToArray, SkipsEmptyRows
|
||||
'cost' => $row[4],
|
||||
]);
|
||||
}
|
||||
SyncCostToMiaoXuan::dispatch($row[0], $row[4]);
|
||||
$updateIds[] = $goodsSku['id'];
|
||||
DailyStockRecord::query()->where('sku_id', $goodsSku['id'])->where('day', $day)->update([
|
||||
'arrived_today_num' => $row[3],
|
||||
@ -96,6 +98,7 @@ class InventoryImport implements ToArray, SkipsEmptyRows
|
||||
}
|
||||
}
|
||||
sleep(2);
|
||||
event(new StockUpdateEvent($onSkuIds, 1));
|
||||
// 批量更新
|
||||
event(new BatchStockUpdateEvent($onSkuIds));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,15 +2,15 @@
|
||||
|
||||
namespace App\Imports;
|
||||
|
||||
use App\Events\BatchStockUpdateEvent;
|
||||
use App\Jobs\SyncCostToMiaoXuan;
|
||||
use App\Models\DailyStockRecord;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Models\TodayPrice;
|
||||
use App\Utils\DateTimeUtils;
|
||||
use Exception;
|
||||
use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
|
||||
use Maatwebsite\Excel\Concerns\ToArray;
|
||||
use App\Utils\ArrayUtils;
|
||||
use App\Events\StockUpdateEvent;
|
||||
|
||||
class NewSetImport implements ToArray, SkipsEmptyRows
|
||||
{
|
||||
@ -50,13 +50,17 @@ class NewSetImport implements ToArray, SkipsEmptyRows
|
||||
'stock' => $row[2] + $goodsSku['stock'],
|
||||
]);
|
||||
}
|
||||
SyncCostToMiaoXuan::dispatch($row[0], $row[3]);
|
||||
$updateIds[] = $goodsSku['id'];
|
||||
// 今日到货
|
||||
$record = DailyStockRecord::query()->where('sku_id', $goodsSku['id'])->where('day', $day)->first(['id', 'arrived_today_num']);
|
||||
$record = DailyStockRecord::query()
|
||||
->where('sku_id', $goodsSku['id'])
|
||||
->where('day', $day)->first(['id', 'arrived_today_num']);
|
||||
$record->arrived_today_num += $row[2];
|
||||
$record->save();
|
||||
}
|
||||
sleep(2);
|
||||
event(new StockUpdateEvent($updateIds, 1));
|
||||
// 批量更新
|
||||
event(new BatchStockUpdateEvent($updateIds));
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ class BusinessGoodsSkuIncrQuantity implements ShouldQueue
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $shop;
|
||||
public $businessGoods;
|
||||
public $businessGoodsSku;
|
||||
public $num;
|
||||
public $isIncremental = true;
|
||||
|
||||
@ -23,10 +23,10 @@ class BusinessGoodsSkuIncrQuantity implements ShouldQueue
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($shop, $businessGoods, $num, $isIncremental)
|
||||
public function __construct($shop, $businessGoodsSku, $num, $isIncremental)
|
||||
{
|
||||
$this->shop = $shop;
|
||||
$this->businessGoods = $businessGoods;
|
||||
$this->businessGoodsSku = $businessGoodsSku;
|
||||
$this->num = $num;
|
||||
$this->isIncremental = $isIncremental;
|
||||
}
|
||||
@ -38,8 +38,8 @@ class BusinessGoodsSkuIncrQuantity implements ShouldQueue
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if ($this->businessGoods) {
|
||||
BusinessFactory::init()->make($this->shop['plat_id'])->setShopWithId($this->shop['id'])->incrQuantity($this->businessGoods, $this->num, $this->isIncremental);
|
||||
if ($this->businessGoodsSku) {
|
||||
BusinessFactory::init()->make($this->shop['plat_id'])->setShopWithId($this->shop['id'])->incrQuantity($this->businessGoodsSku, $this->num, $this->isIncremental);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
50
app/Jobs/SyncCostToMiaoXuan.php
Normal file
50
app/Jobs/SyncCostToMiaoXuan.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SyncCostToMiaoXuan implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $externalSkuId;
|
||||
public $cost;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($externalSkuId, $cost)
|
||||
{
|
||||
$this->externalSkuId = $externalSkuId;
|
||||
$this->cost = $cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$url = 'http://shop.chutang66.com/miaoxuan/cost';
|
||||
$method = 'PUT';
|
||||
$headers = [
|
||||
'headers' => ['Content-type' => 'application/x-www-form-urlencoded;charset=UTF-8'],
|
||||
'form_params' => [
|
||||
'external_sku_id' => $this->externalSkuId,
|
||||
'cost' => $this->cost,
|
||||
]
|
||||
];
|
||||
(new Client())->request($method, $url, $headers);
|
||||
}
|
||||
}
|
||||
52
app/Listeners/BatchStockUpdateListener.php
Normal file
52
app/Listeners/BatchStockUpdateListener.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Events\BatchStockUpdateEvent;
|
||||
use App\Models\BusinessGoodsSku;
|
||||
use App\Models\Shop;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use App\Services\Business\BusinessFactory;
|
||||
|
||||
class BatchStockUpdateListener implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param BatchStockUpdateEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(BatchStockUpdateEvent $event)
|
||||
{
|
||||
$shops = Shop::query()->whereNotIn('status', [Shop::$STATUS_UNAUTHORIZED, Shop::$STATUS_STOP])->get(['id', 'plat_id']);
|
||||
if (empty($shops)) {
|
||||
return;
|
||||
}
|
||||
foreach ($shops as $shop) {
|
||||
foreach ($event->goodsSkus as $goodsSku) {
|
||||
$num = $goodsSku->stock;
|
||||
$businessGoodsSkus = BusinessGoodsSku::query()
|
||||
->select(['goods_id', 'sku_id', 'external_sku_id'])
|
||||
->where('shop_id', $shop->id)
|
||||
->where('is_sync', 1)
|
||||
->where('external_sku_id', $goodsSku->external_sku_id)
|
||||
->get();
|
||||
BusinessFactory::init()->make($shop['plat_id'])->setShopWithId($shop['id'])->batchIncrQuantity($businessGoodsSkus->toArray(), $num, false);
|
||||
usleep(140);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
app/Listeners/CancelLogisticListener.php
Normal file
47
app/Listeners/CancelLogisticListener.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Events\CreateLogisticEvent;
|
||||
use App\Models\Shop;
|
||||
use App\Models\Waybill;
|
||||
use App\Services\Business\BusinessFactory;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
|
||||
class CancelLogisticListener implements ShouldQueue
|
||||
{
|
||||
public $connection = 'redis';
|
||||
|
||||
public $queue = 'listeners';
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param CreateLogisticEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(CreateLogisticEvent $event)
|
||||
{
|
||||
$waybillNo = Waybill::query()
|
||||
->where('shop_id', $event->shopId)
|
||||
->where('order_sn', $event->orderSn)
|
||||
->value('waybill_code');
|
||||
if (empty($waybillNo)) {
|
||||
return;
|
||||
}
|
||||
$shop = Shop::query()->findOrFail($event->shopId);
|
||||
$client = BusinessFactory::init()->make($shop['plat_id'])->setShop($shop);
|
||||
$client->cancelLogistic($event->orderSn, $event->waybillNo);
|
||||
}
|
||||
}
|
||||
@ -3,13 +3,17 @@
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Models\CombinationGood;
|
||||
use App\Models\DailyStockRecord;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Utils\DateTimeUtils;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use App\Events\StockUpdateEvent;
|
||||
use App\Events\BatchStockUpdateEvent;
|
||||
|
||||
class CombinationGoodsStockUpdateListener
|
||||
class CombinationGoodsStockUpdateListener implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
@ -28,18 +32,19 @@ class CombinationGoodsStockUpdateListener
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
if ($event->combinationGoodsUpdate) {
|
||||
if (!$event->combinationGoodsUpdate) {
|
||||
return false;
|
||||
}
|
||||
$updateIds = $combinationGoodsIds = $combinationGoodsItemIds = [];
|
||||
if ($event->goodsSku) {
|
||||
if (!empty($event->goodsSku)) {
|
||||
if ($event->goodsSku->is_combination) {
|
||||
$combinationGoodsIds[] = $event->goodsSku->id;
|
||||
} else {
|
||||
$combinationGoodsItemIds[] = $event->goodsSku->id;
|
||||
}
|
||||
}
|
||||
if ($event->goodsSkus) {
|
||||
|
||||
if (!empty($event->goodsSkus)) {
|
||||
foreach ($event->goodsSkus as $sku) {
|
||||
if ($sku->is_combination) {
|
||||
$combinationGoodsIds[] = $sku->id;
|
||||
@ -55,21 +60,20 @@ class CombinationGoodsStockUpdateListener
|
||||
->whereIn('goods_sku_id', $combinationGoodsIds)
|
||||
->get();
|
||||
foreach ($combinationGoods as $item) {
|
||||
$sku = GoodsSku::query()->find($item['item_id']);
|
||||
$sku->stock -= $item['item_num'];
|
||||
$sku->save();
|
||||
$updateIds[] = $sku->id;
|
||||
$goodsSku = GoodsSku::query()->find($item['item_id']);
|
||||
$stock = $goodsSku->stock - $item['item_num'];
|
||||
[$status, $stock] = $this->checkStatusAndStock($goodsSku, $stock);
|
||||
$goodsSku->status = $status;
|
||||
$goodsSku->stock = $stock;
|
||||
$goodsSku->save();
|
||||
$updateIds[] = $goodsSku->id;
|
||||
}
|
||||
}
|
||||
// 计算主商品库存
|
||||
if ($combinationGoodsItemIds) {
|
||||
$goodsSkuIds = CombinationGood::query()
|
||||
->whereIn('item_id', $combinationGoodsItemIds)
|
||||
->pluck('goods_sku_id')
|
||||
->toArray();
|
||||
if (empty($goodsSkuIds)) {
|
||||
return false;
|
||||
}
|
||||
->pluck('goods_sku_id');
|
||||
foreach ($goodsSkuIds as $goodsSkuId) {
|
||||
$combinationGoods = CombinationGood::query()
|
||||
->with('goodsSkuItem:id,stock')
|
||||
@ -80,13 +84,37 @@ class CombinationGoodsStockUpdateListener
|
||||
$stock[] = (int)($goods['goodsSkuItem']['stock'] / $goods['item_num']);
|
||||
}
|
||||
$stock = min($stock);
|
||||
GoodsSku::query()->where('id', $goodsSkuId)->update(['stock' => $stock]);
|
||||
$goodsSku = GoodsSku::query()->find($goodsSkuId);
|
||||
[$status, $stock] = $this->checkStatusAndStock($goodsSku, $stock);
|
||||
$goodsSku->status = $status;
|
||||
$goodsSku->stock = $stock;
|
||||
$goodsSku->save();
|
||||
$updateIds[] = $goodsSkuId;
|
||||
}
|
||||
}
|
||||
if ($updateIds) {
|
||||
$updateIds = array_unique($updateIds);
|
||||
event(new StockUpdateEvent($updateIds, 1, true));
|
||||
// 批量更新
|
||||
event(new BatchStockUpdateEvent($updateIds, false));
|
||||
}
|
||||
}
|
||||
|
||||
private function checkStatusAndStock($goodsSku, $stock)
|
||||
{
|
||||
if (0 >= $stock) {
|
||||
$status = GoodsSku::$STATUS_DOWN;
|
||||
} else {
|
||||
$status = GoodsSku::$STATUS_ON_SALE;
|
||||
}
|
||||
$arrivedTodayNum = DailyStockRecord::query()
|
||||
->where('day', DateTimeUtils::getToday())
|
||||
->where('sku_id', $goodsSku->id)
|
||||
->value('arrived_today_num');
|
||||
if (20 < $arrivedTodayNum + $goodsSku->yesterday_num && 4 > $stock) {
|
||||
$status = GoodsSku::$STATUS_DOWN;
|
||||
$stock = 0;
|
||||
}
|
||||
|
||||
return [$status, $stock];
|
||||
}
|
||||
}
|
||||
|
||||
39
app/Listeners/CreateLogisticListener.php
Normal file
39
app/Listeners/CreateLogisticListener.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Events\CreateLogisticEvent;
|
||||
use App\Models\Shop;
|
||||
use App\Services\Business\BusinessFactory;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
|
||||
class CreateLogisticListener implements ShouldQueue
|
||||
{
|
||||
public $connection = 'redis';
|
||||
|
||||
public $queue = 'listeners';
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param CreateLogisticEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(CreateLogisticEvent $event)
|
||||
{
|
||||
$shop = Shop::query()->findOrFail($event->shopId);
|
||||
$client = BusinessFactory::init()->make($shop['plat_id'])->setShop($shop);
|
||||
$client->createLogistic($event->orderSn, $event->waybillNo);
|
||||
}
|
||||
}
|
||||
@ -3,15 +3,16 @@
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Events\StockUpdateEvent;
|
||||
use App\Jobs\BusinessGoodsSkuIncrQuantity;
|
||||
use App\Models\BusinessGoodsSku;
|
||||
use App\Models\Shop;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use App\Services\Business\BusinessFactory;
|
||||
|
||||
class StockUpdateListener
|
||||
class StockUpdateListener implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
@ -35,40 +36,14 @@ class StockUpdateListener
|
||||
return;
|
||||
}
|
||||
foreach ($shops as $shop) {
|
||||
if (isset($event->goodsSku)) {
|
||||
$num = $event->goodsSku->stock;
|
||||
$businessGoodsSkus = BusinessGoodsSku::query()
|
||||
->select(['goods_id', 'sku_id', 'external_sku_id'])
|
||||
->where('shop_id', $shop->id)
|
||||
->where('is_sync', 1)
|
||||
->where('external_sku_id', $event->goodsSku->external_sku_id)
|
||||
->get();
|
||||
if ($event->isBatch) {
|
||||
BusinessFactory::init()->make($shop['plat_id'])->setShopWithId($shop['id'])->batchIncrQuantity($businessGoodsSkus->toArray(), $num, false);
|
||||
} else {
|
||||
foreach ($businessGoodsSkus as $businessGoodsSku) {
|
||||
BusinessGoodsSkuIncrQuantity::dispatch($shop, $businessGoodsSku->toArray(), $num, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($event->goodsSkus)) {
|
||||
foreach ($event->goodsSkus as $goodsSku) {
|
||||
$num = $goodsSku->stock;
|
||||
$businessGoodsSkus = BusinessGoodsSku::query()
|
||||
->select(['goods_id', 'sku_id', 'external_sku_id'])
|
||||
->where('shop_id', $shop->id)
|
||||
->where('is_sync', 1)
|
||||
->where('external_sku_id', $goodsSku->external_sku_id)
|
||||
->get();
|
||||
if ($event->isBatch) {
|
||||
BusinessFactory::init()->make($shop['plat_id'])->setShopWithId($shop['id'])->batchIncrQuantity($businessGoodsSkus->toArray(), $num, false);
|
||||
} else {
|
||||
foreach ($businessGoodsSkus as $businessGoodsSku) {
|
||||
BusinessGoodsSkuIncrQuantity::dispatch($shop, $businessGoodsSku->toArray(), $num, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$num = $event->goodsSku->stock;
|
||||
$businessGoodsSkus = BusinessGoodsSku::query()
|
||||
->select(['goods_id', 'sku_id', 'external_sku_id'])
|
||||
->where('shop_id', $shop->id)
|
||||
->where('is_sync', 1)
|
||||
->where('external_sku_id', $event->goodsSku->external_sku_id)
|
||||
->get();
|
||||
BusinessFactory::init()->make($shop['plat_id'])->setShopWithId($shop['id'])->batchIncrQuantity($businessGoodsSkus->toArray(), $num, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Models\GoodsSku;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
|
||||
class StockWarning implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function handle($event)
|
||||
{
|
||||
if (isset($event->goodsSku)) {
|
||||
$event->goodsSku->status = 2;
|
||||
if (0 >= $event->goodsSku->stock) {
|
||||
$event->goodsSku->status = 0;
|
||||
}
|
||||
if (5 < $event->goodsSku->stock) {
|
||||
$event->goodsSku->status = 1;
|
||||
}
|
||||
$event->goodsSku->save();
|
||||
}
|
||||
if (isset($event->goodsSkus)) {
|
||||
$warningIds = $normalIds = $downIds = [];
|
||||
foreach ($event->goodsSkus as $goodsSku) {
|
||||
if (0 >= $goodsSku['stock']) {
|
||||
$downIds[] = $goodsSku['id'];
|
||||
} elseif (5 < $goodsSku['stock']) {
|
||||
$normalIds[] = $goodsSku['id'];
|
||||
} else {
|
||||
$warningIds[] = $goodsSku['id'];
|
||||
}
|
||||
}
|
||||
if ($warningIds) {
|
||||
GoodsSku::query()->whereIn('id', $warningIds)->update(['status' => 2]);
|
||||
}
|
||||
if ($normalIds) {
|
||||
GoodsSku::query()->whereIn('id', $normalIds)->update(['status' => 1]);
|
||||
}
|
||||
if ($downIds) {
|
||||
GoodsSku::query()->whereIn('id', $downIds)->update(['status' => 0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,7 @@ class UpdateBusinessGoodsStock implements ShouldQueue
|
||||
* Handle the event.
|
||||
*
|
||||
* @param BusinessOrdersUpdate $event
|
||||
* @return void
|
||||
* @return false|void
|
||||
*/
|
||||
public function handle(BusinessOrdersUpdate $event)
|
||||
{
|
||||
@ -41,17 +41,19 @@ class UpdateBusinessGoodsStock implements ShouldQueue
|
||||
$log->target_id = $event->goodsSku->id ?? 0;
|
||||
$log->target_field = 'stock';
|
||||
$log->user_id = 999;
|
||||
$log->message = '未找到' . json_encode($event->businessGoods, 256);
|
||||
$log->message = '未找到' . json_encode($event->businessGoodSku, 256);
|
||||
$log->save();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$builder = Shop::query()->whereNotIn('status', [Shop::$STATUS_UNAUTHORIZED, Shop::$STATUS_STOP]);
|
||||
// 非订单影响库存变更,只更新本店铺下商品
|
||||
if (!isset($event->businessGoods['business_order_id'])) {
|
||||
$builder->where('id', $event->businessGoods['shop_id']);
|
||||
if (!isset($event->businessGoodSku['business_order_id'])) {
|
||||
$builder->where('id', $event->businessGoodSku['shop_id']);
|
||||
}
|
||||
$shops = $builder->get(['id', 'plat_id']);
|
||||
|
||||
if (empty($shops)) {
|
||||
LogFile::info('可操作店铺为空');
|
||||
return false;
|
||||
@ -59,9 +61,14 @@ class UpdateBusinessGoodsStock implements ShouldQueue
|
||||
|
||||
foreach ($shops as $shop) {
|
||||
$num = $event->goodsSku->stock;
|
||||
$businessGoodsSkus = BusinessGoodsSku::query()->where('shop_id', $shop->id)->where('is_sync', 1)->where('external_sku_id', $event->businessGoods['external_sku_id'])->get();
|
||||
$businessGoodsSkus = BusinessGoodsSku::query()
|
||||
->where('shop_id', $shop->id)
|
||||
->where('is_sync', 1)
|
||||
->where('external_sku_id', $event->businessGoodSku['external_sku_id'])
|
||||
->get();
|
||||
foreach ($businessGoodsSkus as $businessGoodsSku) {
|
||||
BusinessGoodsSkuIncrQuantity::dispatch($shop, $businessGoodsSku->toArray(), $num, false);
|
||||
usleep(140);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,12 @@ class BusinessOrder extends Model
|
||||
'cancel_status',
|
||||
'after_sales_status',
|
||||
'supply_participate_no',
|
||||
'confirm_at_start',
|
||||
'confirm_at_end',
|
||||
'goods_sku_num',
|
||||
'print_status',
|
||||
'ids',
|
||||
'pno',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
@ -63,21 +69,21 @@ class BusinessOrder extends Model
|
||||
|
||||
public function getShippingStatusAttribute($value)
|
||||
{
|
||||
$map = ['未发货', '已发货', '部分发货'];
|
||||
$map = ['未发货', '已发货', '部分发货', '' => ''];
|
||||
|
||||
return $map[$value];
|
||||
}
|
||||
|
||||
public function getIsSupplierAttribute($value)
|
||||
{
|
||||
$map = ['帮忙团订单', '自卖团订单'];
|
||||
$map = ['帮忙团订单', '自卖团订单', '' => ''];
|
||||
|
||||
return $map[$value];
|
||||
}
|
||||
|
||||
public function getCancelStatusAttribute($value)
|
||||
{
|
||||
$map = ['未取消', '已取消'];
|
||||
$map = ['未取消', '已取消', '' => ''];
|
||||
|
||||
return $map[$value];
|
||||
}
|
||||
|
||||
@ -44,4 +44,9 @@ class BusinessOrderItem extends Model
|
||||
{
|
||||
return $this->hasOne(GoodsSkuLocation::class, 'external_sku_id', 'external_sku_id');
|
||||
}
|
||||
|
||||
public function goodsSku()
|
||||
{
|
||||
return $this->hasOne(GoodsSku::class, 'external_sku_id', 'external_sku_id');
|
||||
}
|
||||
}
|
||||
|
||||
34
app/Models/DailyReport.php
Normal file
34
app/Models/DailyReport.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class DailyReport extends Model
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
'shop_data' => 'array',
|
||||
];
|
||||
|
||||
public function goods()
|
||||
{
|
||||
return $this->hasOne(Goods::class, 'id', 'goods_id');
|
||||
}
|
||||
|
||||
public function goodsBrand()
|
||||
{
|
||||
return $this->belongsTo(GoodsBrand::class, 'brand_id', 'id');
|
||||
}
|
||||
|
||||
public function goodsType()
|
||||
{
|
||||
return $this->belongsTo(GoodsType::class, 'type_id', 'id');
|
||||
}
|
||||
|
||||
public function goodsSku()
|
||||
{
|
||||
return $this->hasOne(GoodsSku::class, 'id', 'goods_sku_id');
|
||||
}
|
||||
}
|
||||
19
app/Models/DailySalesReport.php
Normal file
19
app/Models/DailySalesReport.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\traits\Filter;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class DailySalesReport extends Model
|
||||
{
|
||||
use Filter;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public $fieldSearchable = [
|
||||
'date',
|
||||
'name' => 'like',
|
||||
'sales_num' => '>',
|
||||
];
|
||||
}
|
||||
12
app/Models/DeveloperConfig.php
Normal file
12
app/Models/DeveloperConfig.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class DeveloperConfig extends Model
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
public static $ORDER_RESET_TIME = 'order_reset_time';
|
||||
}
|
||||
@ -10,7 +10,6 @@ class Goods extends Model
|
||||
|
||||
//查询字段
|
||||
public $fieldSearchable = [
|
||||
'goods_title',
|
||||
'type_id',
|
||||
'brand_id',
|
||||
];
|
||||
|
||||
@ -13,7 +13,8 @@ class GoodsSku extends Model
|
||||
'sku_title',
|
||||
'status',
|
||||
'exclude_ids',
|
||||
'external_sku_id'
|
||||
'external_sku_id',
|
||||
'is_combination',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
@ -31,10 +32,14 @@ class GoodsSku extends Model
|
||||
'thumb_url',
|
||||
'external_sku_id',
|
||||
'is_combination',
|
||||
'name',
|
||||
];
|
||||
|
||||
protected $hidden = ['created_at'];
|
||||
|
||||
public static $STATUS_ON_SALE = 1;
|
||||
public static $STATUS_DOWN = 0;
|
||||
|
||||
/**
|
||||
* 获取状态
|
||||
*
|
||||
|
||||
@ -26,7 +26,6 @@ class Shop extends Model
|
||||
'access_token',
|
||||
'expires_in',
|
||||
'refresh_token',
|
||||
'refresh_token_expires_at',
|
||||
'refresh_token_expires_in',
|
||||
'pop_auth_token_create_response',
|
||||
];
|
||||
@ -42,10 +41,8 @@ class Shop extends Model
|
||||
1 => '已授权',
|
||||
2 => '无需授权',
|
||||
3 => '停用',
|
||||
'重新授权' => '重新授权',
|
||||
];
|
||||
if (1 === (int)$value && ($this->attributes['expires_at'] - time()) / 3600 <= 72) {
|
||||
return '重新授权';
|
||||
}
|
||||
|
||||
return $map[$value];
|
||||
}
|
||||
@ -61,4 +58,14 @@ class Shop extends Model
|
||||
|
||||
return $map[$value];
|
||||
}
|
||||
|
||||
public function getRefreshTokenExpiresAtAttribute($value)
|
||||
{
|
||||
return $value ? date('Y-m-d H:i:s', $value) : '';
|
||||
}
|
||||
|
||||
public function ship()
|
||||
{
|
||||
return $this->hasOne(ShopShip::class, 'shop_id', 'id');
|
||||
}
|
||||
}
|
||||
|
||||
10
app/Models/ShopSender.php
Normal file
10
app/Models/ShopSender.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ShopSender extends Model
|
||||
{
|
||||
protected $guarded = [];
|
||||
}
|
||||
49
app/Models/ShopShip.php
Normal file
49
app/Models/ShopShip.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ShopShip extends Model
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
public function shop()
|
||||
{
|
||||
return $this->belongsTo(Shop::class, 'shop_id', 'id');
|
||||
}
|
||||
|
||||
public function getStatusAttribute($value)
|
||||
{
|
||||
$map = [
|
||||
0 => '未授权',
|
||||
1 => '已授权',
|
||||
3 => '停用',
|
||||
];
|
||||
if (1 === (int)$value && ($this->attributes['expires_at'] - time()) / 3600 <= 72) {
|
||||
return '重新授权';
|
||||
}
|
||||
|
||||
return $map[$value];
|
||||
}
|
||||
|
||||
public function getExpiresAtAttribute($value)
|
||||
{
|
||||
return $value ? date('Y-m-d H:i:s', $value) : '';
|
||||
}
|
||||
|
||||
public function getTypeAttribute($value)
|
||||
{
|
||||
$map = [
|
||||
'normal' => '电商标快',
|
||||
'air' => '空运',
|
||||
];
|
||||
|
||||
return $map[$value];
|
||||
}
|
||||
|
||||
public function senders()
|
||||
{
|
||||
return $this->hasMany(ShopSender::class, 'shop_ship_id');
|
||||
}
|
||||
}
|
||||
13
app/Models/Waybill.php
Normal file
13
app/Models/Waybill.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Waybill extends Model
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
public static $BUSINESS_EXPRESS_CODE = 247;
|
||||
public static $AIR_FREIGHT_CODE = 266;
|
||||
}
|
||||
@ -3,14 +3,19 @@
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Events\BusinessOrdersUpdate;
|
||||
use App\Events\GroupSetEvent;
|
||||
use App\Events\StockUpdateEvent;
|
||||
use App\Events\GroupSetEvent;
|
||||
use App\Events\BatchStockUpdateEvent;
|
||||
use App\Listeners\BatchStockUpdateListener;
|
||||
use App\Listeners\CreateLogisticListener;
|
||||
use App\Listeners\GroupQueryListener;
|
||||
use App\Listeners\StockUpdateListener;
|
||||
use App\Listeners\StockWarning;
|
||||
use App\Listeners\CombinationGoodsStockUpdateListener;
|
||||
use App\Listeners\UpdateBusinessGoodsStock;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
use App\Events\BusinessOrderCancelEvent;
|
||||
use App\Listeners\CancelLogisticListener;
|
||||
use App\Events\CreateLogisticEvent;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
@ -22,17 +27,25 @@ class EventServiceProvider extends ServiceProvider
|
||||
protected $listen = [
|
||||
BusinessOrdersUpdate::class => [
|
||||
UpdateBusinessGoodsStock::class,
|
||||
StockWarning::class,
|
||||
CombinationGoodsStockUpdateListener::class,
|
||||
],
|
||||
BatchStockUpdateEvent::class => [
|
||||
BatchStockUpdateListener::class,
|
||||
CombinationGoodsStockUpdateListener::class,
|
||||
],
|
||||
StockUpdateEvent::class => [
|
||||
StockUpdateListener::class,
|
||||
StockWarning::class,
|
||||
CombinationGoodsStockUpdateListener::class,
|
||||
],
|
||||
GroupSetEvent::class => [
|
||||
GroupQueryListener::class,
|
||||
],
|
||||
BusinessOrderCancelEvent::class => [
|
||||
CancelLogisticListener::class
|
||||
],
|
||||
CreateLogisticEvent::class => [
|
||||
CreateLogisticListener::class
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Services\Business;
|
||||
|
||||
use App\Events\BusinessOrderCancelEvent;
|
||||
use App\Events\BusinessOrdersUpdate;
|
||||
use App\Models\BusinessGoodsSku;
|
||||
use App\Models\BusinessOrder;
|
||||
@ -29,6 +30,10 @@ abstract class BusinessClient
|
||||
|
||||
abstract public function bindGoods($goods);
|
||||
|
||||
abstract public function createLogistic($orderSn, $waybillNo);
|
||||
|
||||
abstract public function cancelLogistic($orderSn, $waybillNo);
|
||||
|
||||
abstract public function incrQuantity($businessGoodsSku, $num, $incremental);
|
||||
|
||||
abstract public function downloadOrdersAndSave($beginTime, $endTime, $downloadType = 'default', $page = 1);
|
||||
@ -45,9 +50,23 @@ abstract class BusinessClient
|
||||
} else {
|
||||
$orderRecord->update($order);
|
||||
}
|
||||
if (!empty($order['cancel_status'])) {
|
||||
event(new BusinessOrderCancelEvent($shopId, $order['order_sn']));
|
||||
}
|
||||
$goodsSkuNum = 0;
|
||||
foreach ($order['sub_order_list'] as $item) {
|
||||
$item['shop_id'] = $shopId;
|
||||
$orderItem = BusinessOrderItem::firstOrNew(['shop_id' => $shopId, 'business_order_id' => $orderRecord->id, 'goods_id' => $item['goods_id'], 'sku_id' => $item['sku_id']], $item);
|
||||
if ($item['external_sku_id']) {
|
||||
$goodsSku = GoodsSku::query()
|
||||
->with('combinationGoods')
|
||||
->where('external_sku_id', $item['external_sku_id'])
|
||||
->first('external_sku_id');
|
||||
$combinationNum = $goodsSku ? ($goodsSku->combinationGoods->count() ?: 1) : 1;
|
||||
$goodsSkuNum += $combinationNum;
|
||||
} else {
|
||||
$goodsSkuNum++;
|
||||
}
|
||||
$num = 0;
|
||||
$cancelNum = $item['already_cancel_number'] ?? 0;
|
||||
if (empty($orderItem->id)) {
|
||||
@ -78,13 +97,15 @@ abstract class BusinessClient
|
||||
event(new BusinessOrdersUpdate($orderItem, $num));
|
||||
}
|
||||
}
|
||||
$orderRecord->goods_sku_num = $goodsSkuNum;
|
||||
$orderRecord->save();
|
||||
}
|
||||
}
|
||||
|
||||
public function authCallback($code, $shopId)
|
||||
public function authCallback($code, $shop)
|
||||
{
|
||||
$this->setCode($code);
|
||||
$this->setShop($shopId);
|
||||
$this->setShop($shop);
|
||||
$this->auth();
|
||||
|
||||
return $this;
|
||||
@ -97,7 +118,7 @@ abstract class BusinessClient
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setShop(Shop $shop)
|
||||
public function setShop($shop)
|
||||
{
|
||||
$this->shop = $shop;
|
||||
|
||||
@ -121,18 +142,6 @@ abstract class BusinessClient
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
public function setSkuId($skuId)
|
||||
{
|
||||
$this->skuId = $skuId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSkuId()
|
||||
{
|
||||
return $this->skuId;
|
||||
}
|
||||
|
||||
public function formDataPostRequest($url, $params)
|
||||
{
|
||||
$method = 'POST';
|
||||
@ -143,6 +152,10 @@ abstract class BusinessClient
|
||||
$res = (new Client())->request($method, $url, $headers);
|
||||
$size = $res->getBody()->getSize();
|
||||
$res = json_decode($res->getBody()->getContents(), true);
|
||||
$paramsJson = json_encode($params, 256);
|
||||
if (strlen($paramsJson) > 1024) {
|
||||
$paramsJson = '';
|
||||
}
|
||||
if (!in_array($params['type'], ['pdd.ktt.increment.order.query', 'pdd.ktt.order.list'], true)) {
|
||||
$log = new Log();
|
||||
$log->module = 'plat';
|
||||
@ -152,14 +165,14 @@ abstract class BusinessClient
|
||||
$log->target_field = $params['type'];
|
||||
$log->user_id = Auth::id() ?? 999;
|
||||
if ($size < 48000) {
|
||||
$log->message = json_encode($res, 256) . '=====' . json_encode($params, 256);
|
||||
$log->message = json_encode($res, 256) . '=====' . $paramsJson;
|
||||
} else {
|
||||
$log->message = json_encode($params, 256);
|
||||
$log->message = $paramsJson;
|
||||
}
|
||||
$log->save();
|
||||
}
|
||||
if (in_array($params['type'], ['pdd.ktt.increment.order.query', 'pdd.ktt.order.list'], true)) {
|
||||
LogFile::info('快团团请求: ' . json_encode($params, 256));
|
||||
LogFile::info('快团团请求: ' . $paramsJson);
|
||||
LogFile::info('快团团返回: ' . json_encode($res, 256));
|
||||
}
|
||||
|
||||
@ -177,6 +190,8 @@ abstract class BusinessClient
|
||||
];
|
||||
$promises[] = $client->postAsync($url, $options);
|
||||
}
|
||||
Promise\Utils::unwrap($promises);
|
||||
if ($promises) {
|
||||
Promise\Utils::unwrap($promises);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,6 +15,10 @@ class BusinessFactory
|
||||
$this->platList['妙选'] = MiaoXuan::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $platName
|
||||
* @return BusinessClient
|
||||
*/
|
||||
public function make($platName)
|
||||
{
|
||||
return new $this->platList[$platName];
|
||||
|
||||
@ -4,6 +4,21 @@ namespace App\Services\Business\KuaiTuanTuan;
|
||||
|
||||
class FaceSheet extends KuaiTuanTuan
|
||||
{
|
||||
protected $clientId = '24f25877aca447c5830a6aa896301d5e';
|
||||
protected $clientSecret = '59b6f4bd402c6423878a8f4ef1bde28359c1f05a';
|
||||
protected $redirectUri = 'http://erp.chutang66.com/pdd/ship';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function getAuthUrl($shopId, $platId)
|
||||
{
|
||||
$state = $shopId . '_' . $platId;
|
||||
|
||||
return "https://wb.pinduoduo.com/logistics/auth?client_id={$this->clientId}&redirect_uri={$this->redirectUri}&state={$state}";
|
||||
}
|
||||
|
||||
/**
|
||||
* 快递公司查看接口
|
||||
*
|
||||
@ -17,6 +32,21 @@ class FaceSheet extends KuaiTuanTuan
|
||||
return $this->doRequest($type, $appendParams);
|
||||
}
|
||||
|
||||
public function getWayBill($sender, $orderInfo, $wpCode)
|
||||
{
|
||||
$type = 'pdd.waybill.get';
|
||||
$appendParams = [
|
||||
'param_waybill_cloud_print_apply_new_request' => [
|
||||
'sender' => $sender,
|
||||
'trade_order_info_dtos' => [$orderInfo],
|
||||
'wp_code' => $wpCode,
|
||||
]
|
||||
];
|
||||
$appendParams['param_waybill_cloud_print_apply_new_request'] = json_encode($appendParams['param_waybill_cloud_print_apply_new_request'], 256);
|
||||
|
||||
return $this->doRequest($type, $appendParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* searchWayBill
|
||||
*
|
||||
@ -38,10 +68,33 @@ class FaceSheet extends KuaiTuanTuan
|
||||
return $this->doRequest($type, $appendParams);
|
||||
}
|
||||
|
||||
public function test()
|
||||
public function getStdTemplates()
|
||||
{
|
||||
$type = 'pdd.cloudprint.stdtemplates.get';
|
||||
$appendParams = [];
|
||||
$appendParams = [
|
||||
'wp_code' => 'SF'
|
||||
];
|
||||
|
||||
return $this->doRequest($type, $appendParams);
|
||||
}
|
||||
|
||||
public function getCustomares($templateId = 118)
|
||||
{
|
||||
$type = 'pdd.cloudprint.customares.get';
|
||||
$appendParams = [
|
||||
'template_id' => $templateId
|
||||
];
|
||||
|
||||
return $this->doRequest($type, $appendParams);
|
||||
}
|
||||
|
||||
public function cancel($waybillCode, $wpCode)
|
||||
{
|
||||
$type = 'pdd.cloudprint.customares.get';
|
||||
$appendParams = [
|
||||
'waybill_code' => $waybillCode,
|
||||
'wp_code' => $wpCode,
|
||||
];
|
||||
|
||||
return $this->doRequest($type, $appendParams);
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@ namespace App\Services\Business\KuaiTuanTuan;
|
||||
use App\Models\BusinessGoodsSku;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Models\GroupGoods;
|
||||
use App\Models\Shop;
|
||||
use App\Models\ShopShip;
|
||||
use App\Services\Business\BusinessClient;
|
||||
use App\Models\Groups as GroupsModel;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@ -29,13 +31,22 @@ class KuaiTuanTuan extends BusinessClient
|
||||
'sign' => ''
|
||||
];
|
||||
|
||||
public function auth()
|
||||
public function auth($type = 'ktt', $shipType = 'normal')
|
||||
{
|
||||
$accessToken = $this->getAccessTokenWithCode();
|
||||
$accessToken['scope'] = json_encode($accessToken['scope'], 256);
|
||||
$accessToken['pop_auth_token_create_response'] = json_encode($accessToken, 256);
|
||||
$accessToken['status'] = 1;
|
||||
$this->shop->update($accessToken);
|
||||
$accessToken['status'] = Shop::$STATUS_AUTHORIZED;
|
||||
if ('ktt' === $type) {
|
||||
$accessToken['pop_auth_token_create_response'] = json_encode($accessToken, 256);
|
||||
$this->shop->update($accessToken);
|
||||
}
|
||||
if ('ship' === $type) {
|
||||
unset($accessToken['r1_expires_at'], $accessToken['r1_expires_in'], $accessToken['r2_expires_at'], $accessToken['r2_expires_in'], $accessToken['w1_expires_at'], $accessToken['w1_expires_in'], $accessToken['w2_expires_at'], $accessToken['w2_expires_in'], $accessToken['request_id']);
|
||||
$this->shop = ShopShip::query()->updateOrCreate(
|
||||
['shop_id' => $this->shop->id, 'type' => $shipType],
|
||||
$accessToken
|
||||
);
|
||||
}
|
||||
|
||||
return $this->shop;
|
||||
}
|
||||
@ -66,8 +77,10 @@ class KuaiTuanTuan extends BusinessClient
|
||||
public function batchIncrQuantity($businessGoodsSkus, $num, $incremental)
|
||||
{
|
||||
$batchAppendParams = [];
|
||||
$logData = [];
|
||||
foreach ($businessGoodsSkus as $businessGoodsSku) {
|
||||
[$type, $appendParams] = Goods::incrQuantity($businessGoodsSku['goods_id'], $businessGoodsSku['sku_id'], $num, $incremental ? 1 : 2);
|
||||
$logData[] = $appendParams;
|
||||
$appendParams['type'] = $type;
|
||||
$appendParams['client_id'] = $this->clientId;
|
||||
$appendParams['timestamp'] = time();
|
||||
@ -76,6 +89,9 @@ class KuaiTuanTuan extends BusinessClient
|
||||
$batchAppendParams[] = $appendParams;
|
||||
}
|
||||
$this->batchAsyncPostRequest('https://gw-api.pinduoduo.com/api/router', $batchAppendParams);
|
||||
if ($logData) {
|
||||
Log::info('本次批量同步: ' . json_encode($logData, 256));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,7 +169,7 @@ class KuaiTuanTuan extends BusinessClient
|
||||
if (50001 == $res['error_response']['error_code'] && in_array($res['error_response']['sub_code'], ['13', '11'])) {
|
||||
BusinessGoodsSku::query()->where('goods_id', $appendParams['goods_id'])->where('sku_id', $appendParams['sku_id'])->update(['is_sync' => 0]);
|
||||
}
|
||||
Log::error(json_encode($res, 256));
|
||||
Log::error(json_encode($res, 256) . $type);
|
||||
}
|
||||
|
||||
return $res;
|
||||
@ -251,4 +267,25 @@ class KuaiTuanTuan extends BusinessClient
|
||||
|
||||
return $this->doRequest($type, $appendParams);
|
||||
}
|
||||
|
||||
public function createLogistic($orderSn, $waybillNo)
|
||||
{
|
||||
[$type, $appendParams] = Order::createOrderLogistic($orderSn, $waybillNo);
|
||||
|
||||
return $this->doRequest($type, $appendParams);
|
||||
}
|
||||
|
||||
public function cancelLogistic($orderSn, $waybillNo)
|
||||
{
|
||||
[$type, $appendParams] = Order::deleteOrderLogistic($orderSn, $waybillNo);
|
||||
|
||||
return $this->doRequest($type, $appendParams);
|
||||
}
|
||||
|
||||
public function getLogisticsCompanies()
|
||||
{
|
||||
[$type, $appendParams] = Order::getLogisticsCompanies();
|
||||
|
||||
return $this->doRequest($type, $appendParams);
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,5 +57,40 @@ class Order
|
||||
|
||||
return [$type, $appendParams];
|
||||
}
|
||||
|
||||
public static function getLogisticsCompanies()
|
||||
{
|
||||
$type = 'pdd.logistics.companies.get';
|
||||
|
||||
return [$type, []];
|
||||
}
|
||||
|
||||
|
||||
public static function createOrderLogistic($orderSn, $waybillNo, $logisticsId = 44, $logisticsName = '顺丰快递')
|
||||
{
|
||||
// 不支持拆单发货
|
||||
$type = 'pdd.ktt.order.logistic.create';
|
||||
$appendParams = [
|
||||
'logisticsId' => $logisticsId,
|
||||
'logisticsName' => $logisticsName,
|
||||
'orderSn' => $orderSn,
|
||||
// 'subOrderSnList' => [], 发货子单号列表,无子单号视为整单发货
|
||||
'waybillNo' => $waybillNo,
|
||||
];
|
||||
|
||||
return [$type, $appendParams];
|
||||
}
|
||||
|
||||
public static function deleteOrderLogistic($orderSn, $waybillNo)
|
||||
{
|
||||
$type = 'pdd.ktt.order.logistic.delete';
|
||||
$appendParams = [
|
||||
'orderSn' => $orderSn,
|
||||
// 'subOrderSnList' => [], 发货子单号列表,无子单号视为整单发货
|
||||
'waybillNo' => $waybillNo,
|
||||
];
|
||||
|
||||
return [$type, $appendParams];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -47,4 +47,14 @@ class MiaoXuan extends BusinessClient
|
||||
{
|
||||
// TODO: Implement downloadGoods() method.
|
||||
}
|
||||
|
||||
public function createLogistic($orderSn, $waybillNo)
|
||||
{
|
||||
// TODO: Implement createLogistic() method.
|
||||
}
|
||||
|
||||
public function cancelLogistic($orderSn, $waybillNo)
|
||||
{
|
||||
// TODO: Implement cancelLogistic() method.
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\PrintModule\Pdd;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Log as LogFile;
|
||||
|
||||
class Ktt
|
||||
{
|
||||
protected $clientId = '24f25877aca447c5830a6aa896301d5e';
|
||||
protected $clientSecret = '59b6f4bd402c6423878a8f4ef1bde28359c1f05a';
|
||||
protected $callBackUrl = 'http://erp.chutang66.com/pdd/ship';
|
||||
|
||||
public function auth($code)
|
||||
{
|
||||
$accessToken = $this->getAccessTokenWithCode($code);
|
||||
LogFile::info('电子面单应用授权: ' . json_encode($accessToken, 256));
|
||||
}
|
||||
|
||||
protected function getAccessTokenWithCode($code)
|
||||
{
|
||||
$type = 'pdd.pop.auth.token.create';
|
||||
$res = $this->doRequest($type, ['code' => $code]);
|
||||
|
||||
return $res['pop_auth_token_create_response'];
|
||||
}
|
||||
|
||||
public function doRequest($type, $appendParams = [], $url = 'https://gw-api.pinduoduo.com/api/router')
|
||||
{
|
||||
$publicParams = [
|
||||
'type' => $type,
|
||||
'client_id' => $this->clientId,
|
||||
'timestamp' => time()
|
||||
];
|
||||
$publicParams = array_merge($publicParams, $appendParams);
|
||||
$publicParams['sign'] = $this->getSign($publicParams);
|
||||
|
||||
return $this->formDataPostRequest($url, $publicParams);
|
||||
}
|
||||
|
||||
protected function getSign($params)
|
||||
{
|
||||
ksort($params);
|
||||
$str = '';
|
||||
foreach ($params as $key => $val) {
|
||||
$str .= $key . $val;
|
||||
}
|
||||
$str = $this->clientSecret . $str . $this->clientSecret;
|
||||
|
||||
return strtoupper(md5($str));
|
||||
}
|
||||
|
||||
protected function formDataPostRequest($url, $params)
|
||||
{
|
||||
$method = 'POST';
|
||||
$headers = [
|
||||
'headers' => ['Content-type' => 'application/x-www-form-urlencoded;charset=UTF-8'],
|
||||
'form_params' => $params
|
||||
];
|
||||
$res = (new Client())->request($method, $url, $headers);
|
||||
return json_decode($res->getBody()->getContents(), true);
|
||||
}
|
||||
}
|
||||
356
app/Services/Ship/WayBillService.php
Normal file
356
app/Services/Ship/WayBillService.php
Normal file
@ -0,0 +1,356 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Ship;
|
||||
|
||||
use App\Events\CreateLogisticEvent;
|
||||
use App\Models\GoodsSku;
|
||||
use App\Models\ShopShip;
|
||||
use App\Models\Waybill;
|
||||
use App\Services\Business\KuaiTuanTuan\FaceSheet;
|
||||
|
||||
class WayBillService
|
||||
{
|
||||
public $orders;
|
||||
public $objectId;
|
||||
// 快递便携式一联单
|
||||
public $sfOne = 'https://file-link.pinduoduo.com/sf_one';
|
||||
public $sfOneTemplate = 'sf_one1688973997895.xml';
|
||||
// 快递三联面单
|
||||
public $sfThree = 'https://file-link.pinduoduo.com/sf_three';
|
||||
public $sfThreeTemplate = 'sf_three1677381064344.xml';
|
||||
// 标准模板
|
||||
public $sfStd = 'https://file-link.pinduoduo.com/sf_std';
|
||||
public $sfStdTemplate = 'sf_std1677380804913.xml';
|
||||
// 时效类型
|
||||
public $timedDeliveryCode;
|
||||
|
||||
public function getContents()
|
||||
{
|
||||
// 已下单过的订单不再下单
|
||||
$contents = [];
|
||||
foreach ($this->orders as $shopId => $order) {
|
||||
// 订单取消的情况暂不处理
|
||||
$shopShip = $this->getShopShip($shopId);
|
||||
$faceSheet = new FaceSheet();
|
||||
$faceSheet->setShop($shopShip);
|
||||
foreach ($order as $item) {
|
||||
[$sender, $orderInfo, $senderConfig] = $this->prepareRequest($item, $shopShip);
|
||||
$waybill = $this->saveWayBill($item, $shopShip, $senderConfig);
|
||||
|
||||
if (empty($waybill->id)) {
|
||||
$resp = $faceSheet->getWayBill($sender, $orderInfo, $senderConfig['wp_code']);
|
||||
if (isset($resp['pdd_waybill_get_response'])) {
|
||||
$data = $resp['pdd_waybill_get_response']['modules'][0];
|
||||
$printData = json_decode($data['print_data'], true);
|
||||
$waybill->request_id = $resp['pdd_waybill_get_response']['request_id'];
|
||||
$waybill->encryptedData = $printData['encryptedData'];
|
||||
$waybill->signature = $printData['signature'];
|
||||
$waybill->templateUrl = $printData['templateUrl'];
|
||||
$waybill->ver = $printData['ver'];
|
||||
$waybill->waybill_code = $data['waybill_code'];
|
||||
$waybill->save();
|
||||
// 返回待打印内容
|
||||
$contents[$waybill->id] = [
|
||||
'addData' => [
|
||||
'sender' => $sender,
|
||||
],
|
||||
'encryptedData' => $printData['encryptedData'],
|
||||
'signature' => $printData['signature'],
|
||||
'templateUrl' => env('APP_URL') . '/ktt/' . $this->sfOneTemplate, // 电子面单模板
|
||||
'ver' => $printData['ver'],
|
||||
'userid' => $waybill->user_id,
|
||||
'items' => $item['items'],
|
||||
'documentID' => $waybill->id,
|
||||
'order_id' => $item['id'],
|
||||
'participate_no' => $waybill->participate_no,
|
||||
'note' => $waybill->note,
|
||||
];
|
||||
event(new CreateLogisticEvent($shopShip->shop_id, $waybill->order_sn, $data['waybill_code']));
|
||||
}
|
||||
} else {
|
||||
$contents[$waybill->id] = [
|
||||
'addData' => [
|
||||
'sender' => $sender,
|
||||
],
|
||||
'encryptedData' => $waybill->encryptedData,
|
||||
'signature' => $waybill->signature,
|
||||
'templateUrl' => env('APP_URL') . '/ktt/' . $this->sfOneTemplate, // 电子面单模板
|
||||
'ver' => $waybill->ver,
|
||||
'userid' => $waybill->user_id,
|
||||
'items' => json_decode($waybill->items, true),
|
||||
'documentID' => $waybill->id,
|
||||
'order_id' => $item['id'],
|
||||
'participate_no' => $waybill->participate_no,
|
||||
'note' => $waybill->note,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $contents;
|
||||
}
|
||||
|
||||
public function getDocumentsAndOrderIds($contents)
|
||||
{
|
||||
// 打印单,根据商品排序
|
||||
$items = [];
|
||||
foreach ($contents as $docId => $content) {
|
||||
foreach ($content['items'] as $item) {
|
||||
if ($item['is_single']) {
|
||||
$items[$item['external_sku_id']][] = $docId;
|
||||
}
|
||||
}
|
||||
}
|
||||
ksort($items);
|
||||
$documents = $orderIds = $hasIds = [];
|
||||
foreach ($items as $docIds) {
|
||||
$docIds = array_unique($docIds);
|
||||
$docIds = array_diff($docIds, $hasIds);
|
||||
$hasIds = array_merge($hasIds, $docIds);
|
||||
foreach ($docIds as $docId) {
|
||||
$orderIds[] = $contents[$docId]['order_id'];
|
||||
$documents[] = $contents[$docId];
|
||||
}
|
||||
}
|
||||
|
||||
return [$documents, $orderIds];
|
||||
}
|
||||
|
||||
private function saveWayBill($order, $shopShip, $senderConfig)
|
||||
{
|
||||
$waybill = Waybill::query()->firstOrNew(
|
||||
['order_sn' => $order['order_sn']]
|
||||
);
|
||||
|
||||
$waybill->shop_id = $shopShip->shop_id;
|
||||
$waybill->object_id = $this->objectId;
|
||||
|
||||
$waybill->sender_country = $senderConfig['country'];
|
||||
$waybill->sender_province = $senderConfig['province'];
|
||||
$waybill->sender_city = $senderConfig['city'];
|
||||
$waybill->sender_district = $senderConfig['district'];
|
||||
$waybill->sender_detail = $senderConfig['detail'];
|
||||
$waybill->sender_name = $senderConfig['name'];
|
||||
$waybill->sender_mobile = $senderConfig['mobile'];
|
||||
|
||||
$waybill->recipient_province = $order['recipient_province'];
|
||||
$waybill->recipient_city = $order['recipient_city'];
|
||||
$waybill->recipient_district = $order['recipient_district'];
|
||||
$waybill->recipient_detail = $order['recipient_detail'];
|
||||
$waybill->recipient_name = $order['recipient_name'];
|
||||
$waybill->recipient_mobile = $order['recipient_mobile'];
|
||||
|
||||
$waybill->user_id = $shopShip->owner_id;
|
||||
$waybill->wp_code = $senderConfig['wp_code'];
|
||||
$waybill->order_sn = $order['order_sn'];
|
||||
$waybill->order_id = $order['id'];
|
||||
$waybill->participate_no = $order['participate_no'];
|
||||
$waybill->note = $order['note'];
|
||||
$waybill->items = json_encode($order['items'], 256);
|
||||
|
||||
return $waybill;
|
||||
}
|
||||
|
||||
private function getTimedDelivery($order)
|
||||
{
|
||||
$this->timedDeliveryCode = Waybill::$BUSINESS_EXPRESS_CODE;
|
||||
$address = [
|
||||
'辽宁省' => [],
|
||||
'吉林省' => [],
|
||||
'黑龙江省' => [],
|
||||
'甘肃省' => [],
|
||||
'海南省' => [],
|
||||
'宁夏回族自治区' => [
|
||||
'银川市', '石嘴山市', '吴忠市', '固原市'
|
||||
],
|
||||
'青海省' => [
|
||||
'西宁市', '海东市', '海北藏族自治州', '黄南藏族自治州', '海南藏族自治州', '玉树藏族自治州'
|
||||
],
|
||||
];
|
||||
if (isset($address[$order['recipient_province']])) {
|
||||
if (empty($address[$order['recipient_province']])) {
|
||||
$this->timedDeliveryCode = Waybill::$AIR_FREIGHT_CODE;
|
||||
}
|
||||
if ($address[$order['recipient_province']] && in_array($order['recipient_city'], $address[$order['recipient_province']], true)) {
|
||||
$this->timedDeliveryCode = Waybill::$AIR_FREIGHT_CODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function prepareRequest($order, $shopShip)
|
||||
{
|
||||
$this->getTimedDelivery($order);
|
||||
|
||||
$this->setObjectId();
|
||||
|
||||
$items = [];
|
||||
foreach ($order['items'] as $item) {
|
||||
if ($item['should_print']) {
|
||||
// 使用规格编码后删除,此处暂时使用空运名字判断兼容
|
||||
if (false !== strpos($item['name'], '空运')) {
|
||||
$this->timedDeliveryCode = Waybill::$AIR_FREIGHT_CODE;
|
||||
}
|
||||
|
||||
$items[] = [
|
||||
'name' => $item['name'],
|
||||
'count' => $item['count'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$senderConfig = [];
|
||||
foreach ($shopShip->senders as $sender) {
|
||||
if ($sender['timed_delivery_code'] === $this->timedDeliveryCode) {
|
||||
$senderConfig = $sender;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($senderConfig)) {
|
||||
abort(404, '发货人信息未匹配');
|
||||
}
|
||||
$sender = [
|
||||
'address' => [
|
||||
'city' => $senderConfig['city'],
|
||||
'country' => $senderConfig['country'],
|
||||
'detail' => $senderConfig['detail'],
|
||||
'district' => $senderConfig['district'],
|
||||
'province' => $senderConfig['province'],
|
||||
],
|
||||
'name' => $senderConfig['name'],
|
||||
'mobile' => $senderConfig['mobile'],
|
||||
];
|
||||
|
||||
$orderInfo = [
|
||||
'logistics_services' => [
|
||||
'TIMED-DELIVERY' => [
|
||||
'value' => $this->timedDeliveryCode
|
||||
],
|
||||
],
|
||||
'object_id' => $this->objectId,
|
||||
'order_info' => [
|
||||
'order_channels_type' => 'PDD',
|
||||
'trade_order_list' => [$order['order_sn']],
|
||||
],
|
||||
'package_info' => [
|
||||
'items' => $items,
|
||||
],
|
||||
'recipient' => [
|
||||
'address' => [
|
||||
'city' => $order['recipient_city'],
|
||||
'detail' => $order['recipient_detail'],
|
||||
'district' => $order['recipient_district'],
|
||||
'province' => $order['recipient_province'],
|
||||
],
|
||||
'name' => $order['recipient_name'],
|
||||
'mobile' => $order['recipient_mobile'],
|
||||
],
|
||||
'template_url' => $this->sfOne,
|
||||
'user_id' => $shopShip->owner_id,
|
||||
];
|
||||
|
||||
return [$sender, $orderInfo, $senderConfig];
|
||||
}
|
||||
|
||||
public function setObjectId()
|
||||
{
|
||||
$this->objectId = date('YmdHis') . str_pad(mt_rand(1, 9999999), 7, '0', STR_PAD_LEFT);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setOrders($orders)
|
||||
{
|
||||
$orders = $orders->toArray();
|
||||
// 取出所有组合商品编码
|
||||
$combinationExternalIds = [];
|
||||
foreach ($orders as $order) {
|
||||
foreach ($order['items'] as $item) {
|
||||
if (false !== strpos($item['external_sku_id'], 'Z')) {
|
||||
$combinationExternalIds[] = $item['external_sku_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
// 获取组合商品详情
|
||||
$combinations = [];
|
||||
if ($combinationExternalIds) {
|
||||
$goodsSkus = GoodsSku::query()
|
||||
->select(['id', 'external_sku_id'])
|
||||
->with([
|
||||
'combinationGoods:id,goods_sku_id,item_id,item_num',
|
||||
'combinationGoods.goodsSkuItem:id,external_sku_id',
|
||||
])
|
||||
->whereIn('external_sku_id', $combinationExternalIds)
|
||||
->get()
|
||||
->toArray();
|
||||
foreach ($goodsSkus as $goodsSku) {
|
||||
foreach ($goodsSku['combination_goods'] as $item) {
|
||||
$combinations[$goodsSku['external_sku_id']][] = [
|
||||
'count' => $item['item_num'],
|
||||
'external_sku_id' => $item['goods_sku_item']['external_sku_id'],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
// 订单拆分组合
|
||||
foreach ($orders as $order) {
|
||||
$info = [
|
||||
'id' => $order['id'],
|
||||
'order_sn' => $order['order_sn'],
|
||||
'recipient_province' => $order['receiver_address_province'],
|
||||
'recipient_city' => $order['receiver_address_city'],
|
||||
'recipient_district' => $order['receiver_address_district'],
|
||||
'recipient_detail' => $order['receiver_address_detail'],
|
||||
'recipient_name' => $order['receiver_name'],
|
||||
'recipient_mobile' => $order['receiver_mobile'],
|
||||
'participate_no' => $order['is_supplier'] ? $order['participate_no'] : $order['supply_participate_no'],
|
||||
'note' => $order['business_note'] ? $order['business_note'] . ',' . $order['buyer_memo'] : $order['buyer_memo'],
|
||||
'items' => []
|
||||
];
|
||||
foreach ($order['items'] as $item) {
|
||||
$count = $item['goods_number'] - $item['already_cancel_number'];
|
||||
if (isset($combinations[$item['external_sku_id']])) {
|
||||
$info['items'][] = [
|
||||
'is_single' => false,
|
||||
'should_print' => true,
|
||||
'name' => $item['goods_name'],
|
||||
'count' => $count,
|
||||
'external_sku_id' => $item['external_sku_id'],
|
||||
];
|
||||
foreach ($combinations[$item['external_sku_id']] as $combinationItem) {
|
||||
$info['items'][] = [
|
||||
'is_single' => true,
|
||||
'should_print' => false,
|
||||
'count' => $count * $combinationItem['count'],
|
||||
'external_sku_id' => $combinationItem['external_sku_id'],
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$info['items'][] = [
|
||||
'is_single' => true,
|
||||
'should_print' => true,
|
||||
'name' => $item['goods_name'],
|
||||
'count' => $count,
|
||||
'external_sku_id' => $item['external_sku_id'],
|
||||
];
|
||||
}
|
||||
}
|
||||
$this->orders[$order['shop_id']][] = $info;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function getShopShip($shopId)
|
||||
{
|
||||
return ShopShip::query()
|
||||
->select(['id', 'shop_id', 'access_token', 'owner_id'])
|
||||
->where('shop_id', $shopId)
|
||||
->with([
|
||||
'senders' => function ($query) {
|
||||
$query->where('status', 1)->orderBy('sort');
|
||||
}
|
||||
])
|
||||
->first();
|
||||
}
|
||||
}
|
||||
@ -33,4 +33,9 @@ class FormatUtils
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function getPercent($dividend, $divisor, $decimal = 2)
|
||||
{
|
||||
return bcdiv($dividend, $divisor, $decimal + 2) * 100 . '%';
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'name' => env('APP_NAME', 'CFen Erp'),
|
||||
'name' => env('APP_NAME', 'chunfen_erp'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@ -131,7 +131,7 @@ return [
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'password' => env('REDIS_PASSWORD', null),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'database' => env('REDIS_DB', '0'),
|
||||
'database' => env('REDIS_DB', '10'),
|
||||
],
|
||||
|
||||
'cache' => [
|
||||
@ -139,7 +139,7 @@ return [
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'password' => env('REDIS_PASSWORD', null),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'database' => env('REDIS_CACHE_DB', '1'),
|
||||
'database' => env('REDIS_CACHE_DB', '11'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
@ -24,7 +24,7 @@ class CreateBusinessOrdersTable extends Migration
|
||||
$table->bigInteger('after_sales_status')->nullable();
|
||||
$table->string('business_note')->nullable();
|
||||
$table->string('buyer_memo')->nullable();
|
||||
$table->integer('cancel_status')->nullable();
|
||||
$table->integer('cancel_status')->default(0)->nullable();
|
||||
$table->bigInteger('confirm_at')->nullable();
|
||||
$table->bigInteger('discount_amount')->nullable();
|
||||
$table->string('help_sell_nickname')->nullable();
|
||||
@ -51,7 +51,7 @@ class CreateBusinessOrdersTable extends Migration
|
||||
$table->string('self_pick_up_site_name')->nullable();
|
||||
$table->bigInteger('service_amount')->nullable();
|
||||
$table->bigInteger('shipping_amount')->nullable();
|
||||
$table->integer('shipping_status')->nullable();
|
||||
$table->integer('shipping_status')->default(0)->nullable();
|
||||
$table->string('supply_activity_no')->nullable();
|
||||
$table->integer('supply_participate_no')->nullable();
|
||||
$table->bigInteger('theoretical_refund_amount')->nullable();
|
||||
|
||||
@ -21,7 +21,7 @@ class CreateBusinessOrderItemsTable extends Migration
|
||||
$table->bigInteger('shop_id');
|
||||
$table->bigInteger('business_order_id');
|
||||
$table->integer('already_cancel_number')->nullable();
|
||||
$table->integer('cancel_status')->nullable();
|
||||
$table->integer('cancel_status')->default(0)->nullable();
|
||||
$table->string('category_name')->nullable();
|
||||
$table->string('external_sku_id')->nullable();
|
||||
$table->bigInteger('goods_amount')->nullable();
|
||||
@ -35,7 +35,7 @@ class CreateBusinessOrderItemsTable extends Migration
|
||||
$table->bigInteger('help_sell_amount')->nullable();
|
||||
$table->boolean('is_supplier')->nullable();
|
||||
$table->integer('need_verification_number')->nullable();
|
||||
$table->integer('shipping_status')->nullable();
|
||||
$table->integer('shipping_status')->default(0)->nullable();
|
||||
$table->bigInteger('sku_id')->nullable();
|
||||
$table->string('sub_order_sn')->nullable();
|
||||
$table->bigInteger('theoretically_refund_amount')->nullable();
|
||||
|
||||
@ -28,7 +28,7 @@ class CreateGroupsTable extends Migration
|
||||
$table->string('activity_no')->nullable()->comment('团号');
|
||||
$table->unsignedTinyInteger('create_status')->default(3)->comment('1-创建成功,2-创建失败,3-创建中');
|
||||
$table->string('error_msg')->nullable()->comment('create_status为2时有,创建团失败原因');
|
||||
$table->text('qr_code_url')->nullable()->comment('create_status为1时有,团小程序二维码图片地址');
|
||||
$table->string('qr_code_url')->default('')->comment('create_status为1时有,团小程序二维码图片地址');
|
||||
$table->unsignedBigInteger('create_time')->nullable();
|
||||
$table->unsignedTinyInteger('is_help_sell')->nullable()->comment('是否帮卖0-我发布的,1-我帮卖的');
|
||||
$table->tinyInteger('status')->default(-10)->comment('团状态(-10:待发布/预览中,-5:未开始,1:跟团中,20:已结束,30:已删除');
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateShopShipsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasTable('shop_ships')) {
|
||||
return;
|
||||
}
|
||||
Schema::create('shop_ships', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->integer('shop_id');
|
||||
$table->string('access_token');
|
||||
$table->unsignedBigInteger('expires_at')->comment('access_token过期时间点');
|
||||
$table->unsignedInteger('expires_in')->comment('access_token过期时间段,10(表示10秒后过期)');
|
||||
$table->string('owner_id')->comment('商家店铺id');
|
||||
$table->string('owner_name')->comment('商家账号名称');
|
||||
$table->string('refresh_token')->comment('refresh token,可用来刷新access_token');
|
||||
$table->unsignedBigInteger('refresh_token_expires_at')->comment('Refresh token过期时间点');
|
||||
$table->unsignedInteger('refresh_token_expires_in')->comment('refresh_token过期时间段,10表示10秒后过期');
|
||||
$table->text('scope')->comment('接口列表');
|
||||
$table->tinyInteger('status')->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('shop_ships');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddGoodsSkuNumToBusinessOrdersTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasColumns('business_orders', ['goods_sku_num', 'print_status'])) {
|
||||
return;
|
||||
}
|
||||
Schema::table('business_orders', function (Blueprint $table) {
|
||||
$table->integer('goods_sku_num')->default(0)->comment('订单内不同商品种类数量');
|
||||
$table->tinyInteger('print_status')->default(0)->comment('订单内不同商品种类数量');
|
||||
$table->index('goods_sku_num');
|
||||
$table->index('print_status');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('business_orders', function (Blueprint $table) {
|
||||
$table->dropColumn(['goods_sku_num', 'print_status']);
|
||||
$table->dropIndex('goods_sku_num');
|
||||
$table->dropIndex('print_status');
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateShopSendersTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasTable('shop_senders')) {
|
||||
return;
|
||||
}
|
||||
Schema::create('shop_senders', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->integer('shop_id');
|
||||
$table->integer('shop_ship_id');
|
||||
$table->string('country');
|
||||
$table->string('province');
|
||||
$table->string('city');
|
||||
$table->string('district');
|
||||
$table->string('detail');
|
||||
$table->string('name')->nullable()->default('');
|
||||
$table->string('mobile', 18)->nullable();
|
||||
$table->integer('sort')->default(1);
|
||||
$table->integer('status')->default(1);
|
||||
$table->string('wp_code')->default('');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('shop_senders');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateWaybillsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasTable('waybills')) {
|
||||
return;
|
||||
}
|
||||
Schema::create('waybills', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->integer('shop_id');
|
||||
$table->string('request_id')->default('');
|
||||
$table->text('encryptedData')->nullable();
|
||||
$table->string('signature')->default('');
|
||||
$table->string('templateUrl');
|
||||
$table->string('ver')->default('');
|
||||
$table->string('waybill_code')->default('');
|
||||
$table->string('object_id', 32);
|
||||
$table->integer('key')->default(0);
|
||||
|
||||
$table->string('sender_country');
|
||||
$table->string('sender_province');
|
||||
$table->string('sender_city');
|
||||
$table->string('sender_district');
|
||||
$table->string('sender_detail');
|
||||
$table->string('sender_name');
|
||||
$table->integer('sender_mobile');
|
||||
|
||||
$table->string('recipient_country')->default('');
|
||||
$table->string('recipient_province');
|
||||
$table->string('recipient_city');
|
||||
$table->string('recipient_district');
|
||||
$table->string('recipient_detail');
|
||||
$table->string('recipient_name');
|
||||
$table->string('recipient_mobile', 16);
|
||||
|
||||
$table->string('user_id');
|
||||
$table->string('wp_code');
|
||||
$table->string('order_channels_type')->default('PDD');
|
||||
|
||||
$table->string('order_sn');
|
||||
$table->integer('order_id');
|
||||
$table->integer('participate_no')->default(0);
|
||||
$table->integer('timed_delivery')->default(247);
|
||||
$table->string('note')->nullable();
|
||||
$table->text('items');
|
||||
$table->tinyInteger('cancel')->default(0);
|
||||
|
||||
$table->timestamps();
|
||||
|
||||
$table->index('object_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('waybills');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddTypeToShopShipsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasColumns('shop_ships', ['type'])) {
|
||||
return;
|
||||
}
|
||||
Schema::table('shop_ships', function (Blueprint $table) {
|
||||
$table->string('type')->default('normal')->comment('账户类型normal-普通,air-空运');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('shop_ships', function (Blueprint $table) {
|
||||
$table->dropColumn(['type']);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddCodeToWaybillsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasColumns('waybills', ['code'])) {
|
||||
return;
|
||||
}
|
||||
Schema::table('waybills', function (Blueprint $table) {
|
||||
$table->integer('code')->default(247)->comment('247-电商标快,266-空运');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('waybills', function (Blueprint $table) {
|
||||
$table->dropColumn(['code']);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddTimedDeliveryCodeToShopSendersTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasColumns('shop_senders', ['timed_delivery_code'])) {
|
||||
return;
|
||||
}
|
||||
Schema::table('shop_senders', function (Blueprint $table) {
|
||||
$table->integer('timed_delivery_code')->default(247)->comment('地址类型: 247-电商标快,266-空运');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('shop_senders', function (Blueprint $table) {
|
||||
$table->dropColumn(['timed_delivery_code']);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateDeveloperConfigsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasTable('developer_configs')) {
|
||||
return;
|
||||
}
|
||||
Schema::create('developer_configs', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('key')->comment('配置项名称');
|
||||
$table->string('value')->comment('配置项值');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('developer_configs');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateDailyReportsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasTable('daily_reports')) {
|
||||
return;
|
||||
}
|
||||
Schema::create('daily_reports', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->date('date');
|
||||
$table->unsignedInteger('goods_id');
|
||||
$table->unsignedInteger('type_id');
|
||||
$table->unsignedInteger('brand_id');
|
||||
$table->unsignedInteger('goods_sku_id');
|
||||
$table->string('external_sku_id', 64);
|
||||
$table->unsignedInteger('total_goods_price')->default(0);
|
||||
$table->unsignedInteger('total_goods_cost_price')->default(0);
|
||||
$table->unsignedInteger('total_goods_amount')->default(0);
|
||||
$table->unsignedInteger('total_goods_number')->default(0);
|
||||
$table->unsignedInteger('total_cancel_number')->default(0);
|
||||
$table->unsignedDecimal('cost')->default(0);
|
||||
$table->text('shop_data');
|
||||
|
||||
$table->timestamps();
|
||||
$table->index(['date', 'external_sku_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('week_reports');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddNameToGoodsSkusTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasColumn('goods_skus', 'name')) {
|
||||
return;
|
||||
}
|
||||
Schema::table('goods_skus', function (Blueprint $table) {
|
||||
$table->string('name')->default('')->comment('完整商品名称');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('goods_skus', function (Blueprint $table) {
|
||||
$table->dropColumn('name');
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateDailySalesReportsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasTable('daily_sales_reports')) {
|
||||
return;
|
||||
}
|
||||
Schema::create('daily_sales_reports', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->date('date');
|
||||
$table->unsignedInteger('goods_id');
|
||||
$table->unsignedInteger('goods_sku_id');
|
||||
$table->string('name');
|
||||
$table->string('external_sku_id', 64);
|
||||
$table->integer('inventory')->default(0)->comment('盘点数量');
|
||||
$table->integer('arrived_today_num')->default(0)->comment('今日到货');
|
||||
$table->integer('sales_num')->default(0)->comment('总销量');
|
||||
$table->integer('already_cancel_number')->default(0)->comment('已取消数量');
|
||||
$table->unsignedInteger('loss_num')->default(0)->comment('损耗');
|
||||
$table->decimal('goal_rate', 8, 4)->default(0)->comment('目标去化率');
|
||||
$table->integer('S1')->default(0)->comment('11-12');
|
||||
$table->integer('S2')->default(0)->comment('11-13:30');
|
||||
$table->integer('S3')->default(0)->comment('11-15');
|
||||
$table->integer('S4')->default(0)->comment('15-16');
|
||||
$table->integer('S5')->default(0)->comment('11-17:30');
|
||||
$table->integer('S6')->default(0)->comment('11-20');
|
||||
$table->integer('S7')->default(0)->comment('11-9:30');
|
||||
$table->decimal('S1_rate', 8, 4)->default(0);
|
||||
$table->decimal('S2_rate', 8, 4)->default(0);
|
||||
$table->decimal('S3_rate', 8, 4)->default(0);
|
||||
$table->decimal('S4_rate', 8, 4)->default(0);
|
||||
$table->decimal('S5_rate', 8, 4)->default(0);
|
||||
$table->decimal('S6_rate', 8, 4)->default(0);
|
||||
$table->decimal('S7_rate', 8, 4)->default(0);
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('daily_sales_reports');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddGoalRateToGoodsSkusTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasColumn('goods_skus', 'goal_rate')) {
|
||||
return;
|
||||
}
|
||||
Schema::table('goods_skus', function (Blueprint $table) {
|
||||
$table->decimal('goal_rate', 8, 4)->default(0)->comment('目标去化率');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('goods_skus', function (Blueprint $table) {
|
||||
$table->dropColumn('goal_rate');
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddReissueNumToDailyStockRecordsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasColumn('daily_stock_records', 'reissue_num')) {
|
||||
return;
|
||||
}
|
||||
Schema::table('daily_stock_records', function (Blueprint $table) {
|
||||
$table->unsignedInteger('reissue_num')->default(0)->comment('补发数量');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('daily_stock_records', function (Blueprint $table) {
|
||||
$table->dropColumn('reissue_num');
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -40,8 +40,10 @@ class MenusTableSeeder extends Seeder
|
||||
['parent_id' => $id, 'code' => 'PLAT_GOODS_LIST', 'name' => '货品列表', 'seq' => 0],
|
||||
['parent_id' => $id, 'code' => 'PLAT_ORDER_LIST', 'name' => '订单列表', 'seq' => 1],
|
||||
]);
|
||||
// 团购
|
||||
DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'GROUP_MANAGEMENT', 'name' => '团购管理', 'seq' => 1]);
|
||||
// 团购管理
|
||||
DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'GROUP_MANAGEMENT', 'name' => '团购管理', 'seq' => 2]);
|
||||
// 数据中心
|
||||
DB::table('menus')->insertGetId(['parent_id' => 0, 'code' => 'DATA_CENTER', 'name' => '数据中心', 'seq' => 1]);
|
||||
}
|
||||
|
||||
public function update()
|
||||
@ -49,10 +51,23 @@ class MenusTableSeeder extends Seeder
|
||||
$routes = include(resource_path('lang/zh-CN/permission.php'));
|
||||
foreach ($routes as $code => $route) {
|
||||
if (false === strpos($code, '.')) {
|
||||
DB::table('menus')->updateOrInsert(
|
||||
['id' => $route['id'], 'parent_id' => $route['parent_id'], 'code' => $code],
|
||||
['name' => $route['name'], 'show' => $route['show']]
|
||||
);
|
||||
$menu = DB::table('menus')->where('id', $route['id'])->first();
|
||||
if ($menu) {
|
||||
DB::table('menus')->where('id', $route['id'])->update([
|
||||
'parent_id' => $route['parent_id'],
|
||||
'code' => $code,
|
||||
'name' => $route['name'],
|
||||
'show' => $route['show'],
|
||||
]);
|
||||
} else {
|
||||
DB::table('menus')->insert([
|
||||
'id' => $route['id'],
|
||||
'parent_id' => $route['parent_id'],
|
||||
'code' => $code,
|
||||
'name' => $route['name'],
|
||||
'show' => $route['show']
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
public/dist/css/149.9f84b84a.css
vendored
Normal file
1
public/dist/css/149.9f84b84a.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.aside-show[data-v-c25279e8]{transition:all .3s;opacity:0;width:0!important}.aside-hide[data-v-c25279e8]{transition:all .3s;opacity:1;width:200px!important}.el-container[data-v-c25279e8]{height:100vh}.el-aside[data-v-c25279e8]{background-color:#d3dce6;color:#333;overflow-x:hidden}.el-aside[data-v-c25279e8]::-webkit-scrollbar{width:8px}.el-aside[data-v-c25279e8]::-webkit-scrollbar-thumb{background-color:hsla(220,4%,58%,.3);border-radius:20px}.el-main[data-v-c25279e8]{background-color:#f0f2f5;color:#333;padding:0 0!important}.el-main[data-v-c25279e8]::-webkit-scrollbar{width:10px}.el-main[data-v-c25279e8]::-webkit-scrollbar-thumb{background-color:hsla(220,4%,58%,.3)}.box-card[data-v-c25279e8]{min-height:calc(100vh - 120px);margin:10px}.conent[data-v-c25279e8]{width:100%;min-height:calc(100vh - 200px);position:relative}.add[data-v-c25279e8]{cursor:pointer;font-size:25px;color:#606266}.head[data-v-c25279e8]{padding:10px;background-color:#fff;border-bottom:1px solid #f6f6f6;box-shadow:0 1px 4px rgba(0,21,41,.08)}.head ul[data-v-c25279e8]{display:flex;justify-content:space-between}.head ul li[data-v-c25279e8]{display:flex;align-items:center}.head ul li .right[data-v-c25279e8]{margin-left:20px}.head ul li .token[data-v-c25279e8]{cursor:pointer}.el-aside[data-v-c25279e8]{background:#282c34;box-shadow:2px 0 6px rgba(0,21,41,.35)}[data-v-c25279e8] .el-menu{border:none}.el-menu-item[data-v-c25279e8]:hover{outline:0!important;background:#5470c6!important;border-radius:5px!important}.el-menu-item.is-active[data-v-c25279e8]{color:#fff!important;background:#5470c6!important;border-radius:5px!important}.el-menu-item-group__title[data-v-c25279e8]{padding:0 0!important}
|
||||
@ -1 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
|
||||
@ -1 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}a[data-v-61aedda5]{text-decoration:none;color:#fff}.block[data-v-61aedda5]{margin-top:20px}
|
||||
@ -1 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.block[data-v-679bd5d4]{margin-top:20px}
|
||||
@ -1 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}a[data-v-446dc800]{text-decoration:none;color:#fff}.block[data-v-446dc800]{margin-top:20px}
|
||||
1
public/dist/css/470.4d13bccb.css
vendored
Normal file
1
public/dist/css/470.4d13bccb.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.el-upload--picture-card[data-v-1963f826]{width:50px;height:50px}.el-form-item[data-v-1963f826]{margin-left:40px}.avatar-uploader .el-upload[data-v-1963f826]{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader .el-upload[data-v-1963f826]:hover{border-color:#409eff}.avatar-uploader-icon[data-v-1963f826]{font-size:28px;color:#8c939d;width:148px;height:148px;line-height:148px;text-align:center}.avatar[data-v-1963f826]{width:148px;height:148px;display:block}
|
||||
1
public/dist/css/485.8c529968.css
vendored
Normal file
1
public/dist/css/485.8c529968.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.backimg[data-v-53d3caae]{width:100%;height:1080px;background-image:url(../img/%E7%BB%84%2032.a17892e3.png);background-repeat:no-repeat;background-size:100%;position:relative}.sign[data-v-53d3caae]{width:400px;height:500px;position:absolute;top:270px;right:300px}.sign input[data-v-53d3caae]{width:400px;height:51px;border:2px solid #bcbcbc;opacity:1;border-radius:5px;margin-bottom:25px}.sign .title[data-v-53d3caae]{width:125px;height:23px;font-size:22px;font-family:BigruixianBlackGBV1\.0;font-weight:400;line-height:23px;color:#2b53ec;opacity:1}.sign .manage[data-v-53d3caae]{margin-top:19px;margin-bottom:50px}.sign .manage img[data-v-53d3caae]{margin-right:20px}.sign .manage span[data-v-53d3caae]{width:340px;height:57px;font-size:54px;font-family:BigruixianBlackGBV1\.0;font-weight:400;line-height:57px;color:#2b53ec;opacity:1}.sign .title-1[data-v-53d3caae]{width:70px;height:35px;font-size:35px;font-family:Source Han Sans CN;font-weight:500;line-height:60px;color:#393939;opacity:1;margin-bottom:35px}.sign .el-button[data-v-53d3caae]{width:400px;height:58px;background:#2b53ec;border-radius:5px;margin-top:40px}.sign .el-checkbox[data-v-53d3caae]{color:#2b53ec}
|
||||
1
public/dist/css/507.e6e4e404.css
vendored
Normal file
1
public/dist/css/507.e6e4e404.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.block[data-v-5c3641da]{margin-top:20px}
|
||||
1
public/dist/css/523.c2fac020.css
vendored
Normal file
1
public/dist/css/523.c2fac020.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.block[data-v-28a560c7]{margin-top:20px}
|
||||
1
public/dist/css/550.83822904.css
vendored
Normal file
1
public/dist/css/550.83822904.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.block[data-v-395eec9a]{margin-top:20px}
|
||||
1
public/dist/css/561.6e3fdab5.css
vendored
Normal file
1
public/dist/css/561.6e3fdab5.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.block[data-v-cd5188f4]{margin-top:20px}
|
||||
1
public/dist/css/599.70613752.css
vendored
Normal file
1
public/dist/css/599.70613752.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.el-upload--picture-card[data-v-0509b8a0]{width:50px;height:50px}.avatar-uploader .el-upload[data-v-0509b8a0]{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader .el-upload[data-v-0509b8a0]:hover{border-color:#409eff}.avatar-uploader-icon[data-v-0509b8a0]{font-size:28px;color:#8c939d;width:148px;height:148px;line-height:148px;text-align:center}.avatar[data-v-0509b8a0]{width:148px;height:148px;display:block}.shop-sku-img[data-v-0509b8a0]{display:flex}.shop-sku-img .shop[data-v-0509b8a0]{margin-right:20px;margin-bottom:20px}.shop-sku-img .shop .shop-name[data-v-0509b8a0]{text-align:center}
|
||||
1
public/dist/css/637.5c0a41ae.css
vendored
Normal file
1
public/dist/css/637.5c0a41ae.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
|
||||
1
public/dist/css/650.5c0a41ae.css
vendored
Normal file
1
public/dist/css/650.5c0a41ae.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
|
||||
1
public/dist/css/674.6e10234a.css
vendored
Normal file
1
public/dist/css/674.6e10234a.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.table[data-v-b19d0430]{margin-top:20px;position:relative}.btn[data-v-b19d0430]{float:right}[data-v-b19d0430] .cell{display:flex;align-items:center}.commodityimg[data-v-b19d0430]{width:59px;height:59px;background:hsla(0,0%,89%,.39);opacity:1;display:block;margin-right:12px}.Img[data-v-b19d0430]{width:100%;height:100%}.confirmbtn[data-v-b19d0430]{width:114px;height:44px;border-radius:3px;margin-top:21px;margin-bottom:8px}.import-right[data-v-b19d0430]{margin-top:30px}.import-right a[data-v-b19d0430]{text-decoration:none;color:#000}[data-v-b19d0430] .btn11{padding:0;width:14px;height:14px}[data-v-b19d0430] .btn11 img{width:100%;height:100%}.page[data-v-b19d0430]{margin-top:20px}
|
||||
1
public/dist/css/679.32fc9cb6.css
vendored
Normal file
1
public/dist/css/679.32fc9cb6.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.table[data-v-5ba5084c]{margin-top:20px;position:relative}.btn[data-v-5ba5084c]{float:right}[data-v-5ba5084c] .cell{display:flex;align-items:center}.commodityimg[data-v-5ba5084c]{width:59px;height:59px;background:hsla(0,0%,89%,.39);opacity:1;display:block;margin-right:12px}.Img[data-v-5ba5084c]{width:100%;height:100%}[data-v-5ba5084c] .btn11{padding:0;width:14px;height:14px}[data-v-5ba5084c] .btn11 img{width:100%;height:100%}.page[data-v-5ba5084c]{margin-top:20px}
|
||||
1
public/dist/css/750.aa1db5a0.css
vendored
Normal file
1
public/dist/css/750.aa1db5a0.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.block[data-v-7a83ab34]{margin-top:20px}[data-v-7a83ab34] .el-card__body{padding:0}
|
||||
1
public/dist/css/800.97f84af6.css
vendored
Normal file
1
public/dist/css/800.97f84af6.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.block[data-v-891ad2ec]{margin-top:20px}
|
||||
1
public/dist/css/801.c437d427.css
vendored
Normal file
1
public/dist/css/801.c437d427.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.block[data-v-999e92dc]{margin-top:20px}
|
||||
1
public/dist/css/931.5c0a41ae.css
vendored
Normal file
1
public/dist/css/931.5c0a41ae.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}
|
||||
1
public/dist/css/949.3d2ed25d.css
vendored
Normal file
1
public/dist/css/949.3d2ed25d.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.block[data-v-26e9f73c]{margin-top:20px}
|
||||
1
public/dist/css/chunk-086a167d.daab9de2.css
vendored
1
public/dist/css/chunk-086a167d.daab9de2.css
vendored
@ -1 +0,0 @@
|
||||
.block[data-v-999e92dc]{margin-top:20px}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user