This commit is contained in:
邓皓元 2019-03-19 15:54:40 +08:00
parent e325d501b7
commit 5e59e5bb03
33 changed files with 267 additions and 67 deletions

View File

@ -24,6 +24,7 @@ abstract class AbstractExport implements WithEvents, WithTitle, ShouldAutoSize
\App\Domains\Virtual\Exports\CardExport::class => '客户列表',
\App\Domains\Virtual\Exports\FlowPoolExport::class => '流量池列表',
\App\Domains\Virtual\Exports\FlowPoolExportDetailExport::class => '流量池明细',
\App\Domains\Virtual\Exports\OrderCardExport::class => '订单卡清单',
\App\Domains\Stats\Exports\CompanyCountExport::class => '企业统计',
\App\Domains\Stats\Exports\OrderExport::class => '订单统计',
\App\Domains\Stats\Exports\OrderDetailExport::class => '订单明细',

View File

@ -6,6 +6,7 @@ use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use App\Domains\Virtual\Repositories\OrderCardPartitionRepository;
use App\Domains\Virtual\Services\PackageService;
use App\Domains\Virtual\Services\ProductService;
class CardController extends Controller
{
@ -44,7 +45,8 @@ class CardController extends Controller
->whereIn('sim', $cards->pluck('sim')->toArray())->groupBy('sim')->get()->keyBy('sim');
$time = Carbon::now()->format('Y-m-d H:i:s');
$packages = $this->orderCardPartitionRepository->selectRaw('distinct on (sim) sim, package_id')
$packages = $this->orderCardPartitionRepository->selectRaw('distinct on (sim) sim, package_id, product_id')
->whereIn('type', $conditions['type'])
->whereIn('sim', $cards->pluck('sim')->toArray())
->where('service_start_at', '<=', $time)->orderBy('sim')->orderBy('service_start_at', 'desc')
->get()->keyBy('sim');
@ -52,8 +54,11 @@ class CardController extends Controller
$cards->map(function ($item) use ($services, $packages) {
$item->service_start_at = $services[$item->sim]['service_start_at'] ?? '';
$item->service_end_at = $services[$item->sim]['service_end_at'] ?? '';
$item->product_id = $packages[$item->sim]['product_id'] ?? 0;
$item->package_id = $packages[$item->sim]['package_id'] ?? 0;
$item->package_name = PackageService::load($item->package_id)['name'] ?? '';
$item->price = ProductService::load($item->product_id)['price'] ?? 0;
$item->renew_price = ProductService::load($item->product_id)['renew_price'] ?? 0;
});
return res($cards, '卡列表', 201);

View File

@ -55,6 +55,7 @@ class ProductSync extends Command
'package_id' => $package['id'],
'name' => $package['name'] . ' ' . $value['order_account'],
'price' => $price,
'renew_price' => $price,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
'deleted_at' => null,

View File

@ -0,0 +1,52 @@
<?php
namespace App\Domains\Virtual\Exports;
use App\Core\AbstractExport;
use Illuminate\Support\Facades\DB;
use Dipper\Excel\Concerns\WithRows;
use Dipper\Excel\Concerns\FromQuery;
use Dipper\Excel\Concerns\WithHeadings;
use Illuminate\Database\Eloquent\Collection;
use App\Domains\Virtual\Services\CardService;
use Dipper\Excel\Concerns\WithColumnFormatting;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use App\Domains\Virtual\Repositories\OrderCardPartitionRepository;
class OrderCardExport extends AbstractExport implements FromQuery, WithHeadings, WithColumnFormatting
{
public $conditions;
public function __construct(array $conditions = [])
{
$this->conditions = $conditions;
parent::__construct();
}
public function query()
{
$builder = app(OrderCardPartitionRepository::class)->forceNoReset()->select(['sim', 'counts'])
->withConditions($this->conditions)->orderBy('sim');
return $builder;
}
public function headings(): array
{
return [
'SIM',
'数量',
];
}
/**
* @return array
*/
public function columnFormats(): array
{
return [
'A' => NumberFormat::FORMAT_NUMBER_00,
'B' => NumberFormat::FORMAT_NUMBER,
];
}
}

View File

@ -6,8 +6,10 @@ use App\Core\Controller;
use Illuminate\Http\Request;
use App\Exceptions\NotExistException;
use App\Domains\Config\Services\ConfigService;
use App\Domains\Export\Services\ExportService;
use App\Domains\Virtual\Services\OrderService;
use App\Domains\Virtual\Services\CommonService;
use App\Domains\Virtual\Exports\OrderCardExport;
use App\Domains\Virtual\Services\CompanyService;
use App\Domains\Virtual\Services\PackageService;
use App\Domains\Virtual\Repositories\OrderRepository;
@ -179,4 +181,23 @@ class OrderController extends Controller
return res($cards, '卡清单');
}
/**
* 导出卡清单.
*
* @return \Illuminate\Http\Response
*/
public function cardsExport()
{
$conditions = $this->request->all();
try {
$export = new OrderCardExport($conditions);
$url = ExportService::store($export, 'public');
} catch (\Exception $e) {
throw $e;
}
return res($url, '导出成功', 201);
}
}

View File

@ -50,6 +50,7 @@ $router->group(['prefix' => 'virtual', 'as' => 'virtual', 'middleware' => ['admi
$router->post('/orders/destroy', ['as' => 'orders.destroy', 'uses' => 'OrderController@destroy']);
$router->post('/orders/reset', ['as' => 'orders.reset', 'uses' => 'OrderController@reset']);
$router->get('/orders/cards', ['as' => 'orders.cards', 'uses' => 'OrderController@cards']);
$router->get('/orders/cards-export', ['as' => 'orders.cardsExport', 'uses' => 'OrderController@cardsExport']);
// 客户管理
$router->get('/cards/index', ['as' => 'cards.index', 'uses' => 'CardController@index']);

View File

@ -167,9 +167,6 @@ class OrderService extends Service
DB::beginTransaction();
if ($attributes['type'] !== 1 && $attributes['selected']) {
}
if (isset($attributes['sign']) && $attributes['sign'] == 2) {
if (empty($attributes['selected'])) {
throw new InvalidArgumentException('请选择卡');
@ -193,22 +190,49 @@ class OrderService extends Service
$sql = sprintf($sql, app(Grammar::class)->parameterize($params));
array_unshift($params, $attributes['order_at']);
DB::update($sql, $params);
$attributes['type'] = 0;
}
$originType = $attributes['type'];
if (!$attributes['id']) {
if ($product->company_id != $attributes['company_id']) {
throw new NotAllowedException('非法操作');
// 销售订单,如果单卡使用多次,仅第一次为销售,其他改续费。
$extras = [];
$selected = $attributes['selected'];
$attributes['counts'] = count($selected);
foreach ($selected as &$card) {
if ($card['counts'] > 1) {
array_push($extras, [
'sim' => $card['sim'],
'counts' => $card['counts'] - 1,
]);
$card['counts'] = 1;
}
}
$attributes['price'] = $product->price;
$attributes['total_price'] = $attributes['unit_price'] * $attributes['counts'];
$attributes['custom_price'] = $attributes['unit_price'] * $attributes['counts'];
$attributes['order_at'] = $attributes['order_at'] ?? date('Y-m-d H:i:s');
$attributes['package_id'] = $attributes['package_id'] ?? $product->package_id;
$attributes['selected'] = $selected;
$node = $this->orderRepository->create($attributes);
if (!empty($extras)) {
$extraOrderData = $attributes;
$extraOrderData['type'] = $originType;
$extraOrderData['counts'] = array_sum(array_pluck($extras, 'counts'));
$extraOrderData['total_price'] = $attributes['unit_price'] * $extraOrderData['counts'];
$extraOrderData['custom_price'] = $attributes['unit_price'] * $extraOrderData['counts'];
$extraOrder = $this->orderRepository->create($attributes);
$this->upsertOrderCards($extras, $extraOrder);
}
if (!$attributes['id']) {
if ($product->company_id != $attributes['company_id']) {
throw new NotAllowedException('非法操作');
}
$attributes['price'] = $product->price;
$attributes['total_price'] = $attributes['unit_price'] * $attributes['counts'];
$attributes['custom_price'] = $attributes['unit_price'] * $attributes['counts'];
$attributes['order_at'] = $attributes['order_at'] ?? date('Y-m-d H:i:s');
$attributes['package_id'] = $attributes['package_id'] ?? $product->package_id;
$node = $this->orderRepository->create($attributes);
}
}
if ($attributes['id']) {
@ -225,40 +249,7 @@ class OrderService extends Service
if ($attributes['selected']) {
try {
$table = $this->tables[$node['type']];
$cards = $attributes['selected'];
$data = [];
foreach ($cards as $card) {
$data[] = [
'sim' => $card['sim'],
'counts' => $card['counts'],
'type' => $node['type'],
'order_id' => $node['id'],
'company_id' => $node['company_id'],
'package_id' => $node['package_id'],
'product_id' => $node['product_id'],
'unit_price' => $node['unit_price'],
'created_at' => $node['order_at'],
'updated_at' => date('Y-m-d H:i:s'),
];
}
if (!empty($data)) {
$array = array_chunk($data, 10000);
foreach ($array as $value) {
DB::table($table)->upsert($value, ['sim', 'order_id', 'deleted_at']);
$simArray = implode(',', array_pluck($value, 'sim'));
DB::statement("select fix_timelines('{{$simArray}}'::INT8[]);");
RealOrderCardPartition::whereIn('order_id', array_pluck($attributes['selected'], 'order_id'))
->whereIn('sim', array_pluck($value, 'sim'))->update(['virtual_order_id' => $node['id']]);
}
}
$this->upsertOrderCards($attributes['selected'], $node);
$this->orderRepository->forgetCached();
$this->orderCardPartitionRepository->forgetCached();
app(RealOrderCardPartitionRepository::class)->forgetCached();
@ -278,6 +269,41 @@ class OrderService extends Service
return $node;
}
protected function upsertOrderCards($array, $node)
{
$table = $this->tables[$node['type']];
$data = [];
foreach ($array as $card) {
$data[] = [
'sim' => $card['sim'],
'counts' => $card['counts'],
'type' => $node['type'],
'order_id' => $node['id'],
'company_id' => $node['company_id'],
'package_id' => $node['package_id'],
'product_id' => $node['product_id'],
'unit_price' => $node['unit_price'],
'created_at' => $node['order_at'],
'updated_at' => date('Y-m-d H:i:s'),
];
}
if (empty($data)) {
return;
}
$array = array_chunk($data, 10000);
foreach ($array as $value) {
DB::table($table)->upsert($value, ['sim', 'order_id', 'deleted_at']);
$simArray = implode(',', array_pluck($value, 'sim'));
DB::statement("select fix_timelines('{{$simArray}}'::INT8[]);");
RealOrderCardPartition::whereIn('order_id', array_pluck($array, 'order_id'))->whereIn('sim', array_pluck($value, 'sim'))->update(['virtual_order_id' => $node['id']]);
}
}
/**
* 以卡续费/续费包/加油包
*
@ -633,7 +659,9 @@ class OrderService extends Service
{
$conditions['limit'] = $conditions['limit'] ?? 20;
$cards = $this->orderCardPartitionRepository->select(['sim'])->withConditions($conditions)->orderBy('sim')->paginate($conditions['limit']);
$cards = $this->orderCardPartitionRepository->select(['sim', 'counts'])
->withConditions($conditions)->orderBy('sim')
->paginate($conditions['limit']);
return $cards;
}

View File

@ -49,6 +49,7 @@ class ProductService extends Service
$item->company = CompanyService::load($item->company_id);
$item->package = PackageService::load($item->package_id);
$item->price = sprintf('%.02f', $item->price/100);
$item->renew_price = sprintf('%.02f', $item->renew_price/100);
$item->status = $item['package']['status'] ? 1 : $item->status;
$item->carrier_operator = $item['package']['carrier_operator'];
$item->carrier_operator_name = $carrierOperators[$item->carrier_operator] ?? '未知';
@ -66,6 +67,7 @@ class ProductService extends Service
public function store(array $attributes = [])
{
$attributes['price'] = intval($attributes['price'] * 100);
$attributes['renew_price'] = intval($attributes['renew_price'] * 100);
$rule = [
'name' => ['required', 'between:2,32', Rule::unique($this->productRepository->getTable(), 'name')->ignore($attributes['id'])->whereNUll('deleted_at')->where('company_id', $attributes['company_id'])],
@ -145,7 +147,7 @@ class ProductService extends Service
public static function load($id)
{
if (!self::$products) {
self::$products = app(ProductRepository::class)->select(['id', 'type', 'name', 'company_id', 'package_id', 'price', 'status'])
self::$products = app(ProductRepository::class)->select(['id', 'type', 'name', 'company_id', 'package_id', 'price', 'renew_price', 'status'])
->withTrashed()->get()->keyBy('id');
}
@ -179,6 +181,7 @@ class ProductService extends Service
'company_id' => $companyId,
'package_id' => $package['id'],
'price' => $price/100,
'renew_price' => $price/100,
]);
}

View File

@ -25,6 +25,7 @@ class CreateVirtualProductsTable extends Migration
$table->integer('company_id')->unsigned()->default(0)->comment('企业ID');
$table->integer('package_id')->unsigned()->default(0)->comment('套餐ID');
$table->integer('price')->unsigned()->default(0)->comment('价格');
$table->integer('renew_price')->unsigned()->default(0)->comment('续费价格');
$table->text('remark')->nullable()->comment('备注');
$table->tinyInteger('flowed')->unsigned()->default(0)->comment('是否是后向流量池套餐 0:否 1:是');
$table->tinyInteger('status')->unsigned()->default(0)->comment('状态 0:正常 1:禁用');

View File

@ -32,6 +32,17 @@ export function cards(data) {
params: data
});
}
/**
* [cardsExport 卡清单列表]
* @param {[type]} data [description]
* @return {[type]} [description]
*/
export function cardsExport(data) {
return service.get('api/virtual/orders/cards-export', {
params: data
});
}
/**
* [create 创建订单]
* @param {[type]} data [description]

View File

@ -147,8 +147,14 @@
</li>
</ul>
<Divider>出库卡清单</Divider>
<Divider>
<span class="umar-r10">出库卡清单</span>
<Button @click="exportExcel" icon="md-download">导出</Button>
</Divider>
<Row class="ta-r"></Row>
<Table
class="umar-t10"
:columns="columns"
:data="cards"
:loading="loading"
@ -162,7 +168,7 @@
<Page
:current="Number(page.page)"
:page-size="Number(page.limit)"
:page-size-opts="[15, 30, 60, 90]"
:page-size-opts="[10, 20, 50, 100]"
:total="Number(page.total)"
@on-change="changePage"
@on-page-size-change="changeLimit"
@ -175,3 +181,10 @@
</template>
<script src="./js/detail.js"></script>
<style scoped>
>>> .ivu-table {
font-size: 11px;
}
</style>

View File

@ -399,6 +399,7 @@ export default {
this.$store.commit('SET_RELATION_OBJ', {});
},
clear() {
this.showCards = [];
this.$store.dispatch('initOrder');
},
clearSelect() {

View File

@ -8,7 +8,7 @@ export default {
},
data: {
type: Object,
default() {
default () {
return null;
}
}
@ -29,7 +29,7 @@ export default {
page: {
total: 0,
page: 1,
limit: 15
limit: 10
},
columns: [
{
@ -37,14 +37,21 @@ export default {
key: "column1",
align: 'center'
},
{
title: "数量",
key: "counts1",
width: 75,
align: 'center'
},
{
title: "SIM卡号",
key: "column2",
align: 'center'
},
{
title: "SIM卡号",
key: "column3",
title: "数量",
key: "counts2",
width: 75,
align: 'center'
}
],
@ -69,11 +76,12 @@ export default {
let array = [];
for (let index = 0; index < cards.length; index = index + 3) {
for (let index = 0; index < cards.length; index = index + 2) {
array.push({
column1: cards[index] ? cards[index]['sim'] : '',
counts1: cards[index] ? cards[index]['counts'] : '',
column2: cards[index + 1] ? cards[index + 1]['sim'] : '',
column3: cards[index + 2] ? cards[index + 2]['sim'] : ''
counts2: cards[index + 1] ? cards[index + 1]['counts'] : ''
});
}
@ -91,6 +99,24 @@ export default {
},
visibleChange(bool) {
this.$emit('update:show', bool);
},
exportExcel() {
API.cardsExport({ order_id: this.data.id }).then(res => {
this.isShowLoading(false);
if (res.code === 0) {
if (res.data) {
this.downloadFile(res.data);
} else {
this.$Modal.success({
title: '提示',
content: '当前导出数据量大,已进入后台队列导出模式,请稍后至导出列表查看下载。'
});
}
}
}).catch(() => {
this.isShowLoading(false);
});
}
}
};

View File

@ -138,12 +138,10 @@ export default {
if (this.groupIndex === '0_0') {
// 卡不在VD上转销售
this.params.type = 0;
this.params.sign = 1;
this.post();
} else if (this.params.company_id !== this.group[0].company_id) {
// 改企业的
this.params.type = 0;
this.params.sign = 2;
this.$Modal.confirm({
title: '提示',

View File

@ -49,6 +49,20 @@
</div>
</li>
<li class="ui-list">
<div class="ui-list-title">续费价格</div>
<div class="ui-list-content">
<InputNumber
:active-change="false"
:max="100000"
:min="0"
:precision="2"
:step="0.1"
v-model.trim="params.renew_price"
></InputNumber>
</div>
</li>
<li class="ui-list" v-if="[0, 2].indexOf(type) !== -1">
<div class="ui-list-title">后向套餐</div>
<div class="ui-list-content">

View File

@ -32,6 +32,7 @@ export default {
package_id: '',
flowed: 0,
price: 0,
renew_price: 0,
remark: '',
status: 0
},
@ -115,7 +116,7 @@ export default {
},
clear() {
for (let k in this.params) {
if (k === 'price' || k === 'status' || k === 'flowed') {
if (k === 'price' || k === 'status' || k === 'flowed' || k === 'renew_price') {
this.params[k] = 0;
} else {
this.params[k] = '';

View File

@ -88,6 +88,7 @@ export default {
index
}) => {
row.price = Number(row.price);
row.renew_price = Number(row.renew_price);
let html = [];

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=\favicon.ico><script src=\config.js></script><title></title><link href=/css/chunk-3e2248ef.ced8e72d.css rel=prefetch><link href=/css/chunk-4020ddf0.e734d292.css rel=prefetch><link href=/js/chunk-00ae0766.3874cd10.js rel=prefetch><link href=/js/chunk-07a274ec.c3ad5dec.js rel=prefetch><link href=/js/chunk-3e2248ef.43fc323a.js rel=prefetch><link href=/js/chunk-4020ddf0.fd15bdb4.js rel=prefetch><link href=/css/app.d71a8195.css rel=preload as=style><link href=/css/chunk-vendors.3c3b2e85.css rel=preload as=style><link href=/js/app.13976fcc.js rel=preload as=script><link href=/js/chunk-vendors.ed6443e8.js rel=preload as=script><link href=/css/chunk-vendors.3c3b2e85.css rel=stylesheet><link href=/css/app.d71a8195.css rel=stylesheet></head><body><noscript><strong>很抱歉如果没有启用JavaScript程序不能正常工作若要继续使用请启用它。</strong></noscript><div id=app></div><script src=/js/chunk-vendors.ed6443e8.js></script><script src=/js/app.13976fcc.js></script></body></html>
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=\favicon.ico><script src=\config.js></script><title></title><link href=/css/chunk-3af5359e.df1b8b95.css rel=prefetch><link href=/css/chunk-3e2248ef.ced8e72d.css rel=prefetch><link href=/js/chunk-00ae0766.3874cd10.js rel=prefetch><link href=/js/chunk-07a274ec.c3ad5dec.js rel=prefetch><link href=/js/chunk-3af5359e.b176685e.js rel=prefetch><link href=/js/chunk-3e2248ef.43fc323a.js rel=prefetch><link href=/css/app.d71a8195.css rel=preload as=style><link href=/css/chunk-vendors.3c3b2e85.css rel=preload as=style><link href=/js/app.4743bbbb.js rel=preload as=script><link href=/js/chunk-vendors.ed6443e8.js rel=preload as=script><link href=/css/chunk-vendors.3c3b2e85.css rel=stylesheet><link href=/css/app.d71a8195.css rel=stylesheet></head><body><noscript><strong>很抱歉如果没有启用JavaScript程序不能正常工作若要继续使用请启用它。</strong></noscript><div id=app></div><script src=/js/chunk-vendors.ed6443e8.js></script><script src=/js/app.4743bbbb.js></script></body></html>

View File

@ -1,9 +1,9 @@
<?php
use App\Models\Virtual\Product;
use Illuminate\Support\Facades\Schema;
require_once realpath(dirname(__FILE__) . '/TestCase.php');
$subSql = 'SELECT DISTINCT ON (company_id, package_id) id FROM virtual_products ORDER BY company_id, package_id, updated_at DESC';
Product::whereRaw("id not in ($subSql)")->update(['status' => 1]);
Schema::table('virtual_products', function ($table) {
$table->integer('renew_price')->unsigned()->default(0)->comment('续费价格');
});