鲜花2.0-gmv接口开发完成+ sku和spu维度的报表接口开发完成

This commit is contained in:
杨建炊 2024-08-02 16:40:57 +08:00
parent f9bc1fc65a
commit dd6f9427c7
16 changed files with 304 additions and 153 deletions

View File

@ -32,6 +32,7 @@ class BusinessOrdersUpdate
*/
public function __construct($businessGoodSku, $num)
{
try {
$this->businessGoodSku = $businessGoodSku->toArray();
$this->num = $num;
$updateResult = false;
@ -45,9 +46,14 @@ class BusinessOrdersUpdate
if (!$updateResult) {
Log::error("sku 业务更新失败", (array)$this->businessGoodSku);
}
} catch (\Exception $exception) {
Log::error("库存告警发生异常", ["error" => $exception->getMessage()]);
}
}
private function updateStock()
private
function updateStock()
{
$this->goodsSku = GoodsSku::query()
->where('external_sku_id', $this->businessGoodSku['external_sku_id'])
@ -76,7 +82,8 @@ class BusinessOrdersUpdate
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
public
function broadcastOn()
{
return new PrivateChannel('channel-name');
}

View File

@ -47,4 +47,23 @@ class Controller extends BaseController
return $this->log->add($targetId, $targetField);
}
public function success($data, $msg = "")
{
return [
"success" => true,
"msg" => $msg,
"data" => $data
];
}
public function error($errorCode, $msg = "")
{
return [
"success" => false,
"msg" => $msg,
"errorCode" => $errorCode,
"data"=>[]
];
}
}

View File

@ -57,8 +57,8 @@ class DataCenterController extends Controller
//进行校验验证
$validator = Validator::make($allParams, [
'type' => 'required|integer', //1表示今日
'start_day' => 'sometimes|string',
'end_day' => 'sometimes|string'
'start_day' => 'sometimes|date_format:Y-m-d',
'end_day' => 'sometimes|date_format:Y-m-d'
]);
if ($validator->fails()) {
@ -66,7 +66,7 @@ class DataCenterController extends Controller
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
return SaleDataService::saleStatistics($request);
return $this->success(SaleDataService::saleStatistics($request));
}
/**
@ -74,7 +74,8 @@ class DataCenterController extends Controller
* @param Request $request
* @return array|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response|mixed
*/
public function spuSaleStatistics(Request $request){
public function spuSaleStatistics(Request $request)
{
//进行校验验证
$validator = Validator::make($request->all(), [
'type' => 'required|integer', //1表示今日
@ -86,21 +87,23 @@ class DataCenterController extends Controller
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
return SaleDataService::spuSaleStatistics($request);
return $this->success(SaleDataService::spuSaleStatistics($request));
}
public function gmvStatistics(Request $request){
public function gmvStatistics(Request $request)
{
//进行校验验证
$validator = Validator::make($request->all(), [
'type' => 'required|integer', //1表示今日
'start_day' => 'sometimes|date_format:Y-m-d',
'end_day' => 'sometimes|date_format:Y-m-d'
'start_day' => 'required_unless:type,1|date_format:Y-m-d',
'end_day' => 'required_unless:type,1|date_format:Y-m-d',
"interval" => 'sometimes|integer|max:120|min:1'
]);
if ($validator->fails()) {
//校验失败返回异常
$this->setValidatorFailResponse($validator->getMessageBag()->getMessages());
return response($this->res, $this->res['httpCode']);
}
return SaleDataService::gmvStatistics($request);
return $this->success(SaleDataService::gmvStatistics($request));
}
}

View File

@ -30,7 +30,7 @@ class DailyStockRecordController extends Controller
public function index(Request $request)
{
$build = DailyStockRecord::query()->filter()->with("goodsSku:id,name");
$build = DailyStockRecord::query()->filter()->with("goodsSku:id,name,title");
if (!empty($request->title)) {
$build->whereHas('goodsSku', function ($query) use ($request) {
$query->where('name', 'like', '%' . $request->title . '%');

View File

@ -22,10 +22,18 @@ use Maatwebsite\Excel\Facades\Excel;
class LossRecordController extends Controller
{
public function __construct(Request $request)
{
$this->log = new LogModel([
'module' => 'supplier',
'action' => $request->getMethod(),
'target_type' => 'loss_record',
]);
}
public function index(Request $request)
{
$builder = LossRecords::query()->filter()->with("goodsSku:name,external_sku_id");
$builder = LossRecords::query()->filter()->with("goodsSku:name,external_sku_id,title");
if (!empty($request->start_time) && !empty($request->end_time)) {
$builder->whereBetween('created_at', [$request->start_time, $request->end_time]);
}

View File

@ -11,7 +11,6 @@ use App\Imports\PurchaseImport;
use App\Models\GoodsSku;
use App\Models\Log;
use App\Models\Log as LogModel;
use App\Models\LossRecords;
use App\Models\PurchaseRecords;
use App\Models\Suppliers;
use App\Services\DeveloperConfig\DeveloperConfigService;
@ -26,10 +25,17 @@ use Maatwebsite\Excel\Facades\Excel;
class PurchaseRecordController extends Controller
{
public function __construct(Request $request)
{
$this->log = new LogModel([
'module' => 'supplier',
'action' => $request->getMethod(),
'target_type' => 'purchase_record',
]);
}
public function index(Request $request)
{
$builder = PurchaseRecords::query()->filter()->with("goodsSku:id,name,external_sku_id");
$builder = PurchaseRecords::query()->filter()->with("goodsSku:id,name,external_sku_id,title");
if (!empty($request->start_time) && !empty($request->end_time)) {
$builder->whereBetween('created_at', [$request->start_time, $request->end_time]);
}

View File

@ -21,6 +21,7 @@ class InventoryImport implements ToArray, SkipsEmptyRows
*/
public function array(array $collection)
{
if (!empty($collection)) {
unset($collection[0]);
$externalSkuIds = [];
$inventoryKeyByExternalSkuIdMap = [];
@ -46,3 +47,4 @@ class InventoryImport implements ToArray, SkipsEmptyRows
$goodSkuService->inventory($goodsSkus);
}
}
}

View File

@ -23,6 +23,7 @@ class LossImport implements ToArray, SkipsEmptyRows
*/
public function array(array $collection)
{
if(!empty($collection)){
unset($collection[0]);
$externalSkuIds = [];
foreach ($collection as &$row) {
@ -35,9 +36,10 @@ class LossImport implements ToArray, SkipsEmptyRows
$updateIds = [];
$hasGoodsSkus = GoodsSku::query()
->whereIn('external_sku_id', $externalSkuIds)
->get(['id', 'status', 'external_sku_id', 'stock'])
->get(['id', 'status', 'external_sku_id', 'stock', "sale_stock", "cost"])
->toArray();
$hasGoodsSkus = ArrayUtils::index($hasGoodsSkus, 'external_sku_id');
//excel字段排序 編碼 商品名稱 报损數量 成本价 采购人名称 报损原因
foreach ($collection as $row) {
if (!isset($hasGoodsSkus[$row[0]])) {
@ -61,4 +63,7 @@ class LossImport implements ToArray, SkipsEmptyRows
// 批量更新
event(new BatchStockUpdateEvent($updateIds));
}
}
}

View File

@ -24,6 +24,7 @@ class PurchaseImport implements ToArray, SkipsEmptyRows
*/
public function array(array $collection)
{
if (!empty($collection)) {
unset($collection[0]);
$externalSkuIds = [];
foreach ($collection as &$row) {
@ -65,3 +66,4 @@ class PurchaseImport implements ToArray, SkipsEmptyRows
event(new BatchStockUpdateEvent($updateIds));
}
}
}

View File

@ -16,6 +16,8 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use App\Services\Business\BusinessFactory;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class BusinessOrderUpdateListener implements ShouldQueue
{
@ -39,6 +41,7 @@ class BusinessOrderUpdateListener implements ShouldQueue
*/
public function handle(BusinessOrdersUpdate $event)
{
try {
//查询库存是否满足告警规则
$skuId = $event->goodsSku->id;
$nowTime = Carbon::now()->toDateTimeString();
@ -56,5 +59,8 @@ class BusinessOrderUpdateListener implements ShouldQueue
$messageService = new MessageService();
$messageService->createLowerStockNoticeMessage($inventory, $event->goodsSku->toArray());
}
}catch(\Exception $exception) {
Log::error("库存告警发生异常",["error"=>$exception->getMessage()]);
}
}
}

View File

@ -74,8 +74,8 @@ class GoodSkuService
public function handleSkusWithCombinationGoods(array $skusWithCombinationGoods){
//查询sku当前未发货的数量 需要扣减
$externalSkuIds = collect($skusWithCombinationGoods)->pluck("external_sku_id")->toArray();
//默认只查7天内未发货的数据
$startTime = Carbon::now()->subDays(7)->startOfDay()->toDateTimeString();
//默认只查15天内未发货的数据
$startTime = Carbon::now()->subDays(15)->startOfDay()->toDateTimeString();
$unshippedDataCollect = BusinessOrderItem::query()
->leftJoin("business_orders as b", "business_order_id", "=", "b.id")
->select("external_sku_id", DB::raw("sum(goods_number) as goods_total"), DB::raw("sum(already_cancel_number) as cancel_total"))
@ -107,7 +107,8 @@ class GoodSkuService
'cost' => number_format(($goodsSkuItem['stock'] * $goodsSkuItem['cost'] + $v['cost'] * $v['num'])
/ ($goodsSkuItem['stock'] + $v['num']), 2),
];
GoodsSku::query()->where('external_sku_id', $goodsSkuItem['external_sku_id'])->update($updateParams);
GoodsSku::query()->where('external_sku_id',"=", $goodsSkuItem['external_sku_id'])
->update($updateParam);
$updateIds[] = $goodsSkuItem['id'];
$updateParams[] = $updateParam;
} else {

View File

@ -40,7 +40,7 @@ class SaleDataService
, DB::raw("sum(CASE WHEN b.shipping_status=0 THEN goods_number-already_cancel_number ELSE 0 END) as unshipping_num")
, DB::raw("sum(goods_number-already_cancel_number) as goods_total")
, DB::raw("ROUND(sum(goods_amount) / 100,2) as goods_total_amount"))
->where("business_order_items.created_at", ">", Carbon::now()->startOfDay()->toDateTimeString())
->where("business_order_items.created_at", ">", Carbon::now()->subDays(3)->startOfDay()->toDateTimeString())
->where("business_order_items.cancel_status", "=", 0)
->groupBy('external_sku_id')
->orderBy("goods_total", "DESC")
@ -62,7 +62,7 @@ class SaleDataService
$endTime = Carbon::parse($request->input("end_day"))->endOfDay()->toDateTimeString();
$dailyRecord = DailyStockRecord::query()
->select("sku_id", DB::raw("sum(order_goods_num) as goods_total")
, DB::raw("ROUND(sum(order_total_amount) / 100,2) as goods_total_amount"))
, DB::raw("sum(order_total_amount) as goods_total_amount"))
->whereBetween("created_at", [$startTime, $endTime])
->groupBy("sku_id")
->having(DB::raw("sum(order_goods_num)"), ">", 0)
@ -136,14 +136,14 @@ class SaleDataService
{
//spu 基本就是全统计了
if (StaticTypeEnum::TODAY == $request->type) {
return static::spuSaleStatisticsByToday($request);
return static::spuSaleStatisticsByToday();
} else {
//统计历史数据 这里走缓存
return static::spuSaleStatisticsByHistoryCache($request);
}
}
public static function spuSaleStatisticsByToday(Request $request)
public static function spuSaleStatisticsByToday()
{
//实时统计 sku维度
$orderItems = BusinessOrderItem::query()
@ -153,7 +153,7 @@ class SaleDataService
, DB::raw("sum(CASE WHEN b.shipping_status=0 THEN goods_number-already_cancel_number ELSE 0 END) as unshipping_num")
, DB::raw("sum(goods_number-already_cancel_number) as goods_total")
, DB::raw("ROUND(sum(goods_amount) / 100,2) as goods_total_amount"))
->where("business_order_items.created_at", ">", Carbon::now()->startOfDay()->toDateTimeString())
->where("business_order_items.created_at", ">", Carbon::now()->subDays(3)->startOfDay()->toDateTimeString())
->where("business_order_items.cancel_status", "=", 0)
->groupBy('external_sku_id')->get()->toArray();
$externalSkuIds = collect($orderItems)->pluck("external_sku_id")->toArray();
@ -183,6 +183,11 @@ class SaleDataService
})->values()->toArray();
}
/**
* 通过历史报表统计spu数据-缓存
* @param Request $request
* @return mixed
*/
public static function spuSaleStatisticsByHistoryCache(Request $request)
{
$startTime = Carbon::parse($request->input("start_day"))->toDateTimeString();
@ -194,11 +199,17 @@ class SaleDataService
});
}
/**
* 通过历史报表统计spu数据
* @param $startTime
* @param $endTime
* @return array
*/
public static function spuSaleStatisticsByHistory($startTime, $endTime)
{
$dailyAllRecord = DailyStockRecord::query()
->select("sku_id", DB::raw("sum(order_goods_num) as goods_total")
, DB::raw("ROUND(sum(order_total_amount) / 100,2) as goods_total_amount"))
, DB::raw("sum(order_total_amount) as goods_total_amount"))
->whereBetween("created_at", [$startTime, $endTime])
->groupBy("sku_id")
->having(DB::raw("sum(order_goods_num)"), ">", 0)
@ -226,18 +237,46 @@ class SaleDataService
];
})->values()->toArray();
}
public static function gmvStatistics(Request $request){
public static function gmvStatistics(Request $request)
{
//gmv
if (StaticTypeEnum::TODAY == $request->type) {
//以半小时为间隔统计数据
$todayStartTime = Carbon::now()->subDays(3)->startOfDay()->toDateTimeString();
$orderItems = BusinessOrderItem::query()
->select("business_order_items.external_sku_id", "goods_number", "already_cancel_number", "goods_amount", "created_at")
->where("business_order_items.created_at", ">", $todayStartTime)
->where("business_order_items.cancel_status", "=", 0)
->get()->toArray();
$interval = $request->input("interval", 30);
return collect($orderItems)->groupBy(function ($v) use ($todayStartTime, $interval) {
$diff = Carbon::parse($v['created_at'])->diffInMinutes(Carbon::parse($todayStartTime));
return (int)floor($diff / $interval);
})->map(function ($v, $key) use ($todayStartTime, $interval) {
return [
"sort_key" => $key,
"interval" => $interval,
"time_start" => Carbon::parse($todayStartTime)->addMinutes($key * $interval)->toTimeString(),
"time_end" => Carbon::parse($todayStartTime)->addMinutes(($key + 1) * $interval)->toTimeString(),
"goods_total" => $v->sum("goods_number") - $v->sum("already_cancel_number"),
"goods_total_amount" => $v->sum("goods_amount"),
];
})->sort()->values()->toArray();
} else {
//统计历史数据 这里走缓存
//统计历史数据
$startTime = Carbon::parse($request->input("start_day"))->toDateTimeString();
$endTime = Carbon::parse($request->input("end_day"))->endOfDay()->toDateTimeString();
}
return DailyStockRecord::query()
->select("day", DB::raw("sum(order_total_amount) as goods_total_amount")
, DB::raw("sum(order_goods_num) as goods_total"))
->whereBetween("created_at", [$startTime, $endTime])
->groupBy("day")->orderBy("day")
->get()->toArray();
}
}
}

View File

@ -20,6 +20,7 @@ class CreateSuppliersTable extends Migration
$table->string('address')->nullable()->comment('地址');
$table->string('link_tel',100)->nullable()->comment('联系方式');
$table->string('payment_account',100)->nullable()->comment('支付方式');
$table->string('supply_type')->nullable()->comment('供应类型');
$table->string('agent_name')->nullable()->comment('代理人名称');
$table->Integer('agent_id')->nullable()->comment('代理人id');

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddOrderTotalAmountToDailyStockRecord extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (Schema::hasColumn('daily_stock_records', 'order_total_amount')) {
return;
}
Schema::table('daily_stock_records', function (Blueprint $table) {
$table->decimal('order_total_amount')->default(0)->comment('订单总金额');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('daily_stock_record', function (Blueprint $table) {
//
});
}
}

View File

@ -600,18 +600,35 @@ return [
],
'sale_statistics' => [
'id' => 181,
'name' => '销售统计',
'name' => 'sku销售统计',
'parent_id' => 18,
'show' => 1,
],
'data_center.sale_statistics' => [
'id' => 1811,
'name' => '销售统计',
'name' => 'sku统计接口',
'parent_id' => 18
],
'spu_sale_statistics' => [
'id' => 182,
'name' => 'spu销售统计',
'parent_id' => 18,
'show' => 1,
],
'data_center.spu_sale_statistics' => [
'id' => 1812,
'name' => 'spu销售统计',
'id' => 1820,
'name' => 'spu销售统计接口',
'parent_id' => 18
],
'gmv_statistics' => [
'id' => 183,
'name' => '交易趋势',
'parent_id' => 18,
'show' => 1,
],
'data_center.gmv_statistics' => [
'id' => 1830,
'name' => 'gmv统计',
'parent_id' => 18,
],
];

View File

@ -89,7 +89,7 @@ Route::middleware(['auth:api', 'check.permissions'])->group(function () {
// 数据中心 销售报表
Route::get('data_center/sale_statistics', [DataCenterController::class, 'saleStatistics'])->name('data_center.sale_statistics');
Route::get('data_center/spu_sale_statistics', [DataCenterController::class, 'spuSaleStatistics'])->name('data_center.spu_sale_statistics');
Route::get('data_center/gmv_statistics', [DataCenterController::class, 'gmvStatistics'])->name('data_center.gmv_statistics');
});
Route::get('stock/goods_skus', [GoodsSkusController::class, 'stockNum'])->middleware('auth:api');
Route::get('goods/filter/{title}', [GoodsCombinationController::class, 'goodsSkus'])->middleware('auth:api');