同步卡基础信息数据
This commit is contained in:
parent
3cc1811c70
commit
241dcc5b6c
@ -4,6 +4,7 @@ namespace App\Domains\Real\Commands\Sync;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use App\Models\Card\Card;
|
||||
use Illuminate\Support\Arr;
|
||||
use MongoDB\BSON\UTCDateTime;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
@ -25,7 +26,8 @@ class MongoSync extends Command
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$nextMicrotime = $microtime = app(ConfigService::class)->get(self::CURSOR_KEY) ?: 946656000000;
|
||||
$microtime = app(ConfigService::class)->get(self::CURSOR_KEY) ?: 946656000000;
|
||||
$nextMicrotime = intval(microtime(true) * 1000);
|
||||
|
||||
$utcDateTime = new UTCDateTime($microtime);
|
||||
|
||||
@ -33,9 +35,8 @@ class MongoSync extends Command
|
||||
$blocs = app(BlocRepository::class)->get()->pluck('id', 'sn')->toArray();
|
||||
|
||||
$query = DB::connection('mongo')->table('tblCard')
|
||||
->select(['cNo', 'iccid', 'imsi', 'comId', 'oType', 'saDate', 'sDate'])
|
||||
->where('isDel', '<>', 1)
|
||||
->where('sDate', '>', $utcDateTime)
|
||||
->select(['cNo', 'bNo', 'iccid', 'imsi', 'comId', 'oType', 'saDate', 'sDate'])
|
||||
->where('oRDate', '>', $utcDateTime)
|
||||
->orderBy('sDate');
|
||||
|
||||
$total = $query->count();
|
||||
@ -66,18 +67,22 @@ class MongoSync extends Command
|
||||
'carrier_operator' => self::$carrierOperators[$value['oType']] ?? 255,
|
||||
'activated_at' => $activated_at,
|
||||
'virtual_activated_at' => $activated_at,
|
||||
'order_status' => intval(!empty($value['bNo'])),
|
||||
'created_at' => $value['sDate']->toDateTime()->format('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
|
||||
$nextMicrotime = (string) $value['sDate'];
|
||||
|
||||
$nextMicrotime = ($nextMicrotime > $microtime) ? $nextMicrotime : $microtime;
|
||||
}
|
||||
|
||||
Card::upsert($values, 'sim', true);
|
||||
$builder = Card::query()->toBase();
|
||||
|
||||
app(ConfigService::class)->set(self::CURSOR_KEY, intval($nextMicrotime));
|
||||
$sql = $builder->getGrammar()->compileInsert($builder, $values);
|
||||
|
||||
$sql .= 'on conflict (sim) do update set
|
||||
activated_at=excluded.activated_at,
|
||||
virtual_activated_at=COALESCE(cards.virtual_activated_at, excluded.activated_at),
|
||||
order_status=excluded.order_status';
|
||||
|
||||
$builder->connection->insert($sql, Arr::flatten($array, 1));
|
||||
|
||||
if ($page * $this->limit >= $total) {
|
||||
break;
|
||||
@ -86,6 +91,8 @@ class MongoSync extends Command
|
||||
$page++;
|
||||
}
|
||||
|
||||
app(ConfigService::class)->set(self::CURSOR_KEY, intval($nextMicrotime));
|
||||
|
||||
app(CardRepository::class)->forgetCached();
|
||||
}
|
||||
}
|
||||
|
@ -24,44 +24,27 @@ class OrderController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index($type)
|
||||
public function index()
|
||||
{
|
||||
$conditions = $this->request->all();
|
||||
$conditions['type'] = $type;
|
||||
|
||||
$res = $this->OrderService->index($conditions);
|
||||
$res = $this->orderService->index($conditions);
|
||||
|
||||
return res($res, '订单统计', 201);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建.
|
||||
* 统计明细.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
public function detail()
|
||||
{
|
||||
//
|
||||
}
|
||||
$conditions = $this->request->all();
|
||||
|
||||
/**
|
||||
* 编辑.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy()
|
||||
{
|
||||
//
|
||||
$res = $this->orderService->detail($conditions);
|
||||
|
||||
return res($res, '统计明细', 201);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ $router->group(['prefix' => 'stats', 'as' => 'stats', 'middleware' => ['adminAut
|
||||
$router->get('/company-count/export', ['as' => 'company-count.export', 'uses' => 'CompanyCountController@export']);
|
||||
|
||||
// 订单统计
|
||||
$router->get('/order/{type}', ['as' => 'order.index', 'uses' => 'OrderController@index']);
|
||||
$router->get('/order', ['as' => 'order.index', 'uses' => 'OrderController@index']);
|
||||
|
||||
});
|
||||
|
@ -43,16 +43,15 @@ class OrderService extends Service
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function index($type, array $conditions = [])
|
||||
public function index(array $conditions = [])
|
||||
{
|
||||
$conditions['type'] = $type;
|
||||
$conditions['source'] = 1;
|
||||
|
||||
$companies = $this->companyRepository->withTrashed()->get()->pluck('name', 'id')->toArray();
|
||||
$packages = $this->packageRepository->withTrashed()->get()->pluck('name', 'id')->toArray();
|
||||
|
||||
$select = [
|
||||
DB::raw("string_agg(DISTINCT id, ',') as id"),
|
||||
DB::raw("array_to_string(array_agg(id), ',') as order_id"),
|
||||
'company_id',
|
||||
'package_id',
|
||||
'product_id',
|
||||
@ -63,10 +62,12 @@ class OrderService extends Service
|
||||
];
|
||||
|
||||
$orders = $this->orderRepository->select($select)->withConditions($conditions)->applyConditions()
|
||||
->groupBy(['company_id', 'product_id', 'pay_channel'])->paginate($conditions['limit']);
|
||||
|
||||
->groupBy(['company_id', 'package_id', 'product_id', 'unit_price', 'pay_channel'])->paginate($conditions['limit']);
|
||||
|
||||
$orders->map(function ($item) use ($companies, $packages) {
|
||||
$item->company_name = $packages[$item->company_id];
|
||||
$item->unit_price = floatval(sprintf('%.02f', $item->unit_price/100));
|
||||
$item->custom_price = floatval(sprintf('%.02f', $item->custom_price/100));
|
||||
$item->company_name = $companies[$item->company_id];
|
||||
$item->package_name = $packages[$item->package_id];
|
||||
$item->pay_channel_name = CommonService::namePayChannel($item->pay_channel);
|
||||
});
|
||||
@ -88,29 +89,19 @@ class OrderService extends Service
|
||||
$repository = app($class);
|
||||
|
||||
$companies = $this->companyRepository->withTrashed()->get()->pluck('name', 'id')->toArray();
|
||||
$packages = $this->packageRepository->withTrashed()->get()->pluck('name', 'id')->toArray();
|
||||
$packages = $this->packageRepository->withTrashed()->get()->keyBy('id')->toArray();
|
||||
|
||||
$repository->withConditions($conditions)->applyConditions()->paginate($conditions['limit']);
|
||||
$cards = $repository->with('order:id,unit_price,pay_channel,order_at')->withConditions($conditions)->applyConditions()->paginate($conditions['limit']);
|
||||
|
||||
$select = [
|
||||
'id',
|
||||
'company_id',
|
||||
'package_id',
|
||||
'unit_price',
|
||||
'pay_channel',
|
||||
DB::raw('SUM(counts) as counts'),
|
||||
DB::raw('SUM(custom_price) as custom_price'),
|
||||
];
|
||||
|
||||
$orders = $this->orderRepository->select($select)->withConditions($conditions)->applyConditions()
|
||||
->groupBy(['company_id', 'product_id', 'pay_channel'])->paginate($conditions['limit']);
|
||||
|
||||
$orders->map(function ($item) use ($companies, $packages) {
|
||||
$cards->map(function ($item) use ($companies, $packages) {
|
||||
$item->company_name = $packages[$item->company_id];
|
||||
$item->package_name = $packages[$item->package_id];
|
||||
$item->pay_channel_name = CommonService::namePayChannel($item->pay_channel);
|
||||
$item->package_name = $packages[$item->package_id]['name'];
|
||||
$item->service_months = $packages[$item->package_id]['service_months'];
|
||||
$item->unit_price = $item->order['unit_price'];
|
||||
$item->pay_channel_name = CommonService::namePayChannel($item->order['pay_channel']);
|
||||
$item->order_at = $item->order['order_at'];
|
||||
});
|
||||
|
||||
return $orders;
|
||||
return $cards;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,11 @@ trait OrderCardConcern
|
||||
$this->model = $this->model->whereIn('id', $conditions['id']);
|
||||
}
|
||||
|
||||
if (isset($conditions['order_id'])) {
|
||||
$conditions['order_id'] = array_wrap($conditions['order_id']);
|
||||
$this->model = $this->model->whereIn('order_id', $conditions['order_id']);
|
||||
}
|
||||
|
||||
if (isset($conditions['sim'])) {
|
||||
$conditions['sim'] = array_wrap($conditions['sim']);
|
||||
$this->model = $this->model->whereIn('sim', $conditions['sim']);
|
||||
|
@ -26,6 +26,7 @@ class CreateCardsTable extends Migration
|
||||
$table->timestamp('activated_at')->nullable()->comment('激活时间');
|
||||
$table->timestamp('virtual_activated_at')->nullable()->comment('虚拟激活时间');
|
||||
$table->tinyInteger('type')->unsigned()->default(0)->comment('类型(0:真实卡 1:虚拟卡 2:未知卡)');
|
||||
$table->tinyInteger('order_status')->unsigned()->default(0)->comment('订单状态 0:正常 1:退货');
|
||||
$table->timestamp('cancelled_at')->nullable()->comment('注销时间');
|
||||
$table->timestamps();
|
||||
|
||||
|
@ -153,9 +153,11 @@ class PermissionSeeder extends Seeder
|
||||
'type' => 0,
|
||||
'open' => 3,
|
||||
'children' => [
|
||||
[
|
||||
'name' => 'stats.company-index', 'title' => '企业统计', 'path' => '/stats/company-count', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3
|
||||
],
|
||||
['name' => 'stats.company-index', 'title' => '企业统计', 'path' => '/stats/company-count', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
||||
['name' => 'stats.order.0', 'title' => '销售订单统计', 'path' => '/stats/order/0', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
||||
['name' => 'stats.order.1', 'title' => '续费订单统计', 'path' => '/stats/order/1', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
||||
['name' => 'stats.order.2', 'title' => '续费包订单统计', 'path' => '/stats/order/2', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
||||
['name' => 'stats.order.3', 'title' => '加油包订单统计', 'path' => '/stats/order/3', 'icon' => 'md-pulse', 'type' => 0, 'open' => 3],
|
||||
],
|
||||
],
|
||||
[
|
||||
|
@ -24,7 +24,8 @@ const routes = [
|
||||
{ path: '/packages/:type', name: 'Packages', component: load('virtual/packages/index'), meta: { title: '套餐管理' } },
|
||||
{ path: '/cards', name: 'Cards', component: load('virtual/cards/index'), meta: { title: '客户列表' } },
|
||||
{ path: '/exports', name: 'StatsExports', component: load('exports/index'), meta: { title: '导出记录' } },
|
||||
{ path: '/stats/company-count', name: 'StatsCompanyCount', component: load('stats/company-count/index'), meta: { title: '企业统计' } }
|
||||
{ path: '/stats/company-count', name: 'StatsCompanyCount', component: load('stats/company-count/index'), meta: { title: '企业统计' } },
|
||||
{ path: '/stats/order/:type', name: 'StatsOrder', component: load('stats/order/index'), meta: { title: '订单统计' } }
|
||||
]
|
||||
},
|
||||
{ path: '*', redirect: { path: '/home' } }
|
||||
|
@ -52,9 +52,7 @@ export default {
|
||||
};
|
||||
},
|
||||
created() {
|
||||
window.t = this;
|
||||
this.index();
|
||||
console.log(this.$refs.table);
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
@ -129,7 +127,6 @@ export default {
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
let html = $('.ivu-table-header colgroup').html();
|
||||
console.log(html);
|
||||
$('.table-footer-colgroup').html(html);
|
||||
}, 10);
|
||||
});
|
||||
|
114
frontend/src/views/stats/order/index.vue
Normal file
114
frontend/src/views/stats/order/index.vue
Normal file
@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<div class="page-wrap">
|
||||
<ui-loading :show="page_loading.show"></ui-loading>
|
||||
|
||||
<div class="page-handle-wrap">
|
||||
<ul class="handle-wraper bd-b">
|
||||
<li class="f-l">
|
||||
<div class="text-exp">
|
||||
<b>全部信息</b>
|
||||
</div>
|
||||
</li>
|
||||
<li class="f-r">
|
||||
<div class="handle-item">
|
||||
<Button @click="search.show=!search.show" ghost icon="ios-search" type="primary">搜索</Button>
|
||||
</div>
|
||||
|
||||
<div class="handle-item">
|
||||
<Button @click="index(1)" icon="md-refresh">刷新</Button>
|
||||
</div>
|
||||
|
||||
<div class="handle-item">
|
||||
<Button @click="exportExcel" icon="md-download">导出</Button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="search-wrap" v-show="search.show">
|
||||
<ul class="handle-wraper">
|
||||
<li class="handle-item w-250">
|
||||
<AutoComplete @on-search="handleCompleteCompanies" icon="ios-search" placeholder="企业名称" v-model.trim="options.company_name">
|
||||
<Option :key="item.id" :value="item.name" v-for="item in completeHandledCompanies">{{ item.name }}</Option>
|
||||
</AutoComplete>
|
||||
</li>
|
||||
|
||||
<li class="handle-item w-250">
|
||||
<AutoComplete @on-search="handleCompletePackages" icon="ios-search" placeholder="套餐名称" v-model.trim="params.package_name">
|
||||
<Option :key="item.id" :value="item.name" v-for="item in completeHandledPackages">{{ item.name }}</Option>
|
||||
</AutoComplete>
|
||||
</li>
|
||||
|
||||
<li class="handle-item w-250">
|
||||
<Select clearable placeholder="支付方式" v-model="params.pay_channel">
|
||||
<Option :value="'bank'">银行转账</Option>
|
||||
<Option :value="'wx'">微信</Option>
|
||||
<Option :value="'alipay'">支付宝</Option>
|
||||
</Select>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="handle-wraper">
|
||||
<li class="handle-item w-250">
|
||||
<DatePicker :editable="false" placeholder="请选择时间" placement="bottom-start" type="daterange" v-model.trim="options.time"></DatePicker>
|
||||
</li>
|
||||
|
||||
<li class="f-r">
|
||||
<div class="handle-item">
|
||||
<Button @click="index(1)" ghost type="primary">立即搜索</Button>
|
||||
</div>
|
||||
<div class="handle-item">
|
||||
<Button @click="resetSearch" ghost type="warning">重置搜索</Button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-list-wrap">
|
||||
<Table :columns="columns" :data="data" :height="page.limit > 12 ? 610 : ''" ref="table" stripe>
|
||||
<template class="table-footer" slot="footer">
|
||||
<colgroup class="table-footer-colgroup"></colgroup>
|
||||
<thead class="ivu-table">
|
||||
<tr>
|
||||
<th>
|
||||
<div class="ivu-table-cell">总计</div>
|
||||
</th>
|
||||
<th>
|
||||
<div class="ivu-table-cell"></div>
|
||||
</th>
|
||||
<th>
|
||||
<div class="ivu-table-cell"></div>
|
||||
</th>
|
||||
<th>
|
||||
<div class="ivu-table-cell"></div>
|
||||
</th>
|
||||
<th>
|
||||
<div class="ivu-table-cell">{{stats.counts}}</div>
|
||||
</th>
|
||||
<th>
|
||||
<div class="ivu-table-cell">{{stats.custom_price}}</div>
|
||||
</th>
|
||||
<th rowspan="1" v-if="page.limit > 12"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
</template>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
<div class="page-turn-wrap">
|
||||
<Page
|
||||
:current="Number(page.page)"
|
||||
:page-size="Number(page.limit)"
|
||||
:page-size-opts="[10, 20, 100, Infinity]"
|
||||
:total="Number(page.total)"
|
||||
@on-change="changePage"
|
||||
@on-page-size-change="changeLimit"
|
||||
show-elevator
|
||||
show-sizer
|
||||
show-total
|
||||
></Page>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./js/index.js"></script>
|
162
frontend/src/views/stats/order/js/index.js
Normal file
162
frontend/src/views/stats/order/js/index.js
Normal file
@ -0,0 +1,162 @@
|
||||
import { sumBy } from 'service/util';
|
||||
export default {
|
||||
name: 'StatsOrder',
|
||||
data() {
|
||||
return {
|
||||
search: {
|
||||
show: true
|
||||
},
|
||||
options: {
|
||||
company_name: null,
|
||||
package_name: null,
|
||||
pay_channel: null,
|
||||
time: null
|
||||
},
|
||||
data: [],
|
||||
list: [],
|
||||
stats: {},
|
||||
page: {
|
||||
total: 0,
|
||||
limit: 10,
|
||||
page: 1
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
title: '企业名称',
|
||||
key: 'company_name'
|
||||
},
|
||||
{
|
||||
title: '套餐名称',
|
||||
key: 'package_name',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '支付方式',
|
||||
key: 'pay_channel_name',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '销售单价',
|
||||
key: 'unit_price',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '销售数量',
|
||||
key: 'counts',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '销售总金额',
|
||||
key: 'custom_price',
|
||||
width: 120
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.type = Number(this.$route.params.type);
|
||||
this.index();
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* [index 列表]
|
||||
* @param {Number} page [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
index() {
|
||||
let options = Object.assign({
|
||||
orderBy: 'company_id',
|
||||
sortedBy: 'asc',
|
||||
type: this.type
|
||||
},
|
||||
this.options);
|
||||
|
||||
let params = this.searchDataHandle({}, {
|
||||
limit: 0
|
||||
}, options);
|
||||
|
||||
this.isShowLoading(true);
|
||||
|
||||
service.get('api/stats/order', { params }).then(res => {
|
||||
this.isShowLoading(false);
|
||||
if (res.code == 0) {
|
||||
this.list = res.data;
|
||||
this.page.total = this.list.length;
|
||||
this.changePage(1);
|
||||
}
|
||||
}).catch(() => {
|
||||
this.isShowLoading(false);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* [request 刷新]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
request() {
|
||||
let page = this.page.page;
|
||||
|
||||
if (this.data.length == 1) {
|
||||
page = this.returnPage(this.page.total, this.page.page, this.page.limit);
|
||||
}
|
||||
|
||||
this.index();
|
||||
this.changePage(page);
|
||||
},
|
||||
|
||||
resetSearch() {
|
||||
for (let k in this.options) {
|
||||
this.options[k] = null;
|
||||
}
|
||||
|
||||
this.index();
|
||||
},
|
||||
changeLimit(limit) {
|
||||
this.page.limit = limit;
|
||||
this.changePage(1);
|
||||
},
|
||||
changePage(page) {
|
||||
this.page.page = page;
|
||||
this.data = this.list.slice((page - 1) * this.page.limit, page * this.page.limit);
|
||||
|
||||
this.stats = {
|
||||
counts: sumBy(this.list, 'counts'),
|
||||
custom_price: sumBy(this.list, 'custom_price')
|
||||
};
|
||||
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
let html = $('.ivu-table-header colgroup').html();
|
||||
$('.table-footer-colgroup').html(html);
|
||||
}, 10);
|
||||
});
|
||||
},
|
||||
|
||||
exportExcel() {
|
||||
this.isShowLoading(true);
|
||||
|
||||
let options = Object.assign({
|
||||
orderBy: 'id',
|
||||
sortedBy: 'asc'
|
||||
},
|
||||
|
||||
this.options);
|
||||
|
||||
let params = this.searchDataHandle({}, {}, options);
|
||||
|
||||
this.isShowLoading(true);
|
||||
|
||||
service.get('api/stats/company-count/export', {
|
||||
params
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.downloadFile(res.data);
|
||||
}
|
||||
|
||||
this.isShowLoading(false);
|
||||
}).catch(() => {
|
||||
this.isShowLoading(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
@ -1,25 +1,10 @@
|
||||
<?php
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
require_once realpath(dirname(__FILE__) . '/TestCase.php');
|
||||
$date = new DateTime('2018-10-31');
|
||||
$date->modify('-1 month');
|
||||
echo $date->format('Y-m-d');
|
||||
|
||||
$res = Carbon::parse('2018-10')->endOfMonth()->subMonth();
|
||||
$count = DB::connection('mongo')->table('tblCard')
|
||||
->count();
|
||||
|
||||
dd($res);
|
||||
|
||||
$conditions = [
|
||||
'starttime' => Carbon::parse('2018-10-01')->startOfDay(),
|
||||
'endtime' => Carbon::parse('2018-10-31')->startOfDay(),
|
||||
];
|
||||
|
||||
$res = \DB::connection('mongo')->table('tblCard')->where(function ($query) use ($conditions) {
|
||||
$query->where('exPCodes.cDate', '>=', $conditions['starttime'])->where('exPCodes.cDate', '<=', $conditions['endtime'])->where('oDate', 'exists', false);
|
||||
})->orWhere(function ($query) use ($conditions) {
|
||||
$query->where('exPCodes.oDate', '>=', $conditions['starttime'])->where('exPCodes.oDate', '<=', $conditions['endtime'])->where('pType', 0);
|
||||
})->first();
|
||||
|
||||
dd($res['exPCodes']);
|
||||
dd($count);
|
||||
|
Loading…
x
Reference in New Issue
Block a user