feat: 销售记录

This commit is contained in:
赵世界 2024-03-14 20:50:29 +08:00
parent c3a5f39ae6
commit 1b02f90047
13 changed files with 313 additions and 9 deletions

View File

@ -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'],
]);
}
}
}
}

View 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);
}
}

View 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);
}
}

View File

@ -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',
];
}

View File

@ -33,4 +33,9 @@ class FormatUtils
}
return $data;
}
public static function getPercent($dividend, $divisor, $decimal = 2)
{
return bcdiv($dividend, $divisor, $decimal + 2) * 100 . '%';
}
}

View File

@ -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();
});

View File

@ -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()

View 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,
});
}

View File

@ -186,4 +186,4 @@ export function delGoodsCombination(id) {
url: "/api/goods_combination/" + id,
method: "delete",
});
}
}

View File

@ -105,6 +105,11 @@ const list = [
name: "电子面单",
component: () => import("../views/plat/faceSheet.vue"),
},
{
path: "SALES_REPORT_DATA",
name: "销售数据",
component: () => import("../views/dataCenter/salesReport.vue"),
},
],
},
];

View 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>

View File

@ -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,
],
];

View File

@ -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');