feat: 销售记录
This commit is contained in:
parent
c3a5f39ae6
commit
1b02f90047
@ -9,6 +9,7 @@ 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
|
||||
{
|
||||
@ -58,6 +59,7 @@ class DailySalesReport extends Command
|
||||
'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'),
|
||||
@ -129,8 +131,16 @@ class DailySalesReport extends Command
|
||||
if (!isset($goodsSkus[$externalSkuId])) {
|
||||
continue;
|
||||
}
|
||||
\App\Models\DailySalesReport::query()
|
||||
->updateOrCreate([
|
||||
$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,
|
||||
], [
|
||||
@ -139,10 +149,29 @@ class DailySalesReport extends Command
|
||||
'name' => $goodsSkus[$externalSkuId]['name'],
|
||||
'inventory' => $goodsSkus[$externalSkuId]['daily']['inventory'],
|
||||
'arrived_today_num' => $goodsSkus[$externalSkuId]['daily']['arrived_today_num'],
|
||||
'already_cancel_number' => $datum['total_already_cancel_number'],
|
||||
'sales_num' => $sVal,
|
||||
'loss_num' => $goodsSkus[$externalSkuId]['daily']['loss_num'],
|
||||
$s => $datum['total_goods_number'],
|
||||
$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'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
app/Http/Controllers/DataCenter/DataCenterController.php
Normal file
38
app/Http/Controllers/DataCenter/DataCenterController.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?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');
|
||||
|
||||
|
||||
$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);
|
||||
}
|
||||
}
|
||||
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,9 +2,17 @@
|
||||
|
||||
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',
|
||||
];
|
||||
}
|
||||
|
||||
@ -33,4 +33,9 @@ class FormatUtils
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function getPercent($dividend, $divisor, $decimal = 2)
|
||||
{
|
||||
return bcdiv($dividend, $divisor, $decimal + 2) * 100 . '%';
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,10 +25,10 @@ class CreateDailySalesReportsTable extends Migration
|
||||
$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('sales_num')->default(0)->comment('销量');
|
||||
$table->integer('already_cancel_number')->default(0)->comment('已取消数量');
|
||||
$table->unsignedInteger('loss_num')->default(0)->comment('损耗');
|
||||
$table->decimal('goal_rate')->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');
|
||||
@ -36,6 +36,13 @@ class CreateDailySalesReportsTable extends Migration
|
||||
$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();
|
||||
});
|
||||
|
||||
@ -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()
|
||||
|
||||
9
resources/frontend/src/api/dataCenter.js
vendored
Normal file
9
resources/frontend/src/api/dataCenter.js
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
import http from "@/util/http.js";
|
||||
|
||||
export function getSalesReportData(params) {
|
||||
return http({
|
||||
url: "/api/data_center/sales_report",
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
}
|
||||
2
resources/frontend/src/api/goods.js
vendored
2
resources/frontend/src/api/goods.js
vendored
@ -186,4 +186,4 @@ export function delGoodsCombination(id) {
|
||||
url: "/api/goods_combination/" + id,
|
||||
method: "delete",
|
||||
});
|
||||
}
|
||||
}
|
||||
5
resources/frontend/src/router/list.js
vendored
5
resources/frontend/src/router/list.js
vendored
@ -105,6 +105,11 @@ const list = [
|
||||
name: "电子面单",
|
||||
component: () => import("../views/plat/faceSheet.vue"),
|
||||
},
|
||||
{
|
||||
path: "SALES_REPORT_DATA",
|
||||
name: "销售数据",
|
||||
component: () => import("../views/dataCenter/salesReport.vue"),
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
161
resources/frontend/src/views/dataCenter/salesReport.vue
Normal file
161
resources/frontend/src/views/dataCenter/salesReport.vue
Normal file
@ -0,0 +1,161 @@
|
||||
<template>
|
||||
<div class="conent">
|
||||
<el-card :body-style="{ padding: '20px 20px 0 20px' }">
|
||||
<el-form ref="form" :inline="true" :model="form">
|
||||
<el-form-item label="日期:">
|
||||
<el-date-picker v-model="form.date" type="date" placeholder="日期" format="yyyy-MM-DD" value-format="yyyy-MM-DD"></el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="商品名称:">
|
||||
<el-input v-model="form.name" placeholder="商品名称"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleChoose">筛选</el-button>
|
||||
<el-button plain @click="handleReChoose">重置筛选</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card style="margin-top: 10px">
|
||||
<el-table v-loading="loading" ref="multipleTable" :data="tableData" style="width: 100%"
|
||||
@sort-change="sortChange" :default-sort="{ prop: 'sales_num', order: 'descending' }">
|
||||
<el-table-column label="商品名称" prop="name" width="250"></el-table-column>
|
||||
<el-table-column label="完整编码" prop="external_sku_id"></el-table-column>
|
||||
<el-table-column label="入库数量" prop="stock"></el-table-column>
|
||||
<el-table-column label="销量" prop="sales_num" sortable="custom"></el-table-column>
|
||||
<el-table-column label="损耗" prop="loss_num"></el-table-column>
|
||||
<el-table-column label="目标去化率" prop="goal_rate"></el-table-column>
|
||||
|
||||
<el-table-column label="S1(11:00-12:00)">
|
||||
<el-table-column prop="S1" label="销量">
|
||||
</el-table-column>
|
||||
<el-table-column prop="S1_rate" label="去化率" sortable="custom">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="S2(11:00-13:30)">
|
||||
<el-table-column prop="S2" label="销量">
|
||||
</el-table-column>
|
||||
<el-table-column prop="S2_rate" label="去化率" sortable="custom">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="S3(11:00-15:00)">
|
||||
<el-table-column prop="S3" label="销量">
|
||||
</el-table-column>
|
||||
<el-table-column prop="S3_rate" label="去化率" sortable="custom">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="S4(15:00-16:00)">
|
||||
<el-table-column prop="S4" label="销量">
|
||||
</el-table-column>
|
||||
<el-table-column prop="S4_rate" label="去化率" sortable="custom">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="S5(11:00-17:30)">
|
||||
<el-table-column prop="S5" label="销量">
|
||||
</el-table-column>
|
||||
<el-table-column prop="S5_rate" label="去化率" sortable="custom">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="S6(11:00-20:00)">
|
||||
<el-table-column prop="S6" label="销量">
|
||||
</el-table-column>
|
||||
<el-table-column prop="S6_rate" label="去化率" sortable="custom">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="S7(11:00-09:00)">
|
||||
<el-table-column prop="S7" label="销量">
|
||||
</el-table-column>
|
||||
<el-table-column prop="S7_rate" label="去化率" sortable="custom">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页功能 -->
|
||||
<div class="block">
|
||||
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
|
||||
:current-page="current_page" :page-sizes="[50, 100, 150, 200]" :page-size="per_page"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="Paginationdata.total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSalesReportData } from "../../api/dataCenter";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
date: "",
|
||||
name: "",
|
||||
sort: "sales_num",
|
||||
sortOrder: "DESC",
|
||||
},
|
||||
loading: true,
|
||||
tableData: [],
|
||||
Paginationdata: {}, //分页相关数据
|
||||
current_page: 1, //当前页
|
||||
per_page: 50, //每页显示数量
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.salseReportData();
|
||||
},
|
||||
methods: {
|
||||
// 销售数据
|
||||
salseReportData(params = {}) {
|
||||
params.page = this.current_page;
|
||||
params.per_page = this.per_page;
|
||||
|
||||
getSalesReportData(params).then((res) => {
|
||||
this.tableData = res.data.data;
|
||||
this.Paginationdata = res.data.meta;
|
||||
});
|
||||
this.loading = false;
|
||||
},
|
||||
//分页功能
|
||||
handleSizeChange(val) {
|
||||
//当前条数
|
||||
this.current_page = 1;
|
||||
this.per_page = val;
|
||||
this.salseReportData();
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
//当前页
|
||||
this.current_page = val;
|
||||
this.salseReportData();
|
||||
},
|
||||
// 筛选
|
||||
handleChoose() {
|
||||
this.form = {
|
||||
...this.form,
|
||||
page: 1,
|
||||
per_page: this.per_page,
|
||||
};
|
||||
this.salseReportData(this.form);
|
||||
},
|
||||
// 重置筛选
|
||||
handleReChoose() {
|
||||
this.form = {
|
||||
date: "",
|
||||
name: "",
|
||||
};
|
||||
this.salseReportData();
|
||||
},
|
||||
// 排序
|
||||
sortChange(line) {
|
||||
this.form.sort = line.prop;
|
||||
this.form.sortOrder = ('ascending' === line.order) ? 'ASC' : 'DESC';
|
||||
this.salseReportData(this.form);
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.block {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
@ -459,4 +459,22 @@ return [
|
||||
'name' => '收货信息保存',
|
||||
'parent_id' => 170,
|
||||
],
|
||||
// 数据中心
|
||||
'DATA_CENTER' => [
|
||||
'id' => 18,
|
||||
'name' => '数据中心',
|
||||
'parent_id' => 0,
|
||||
'show' => 1,
|
||||
],
|
||||
'SALES_REPORT_DATA' => [
|
||||
'id' => 180,
|
||||
'name' => '销售数据',
|
||||
'parent_id' => 18,
|
||||
'show' => 1,
|
||||
],
|
||||
'sales_report.index' => [
|
||||
'id' => 1800,
|
||||
'name' => '销售数据列表',
|
||||
'parent_id' => 180,
|
||||
],
|
||||
];
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\Auth\LoginController;
|
||||
use App\Http\Controllers\DataCenter\DataCenterController;
|
||||
use App\Http\Controllers\Role\RolesController;
|
||||
use App\Http\Controllers\Shop\ShipController;
|
||||
use App\Http\Controllers\UploadController;
|
||||
@ -69,6 +70,8 @@ Route::middleware(['auth:api', 'check.permissions'])->group(function () {
|
||||
// 发货信息
|
||||
Route::get('shop/ship/senders', [ShipController::class, 'getSenders'])->name('shop_ship.senders.get');
|
||||
Route::post('shop/ship/senders', [ShipController::class, 'saveSenders'])->name('shop_ship.senders.save');
|
||||
// 数据中心
|
||||
Route::get('data_center/sales_report', [DataCenterController::class, 'salesReport'])->name('sales_report.index');
|
||||
});
|
||||
Route::get('stock/goods_skus', [GoodsSkusController::class, 'stockNum'])->middleware('auth:api');
|
||||
Route::get('goods/filter/{title}', [GoodsCombinationController::class, 'goodsSkus'])->middleware('auth:api');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user