同步优化
This commit is contained in:
parent
67c170ed44
commit
ed04a81983
@ -50,10 +50,10 @@ class MongoSync extends Command
|
|||||||
$jobs->push(new MongoSyncJob($page, $this->limit, $utcDateTime));
|
$jobs->push(new MongoSyncJob($page, $this->limit, $utcDateTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
app(ConfigService::class)->set(self::CURSOR_KEY, intval($nextMicrotime));
|
|
||||||
|
|
||||||
$total && MongoSyncJob::withChain($jobs->toArray())
|
$total && MongoSyncJob::withChain($jobs->toArray())
|
||||||
->dispatch(1, $this->limit, $utcDateTime)
|
->dispatch(1, $this->limit, $utcDateTime)
|
||||||
->allOnQueue('sync');
|
->allOnQueue('sync');
|
||||||
|
|
||||||
|
app(ConfigService::class)->set(self::CURSOR_KEY, intval($nextMicrotime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,10 +53,10 @@ class CardSync extends Command
|
|||||||
$jobs->push(new CardSyncJob($page, $this->limit, $maxId));
|
$jobs->push(new CardSyncJob($page, $this->limit, $maxId));
|
||||||
}
|
}
|
||||||
|
|
||||||
$nextId && app(ConfigService::class)->set(self::CURSOR_KEY, $nextId);
|
|
||||||
|
|
||||||
$total && CardSyncJob::withChain($jobs->toArray())
|
$total && CardSyncJob::withChain($jobs->toArray())
|
||||||
->dispatch(1, $this->limit, $maxId)
|
->dispatch(1, $this->limit, $maxId)
|
||||||
->allOnQueue('sync');
|
->allOnQueue('sync');
|
||||||
|
|
||||||
|
$nextId && app(ConfigService::class)->set(self::CURSOR_KEY, $nextId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,10 @@ class CompanySync extends Command
|
|||||||
$item['updated_at'] = date('Y-m-d H:i:s', $item['updated_at']);
|
$item['updated_at'] = date('Y-m-d H:i:s', $item['updated_at']);
|
||||||
$item['deleted_at'] = $item['del'] ? $item['updated_at'] : null;
|
$item['deleted_at'] = $item['del'] ? $item['updated_at'] : null;
|
||||||
unset($item['del']);
|
unset($item['del']);
|
||||||
|
unset($item['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
Company::upsert($data, 'id');
|
Company::upsert($data, ['sn', 'deleted_at']);
|
||||||
|
|
||||||
app(CompanyRepository::class)->forgetCached();
|
app(CompanyRepository::class)->forgetCached();
|
||||||
}
|
}
|
||||||
|
@ -59,10 +59,10 @@ class LogSync extends Command
|
|||||||
$jobs->push(new LogSyncJob($page, $this->limit, $maxId));
|
$jobs->push(new LogSyncJob($page, $this->limit, $maxId));
|
||||||
}
|
}
|
||||||
|
|
||||||
$nextId && app(ConfigService::class)->set(self::CURSOR_KEY, $nextId);
|
|
||||||
|
|
||||||
$total && LogSyncJob::withChain($jobs->toArray())
|
$total && LogSyncJob::withChain($jobs->toArray())
|
||||||
->dispatch(1, $this->limit, $maxId)
|
->dispatch(1, $this->limit, $maxId)
|
||||||
->allOnQueue('sync');
|
->allOnQueue('sync');
|
||||||
|
|
||||||
|
$nextId && app(ConfigService::class)->set(self::CURSOR_KEY, $nextId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ class CardSyncJob implements ShouldQueue
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$blocs = app(BlocRepository::class)->get()->pluck('id', 'shorthand')->toArray();
|
$blocs = app(BlocRepository::class)->withTrashed()->get()->pluck('id', 'shorthand')->toArray();
|
||||||
|
|
||||||
$query = DB::connection('vd_old')->table('ckb_custom')
|
$query = DB::connection('vd_old')->table('ckb_custom')
|
||||||
->select(['id', 'custom_no', 'imsi', 'carrieroperator', 'iccid', 'card_number', 'card_from', 'iccid', 'company', 'custom_state', 'create_time' ,'update_time', 'card_cycle_start'])
|
->select(['id', 'custom_no', 'imsi', 'carrieroperator', 'iccid', 'card_number', 'card_from', 'iccid', 'company', 'custom_state', 'create_time' ,'update_time', 'card_cycle_start'])
|
||||||
|
@ -11,13 +11,16 @@ use Illuminate\Support\Facades\DB;
|
|||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Dipper\Foundation\Bus\Dispatchable;
|
use Dipper\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
use App\Models\Virtual\OrderCardPartition;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use App\Domains\Config\Services\ConfigService;
|
use App\Domains\Config\Services\ConfigService;
|
||||||
use App\Domains\Virtual\Commands\Sync\LogSync;
|
use App\Domains\Virtual\Commands\Sync\LogSync;
|
||||||
|
use App\Domains\Virtual\Services\CommonService;
|
||||||
use App\Domains\Virtual\Services\ProductService;
|
use App\Domains\Virtual\Services\ProductService;
|
||||||
use App\Domains\Card\Repositories\BlocRepository;
|
use App\Domains\Card\Repositories\BlocRepository;
|
||||||
use App\Domains\Card\Repositories\CardRepository;
|
use App\Domains\Card\Repositories\CardRepository;
|
||||||
use App\Domains\Virtual\Repositories\OrderRepository;
|
use App\Domains\Virtual\Repositories\OrderRepository;
|
||||||
|
use App\Domains\Virtual\Repositories\CompanyRepository;
|
||||||
use App\Domains\Virtual\Repositories\PackageRepository;
|
use App\Domains\Virtual\Repositories\PackageRepository;
|
||||||
use App\Domains\Virtual\Repositories\ProductRepository;
|
use App\Domains\Virtual\Repositories\ProductRepository;
|
||||||
use App\Domains\Virtual\Repositories\OrderCardRepository;
|
use App\Domains\Virtual\Repositories\OrderCardRepository;
|
||||||
@ -34,21 +37,14 @@ class LogSyncJob implements ShouldQueue
|
|||||||
public $limit;
|
public $limit;
|
||||||
public $maxId;
|
public $maxId;
|
||||||
|
|
||||||
protected $blocs;
|
|
||||||
protected $packages;
|
protected $packages;
|
||||||
protected $products;
|
protected $products;
|
||||||
|
protected $companies;
|
||||||
|
|
||||||
public static $types = [11 => 1, 13 => 0, 14 => 2, 15 => 3];
|
public static $types = [11 => 1, 13 => 0, 14 => 2, 15 => 3];
|
||||||
protected static $carrierOperators = [10 => 0, 11 => 1, 12 => 2];
|
protected static $carrierOperators = [10 => 0, 11 => 1, 12 => 2];
|
||||||
protected static $payChannels = [10 => 'wx', 11 => 'alipay', 12 => 'bank'];
|
protected static $payChannels = [10 => 'wx', 11 => 'alipay', 12 => 'bank'];
|
||||||
|
|
||||||
protected static $orderClasses = [
|
|
||||||
\App\Models\Virtual\OrderCard::class,
|
|
||||||
\App\Models\Virtual\OrderRenewalCard::class,
|
|
||||||
\App\Models\Virtual\OrderRenewalPackageCard::class,
|
|
||||||
\App\Models\Virtual\OrderFlowPackageCards::class,
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undocumented function
|
* Undocumented function
|
||||||
*
|
*
|
||||||
@ -68,8 +64,9 @@ class LogSyncJob implements ShouldQueue
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->packages = app(PackageRepository::class)->get()->keyBy('sn');
|
$this->packages = app(PackageRepository::class)->withTrashed()->get()->keyBy('sn');
|
||||||
$this->products = app(ProductRepository::class)->get()->keyBy('sn');
|
$this->products = app(ProductRepository::class)->withTrashed()->get()->keyBy('sn');
|
||||||
|
$this->companies = app(CompanyRepository::class)->withTrashed()->get()->keyBy('sn');
|
||||||
|
|
||||||
$query = DB::connection('vd_old')->table('logs')->whereIn('type', array_keys(self::$types))
|
$query = DB::connection('vd_old')->table('logs')->whereIn('type', array_keys(self::$types))
|
||||||
->where('id', '>', $this->maxId)->orderBy('id');
|
->where('id', '>', $this->maxId)->orderBy('id');
|
||||||
@ -82,11 +79,14 @@ class LogSyncJob implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
DB::beginTransaction();
|
DB::beginTransaction();
|
||||||
|
$orderArray = [];
|
||||||
|
$relationArray = [];
|
||||||
|
|
||||||
foreach ($res as $key => $value) {
|
foreach ($res as $key => $value) {
|
||||||
$value = (array)$value;
|
$value = (array)$value;
|
||||||
|
|
||||||
$package = $this->getPackage($value['content']);
|
$package = $this->getPackage($value['content']);
|
||||||
|
$company = $this->getCompany(CommonService::stringifyCompanyId($value['company']));
|
||||||
$unit_price = intval($value['order_account'] * 100);
|
$unit_price = intval($value['order_account'] * 100);
|
||||||
$custom_price = intval($value['order_account'] * 100);
|
$custom_price = intval($value['order_account'] * 100);
|
||||||
$product = $this->getProduct($package, $value['company'], $unit_price);
|
$product = $this->getProduct($package, $value['company'], $unit_price);
|
||||||
@ -94,13 +94,13 @@ class LogSyncJob implements ShouldQueue
|
|||||||
$pay_channel = self::$payChannels[$value['pay_type']];
|
$pay_channel = self::$payChannels[$value['pay_type']];
|
||||||
|
|
||||||
// 按规则生成订单编号 (月6+类型1+公司3+套餐4+价格6)
|
// 按规则生成订单编号 (月6+类型1+公司3+套餐4+价格6)
|
||||||
$sn = date('Ym', $value['create_time']) . $type . sprintf('%03d', $value['company']) . sprintf('%04d', $package['id']) . sprintf('%06d', $custom_price);
|
$sn = date('Ym', $value['create_time']) . $type . sprintf('%03d', $company['id']) . sprintf('%04d', $package['id']) . sprintf('%06d', $custom_price);
|
||||||
|
|
||||||
$data = [
|
$orderArray[$sn] = [
|
||||||
'sn' => $sn,
|
'sn' => $sn,
|
||||||
'source' => 1,
|
'source' => 1,
|
||||||
'type' => $type,
|
'type' => $type,
|
||||||
'company_id' => $value['company'],
|
'company_id' => $company['id'],
|
||||||
'package_id' => $package['id'],
|
'package_id' => $package['id'],
|
||||||
'product_id' => $product['id'],
|
'product_id' => $product['id'],
|
||||||
'pay_channel' => $pay_channel,
|
'pay_channel' => $pay_channel,
|
||||||
@ -114,43 +114,48 @@ class LogSyncJob implements ShouldQueue
|
|||||||
'created_at' => date('Y-m-d H:i:s', $value['create_time']),
|
'created_at' => date('Y-m-d H:i:s', $value['create_time']),
|
||||||
];
|
];
|
||||||
|
|
||||||
try {
|
$relationArray[] = [
|
||||||
if ($order = Order::where('sn', $data['sn'])->first()) {
|
'order_sn' => $sn,
|
||||||
$order->counts = $order->counts + 1;
|
'type' => $type,
|
||||||
$order->total_price = $order->total_price + $unit_price;
|
'sim' => $value['sim'],
|
||||||
$order->custom_price = $order->custom_price + $custom_price;
|
'company_id' => $company['id'],
|
||||||
$order->save();
|
'package_id' => $package['id'],
|
||||||
} else {
|
'counts' => 1,
|
||||||
$order = Order::create($data);
|
'created_at' => date('Y-m-d H:i:s', $value['create_time']),
|
||||||
}
|
'updated_at' => date('Y-m-d H:i:s'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
$relationData = [
|
try {
|
||||||
'type' => $type,
|
$builder = Order::query()->toBase();
|
||||||
'sim' => $value['sim'],
|
|
||||||
'order_id' => $order->id,
|
|
||||||
'company_id' => $order->company_id,
|
|
||||||
'package_id' => $order->package_id,
|
|
||||||
'counts' => 1,
|
|
||||||
'created_at' => date('Y-m-d H:i:s', $value['create_time']),
|
|
||||||
'updated_at' => date('Y-m-d H:i:s'),
|
|
||||||
];
|
|
||||||
|
|
||||||
$class = (new self::$orderClasses[$type])->query();
|
$sql = $builder->getGrammar()->compileInsert($builder, $orderArray);
|
||||||
|
|
||||||
if ($type) {
|
$sql .= " on conflict (sn, COALESCE(deleted_at, '1970-01-01 08:00:00'::timestamp)) do update set
|
||||||
if ($relation = $class->where('sim', $value['sim'])->where('order_id', $order->id)->first()) {
|
counts=virtual_orders.counts + 1,
|
||||||
$relation->counts = $relation->counts + 1;
|
total_price=virtual_orders.unit_price * (virtual_orders.counts + 1),
|
||||||
$relation->save();
|
custom_price=virtual_orders.unit_price * (virtual_orders.counts + 1)";
|
||||||
} else {
|
|
||||||
$relation = $class->create($relationData);
|
$builder->connection->insert($sql, Arr::flatten($orderArray, 1));
|
||||||
}
|
|
||||||
} else {
|
$orders = Order::withTrashed()->select(['id', 'sn'])->whereIn('sn', array_pluck($orderArray, 'sn'))->get()->pluck('id', 'sn')->toArray();
|
||||||
$relation = $class->upsert($relationData, ['sim', 'order_id', 'deleted_at']);
|
|
||||||
}
|
foreach ($relationArray as $key => $value) {
|
||||||
} catch (\Exception $e) {
|
$relationArray[$key]['order_id'] = $orders[$value['order_sn']];
|
||||||
DB::rollback();
|
unset($relationArray[$key]['order_sn']);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$builder = OrderCardPartition::query()->toBase();
|
||||||
|
|
||||||
|
$sql = $builder->getGrammar()->compileInsert($builder, $relationArray);
|
||||||
|
|
||||||
|
$sql .= " on conflict (type, order_id, sim, COALESCE(deleted_at, '1970-01-01 08:00:00'::timestamp)) do update set
|
||||||
|
counts=virtual_order_cards_partition.counts + 1";
|
||||||
|
|
||||||
|
$builder->connection->insert($sql, Arr::flatten($relationArray, 1));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollback();
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
@ -163,6 +168,21 @@ class LogSyncJob implements ShouldQueue
|
|||||||
app(OrderCardPartitionRepository::class)->forgetCached();
|
app(OrderCardPartitionRepository::class)->forgetCached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取套餐
|
||||||
|
*
|
||||||
|
* @param string $sn
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function getCompany($sn)
|
||||||
|
{
|
||||||
|
if (!$company = $this->companies[$sn]) {
|
||||||
|
throw new \Exception('企业不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $company;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取套餐
|
* 获取套餐
|
||||||
*
|
*
|
||||||
|
@ -73,10 +73,6 @@ trait OrderCardConcern
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isset($conditions['month'])) {
|
if (isset($conditions['month'])) {
|
||||||
// $query->where(function ($subQuery) use ($conditions) {
|
|
||||||
// $subQuery->where('service_start_at', '<=', Carbon::parse($conditions['month']))
|
|
||||||
// ->where('service_end_at', '>=', Carbon::parse($conditions['month']));
|
|
||||||
// });
|
|
||||||
$conditions['month'] = (int)Carbon::parse($conditions['month'])->format('Ym');
|
$conditions['month'] = (int)Carbon::parse($conditions['month'])->format('Ym');
|
||||||
$query->whereRaw("timelines_array(sim) @> '{{$conditions['month']}}'");
|
$query->whereRaw("timelines_array(sim) @> '{{$conditions['month']}}'");
|
||||||
}
|
}
|
||||||
|
@ -58,21 +58,21 @@ class ProductRepository extends Repository
|
|||||||
$conditions['id'] = array_wrap($conditions['id']);
|
$conditions['id'] = array_wrap($conditions['id']);
|
||||||
$query->whereIn('id', $conditions['id']);
|
$query->whereIn('id', $conditions['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($conditions['company_id'])) {
|
if (isset($conditions['company_id'])) {
|
||||||
$query->where('company_id', $conditions['company_id']);
|
$query->where('company_id', $conditions['company_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($conditions['name'])) {
|
if (isset($conditions['name'])) {
|
||||||
$query->where('name', 'like', "%{$conditions['name']}%");
|
$query->where('name', 'like', "%{$conditions['name']}%");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($conditions['package_name'])) {
|
if (isset($conditions['package_name'])) {
|
||||||
$query->whereHas('package', function ($relation) use ($conditions) {
|
$query->whereHas('package', function ($relation) use ($conditions) {
|
||||||
$relation->withTrashed()->where('name', $conditions['package_name']);
|
$relation->withTrashed()->where('name', $conditions['package_name']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($conditions['carrier_operator'])) {
|
if (isset($conditions['carrier_operator'])) {
|
||||||
$query->whereHas('package', function ($relation) use ($conditions) {
|
$query->whereHas('package', function ($relation) use ($conditions) {
|
||||||
$relation->withTrashed()->where('carrier_operator', $conditions['carrier_operator']);
|
$relation->withTrashed()->where('carrier_operator', $conditions['carrier_operator']);
|
||||||
|
@ -56,7 +56,7 @@ class OrderCard extends Model
|
|||||||
use SoftDeletes, OrderRelations, HasCompositePrimaryKey;
|
use SoftDeletes, OrderRelations, HasCompositePrimaryKey;
|
||||||
|
|
||||||
protected $table = 'virtual_order_cards';
|
protected $table = 'virtual_order_cards';
|
||||||
|
|
||||||
public function renewals()
|
public function renewals()
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Package::class, 'virtual_order_renewal_cards', 'sim', 'package_id', 'sim', 'id')->withPivot('created_at', 'counts');
|
return $this->belongsToMany(Package::class, 'virtual_order_renewal_cards', 'sim', 'package_id', 'sim', 'id')->withPivot('created_at', 'counts');
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Models\Virtual;
|
namespace App\Models\Virtual;
|
||||||
|
|
||||||
use App\Core\Model;
|
use App\Core\Model;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App\Models\Virtual\Product
|
* App\Models\Virtual\Product
|
||||||
@ -38,6 +39,8 @@ use App\Core\Model;
|
|||||||
*/
|
*/
|
||||||
class Product extends Model
|
class Product extends Model
|
||||||
{
|
{
|
||||||
|
use SoftDeletes;
|
||||||
|
|
||||||
protected $table = 'virtual_products';
|
protected $table = 'virtual_products';
|
||||||
|
|
||||||
public function company()
|
public function company()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
CREATE OR REPLACE FUNCTION TIMELINES_JSON (sim INT8)
|
CREATE OR REPLACE FUNCTION TIMELINES_JSON (sim INT8, activated_at TIMESTAMP)
|
||||||
RETURNS JSONB
|
RETURNS JSONB
|
||||||
AS $$
|
AS $$
|
||||||
DECLARE
|
DECLARE
|
||||||
@ -6,14 +6,11 @@ DECLARE
|
|||||||
query TEXT;
|
query TEXT;
|
||||||
order_row RECORD;
|
order_row RECORD;
|
||||||
temp_text TEXT;
|
temp_text TEXT;
|
||||||
temp_activated_at TIMESTAMP;
|
|
||||||
temp_service_start_at TIMESTAMP;
|
temp_service_start_at TIMESTAMP;
|
||||||
temp_service_end_at TIMESTAMP;
|
temp_service_end_at TIMESTAMP;
|
||||||
next_timestamp TIMESTAMP;
|
next_timestamp TIMESTAMP;
|
||||||
BEGIN
|
BEGIN
|
||||||
SELECT virtual_activated_at INTO temp_activated_at FROM vd.cards WHERE cards.sim = TIMELINES_JSON.sim;
|
IF activated_at IS NULL THEN
|
||||||
|
|
||||||
IF temp_activated_at IS NULL THEN
|
|
||||||
RETURN timelines;
|
RETURN timelines;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
@ -37,7 +34,7 @@ BEGIN
|
|||||||
-- 服务时间
|
-- 服务时间
|
||||||
CASE (order_row. "type")
|
CASE (order_row. "type")
|
||||||
WHEN 0 THEN
|
WHEN 0 THEN
|
||||||
temp_service_start_at := TO_CHAR(temp_activated_at, 'YYYY-MM-01 00:00:00');
|
temp_service_start_at := TO_CHAR(activated_at, 'YYYY-MM-01 00:00:00');
|
||||||
temp_service_end_at := temp_service_start_at + (order_row.service_months || ' month')::INTERVAL + (order_row.delay_months || ' month')::INTERVAL - '1 second'::INTERVAL;
|
temp_service_end_at := temp_service_start_at + (order_row.service_months || ' month')::INTERVAL + (order_row.delay_months || ' month')::INTERVAL - '1 second'::INTERVAL;
|
||||||
WHEN 1, 2 THEN
|
WHEN 1, 2 THEN
|
||||||
IF (next_timestamp > order_row.created_at) THEN
|
IF (next_timestamp > order_row.created_at) THEN
|
||||||
@ -72,6 +69,18 @@ END;
|
|||||||
$$
|
$$
|
||||||
LANGUAGE plpgsql;
|
LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION TIMELINES_JSON (sim INT8)
|
||||||
|
RETURNS JSONB
|
||||||
|
AS $$
|
||||||
|
DECLARE
|
||||||
|
activated_at TIMESTAMP;
|
||||||
|
BEGIN
|
||||||
|
SELECT virtual_activated_at INTO activated_at FROM vd.cards WHERE cards.sim = TIMELINES_JSON.sim;
|
||||||
|
RETURN vd.TIMELINES_JSON(sim, activated_at);
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
LANGUAGE plpgsql;
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION TIMELINES_RANGE (sim INT8)
|
CREATE OR REPLACE FUNCTION TIMELINES_RANGE (sim INT8)
|
||||||
RETURNS TSRANGE[]
|
RETURNS TSRANGE[]
|
||||||
AS $$
|
AS $$
|
||||||
@ -90,6 +99,39 @@ END;
|
|||||||
$$
|
$$
|
||||||
LANGUAGE plpgsql;
|
LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION TIMELINES_ARRAY (sim INT8, activated_at TIMESTAMP)
|
||||||
|
RETURNS INT[]
|
||||||
|
AS $$
|
||||||
|
DECLARE
|
||||||
|
timelines INT[] := '{}';
|
||||||
|
timelines_json JSONB;
|
||||||
|
item JSONB;
|
||||||
|
temp_months INT;
|
||||||
|
i INT;
|
||||||
|
BEGIN
|
||||||
|
IF activated_at IS NULL THEN
|
||||||
|
RETURN timelines;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
timelines_json := vd.TIMELINES_JSON(sim, activated_at);
|
||||||
|
|
||||||
|
FOR item IN SELECT * FROM json_array_elements(timelines_json::JSON) LOOP
|
||||||
|
temp_months = (TO_CHAR((item->>'service_end_at')::TIMESTAMP, 'YYYY')::INT - TO_CHAR((item->>'service_start_at')::TIMESTAMP, 'YYYY')::INT) * 12
|
||||||
|
+ (TO_CHAR((item->>'service_end_at')::TIMESTAMP, 'MM')::INT - TO_CHAR((item->>'service_start_at')::TIMESTAMP, 'MM')::INT);
|
||||||
|
i := 0;
|
||||||
|
|
||||||
|
RAISE NOTICE 'TIMELINES_ARRAY: % - % - %', item->>'sim', item->>'package_id', temp_months;
|
||||||
|
|
||||||
|
WHILE i <= temp_months LOOP
|
||||||
|
timelines := timelines || TO_CHAR((item->>'service_start_at')::TIMESTAMP + (i || ' month')::INTERVAL, 'YYYYMM')::INT;
|
||||||
|
i := i + 1;
|
||||||
|
END LOOP;
|
||||||
|
END LOOP;
|
||||||
|
RETURN timelines;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
LANGUAGE plpgsql IMMUTABLE;
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION TIMELINES_ARRAY (sim INT8)
|
CREATE OR REPLACE FUNCTION TIMELINES_ARRAY (sim INT8)
|
||||||
RETURNS INT[]
|
RETURNS INT[]
|
||||||
AS $$
|
AS $$
|
||||||
|
@ -36,10 +36,7 @@ CREATE TABLE virtual_order_renewal_cards PARTITION OF virtual_order_cards_partit
|
|||||||
CREATE TABLE virtual_order_renewal_package_cards PARTITION OF virtual_order_cards_partition FOR VALUES IN (2);
|
CREATE TABLE virtual_order_renewal_package_cards PARTITION OF virtual_order_cards_partition FOR VALUES IN (2);
|
||||||
CREATE TABLE virtual_order_flows_package_cards PARTITION OF virtual_order_cards_partition FOR VALUES IN (3);
|
CREATE TABLE virtual_order_flows_package_cards PARTITION OF virtual_order_cards_partition FOR VALUES IN (3);
|
||||||
|
|
||||||
CREATE UNIQUE INDEX "virtual_order_cards_order_id_sim_deleted_at_unique" ON "virtual_order_cards" (order_id, sim, COALESCE(deleted_at, '1970-01-01 08:00:00'::timestamp));
|
CREATE UNIQUE INDEX "virtual_order_cards_partition_order_id_sim_deleted_at_unique" ON "virtual_order_cards_partition" ("type", order_id, sim, COALESCE(deleted_at, '1970-01-01 08:00:00'::timestamp));
|
||||||
CREATE UNIQUE INDEX "virtual_order_renewal_cards_order_id_sim_deleted_at_unique" ON "virtual_order_cards" (order_id, sim, COALESCE(deleted_at, '1970-01-01 08:00:00'::timestamp));
|
|
||||||
CREATE UNIQUE INDEX "virtual_order_renewal_package_cards_order_id_sim_deleted_at_unique" ON "virtual_order_cards" (order_id, sim, COALESCE(deleted_at, '1970-01-01 08:00:00'::timestamp));
|
|
||||||
CREATE UNIQUE INDEX "virtual_order_flows_package_cards_order_id_sim_deleted_at_unique" ON "virtual_order_cards" (order_id, sim, COALESCE(deleted_at, '1970-01-01 08:00:00'::timestamp));
|
|
||||||
|
|
||||||
CREATE INDEX "virtual_order_cards_timelines_index" ON "virtual_order_cards" USING GIN (timelines_array(sim));
|
CREATE INDEX "virtual_order_cards_timelines_index" ON "virtual_order_cards" USING GIN (timelines_array(sim));
|
||||||
CREATE INDEX "virtual_order_renewal_cards_timelines_index" ON "virtual_order_renewal_cards" USING GIN (timelines_array(sim));
|
CREATE INDEX "virtual_order_renewal_cards_timelines_index" ON "virtual_order_renewal_cards" USING GIN (timelines_array(sim));
|
||||||
|
@ -1,174 +0,0 @@
|
|||||||
CREATE OR REPLACE FUNCTION FIX_TIMELINES (sim INT8, activated_at TIMESTAMP without TIME zone)
|
|
||||||
RETURNS BOOLEAN
|
|
||||||
AS $$
|
|
||||||
DECLARE
|
|
||||||
query TEXT;
|
|
||||||
order_row RECORD;
|
|
||||||
temp_service_start_at TIMESTAMP;
|
|
||||||
temp_service_end_at TIMESTAMP;
|
|
||||||
next_timestamp TIMESTAMP;
|
|
||||||
BEGIN
|
|
||||||
RAISE NOTICE '% - %', sim, activated_at;
|
|
||||||
IF activated_at IS NULL THEN
|
|
||||||
UPDATE
|
|
||||||
vd.virtual_order_cards_partition
|
|
||||||
SET
|
|
||||||
service_start_at = NULL,
|
|
||||||
service_end_at = NULL
|
|
||||||
WHERE
|
|
||||||
virtual_order_cards_partition.sim = FIX_TIMELINES.sim;
|
|
||||||
ELSE
|
|
||||||
query := 'SELECT
|
|
||||||
virtual_order_cards_partition.*,
|
|
||||||
virtual_packages.service_months,
|
|
||||||
virtual_packages.effect_months,
|
|
||||||
virtual_packages.delay_months
|
|
||||||
FROM
|
|
||||||
vd.virtual_order_cards_partition
|
|
||||||
JOIN vd.virtual_packages ON virtual_order_cards_partition.package_id = virtual_packages."id"
|
|
||||||
WHERE
|
|
||||||
virtual_order_cards_partition.sim = $1
|
|
||||||
ORDER BY
|
|
||||||
"type" ASC,
|
|
||||||
created_at ASC';
|
|
||||||
FOR order_row IN EXECUTE query
|
|
||||||
USING sim LOOP
|
|
||||||
-- 服务时间
|
|
||||||
CASE (order_row. "type")
|
|
||||||
WHEN 0 THEN
|
|
||||||
temp_service_start_at := TO_CHAR(activated_at, 'YYYY-MM-01 00:00:00');
|
|
||||||
temp_service_end_at := temp_service_start_at + (order_row.service_months || ' month')::INTERVAL + (order_row.delay_months || ' month')::INTERVAL - '1 second'::INTERVAL;
|
|
||||||
WHEN 1,
|
|
||||||
2 THEN
|
|
||||||
IF (next_timestamp > order_row.created_at) THEN
|
|
||||||
temp_service_start_at := TO_CHAR(next_timestamp, 'YYYY-MM-01 00:00:00');
|
|
||||||
ELSE
|
|
||||||
temp_service_start_at := TO_CHAR(order_row.created_at, 'YYYY-MM-01 00:00:00');
|
|
||||||
END IF;
|
|
||||||
temp_service_end_at := temp_service_start_at + order_row.counts * (order_row.service_months || ' month')::INTERVAL + (order_row.delay_months || ' month')::INTERVAL - '1 second'::INTERVAL;
|
|
||||||
ELSE
|
|
||||||
-- 先购买了加油包后再激活的
|
|
||||||
IF (order_row.created_at < activated_at) THEN
|
|
||||||
IF (order_row.created_at < TO_CHAR(activated_at - '1 month'::INTERVAL, 'YYYY-MM-01 00:00:00')::TIMESTAMP) THEN
|
|
||||||
-- 购买时间小于一个月的,直接生效
|
|
||||||
temp_service_start_at := TO_CHAR(activated_at, 'YYYY-MM-01 00:00:00');
|
|
||||||
ELSE
|
|
||||||
-- 延时生效
|
|
||||||
temp_service_start_at := TO_CHAR(activated_at + (order_row.effect_months || ' month')::INTERVAL,
|
|
||||||
'YYYY-MM-01 00:00:00');
|
|
||||||
END IF;
|
|
||||||
ELSE
|
|
||||||
-- 延时生效
|
|
||||||
temp_service_start_at := TO_CHAR(order_row.created_at + (order_row.effect_months || ' month')::INTERVAL,
|
|
||||||
'YYYY-MM-01 00:00:00');
|
|
||||||
END IF;
|
|
||||||
temp_service_end_at := temp_service_start_at + (order_row.service_months || ' month')::INTERVAL + (order_row.delay_months || ' month')::INTERVAL - '1 second'::INTERVAL;
|
|
||||||
END CASE;
|
|
||||||
next_timestamp := temp_service_end_at + '1 second'::INTERVAL;
|
|
||||||
-- 更新数据库
|
|
||||||
UPDATE
|
|
||||||
vd.virtual_order_cards_partition
|
|
||||||
SET
|
|
||||||
service_start_at = temp_service_start_at,
|
|
||||||
service_end_at = temp_service_end_at
|
|
||||||
WHERE
|
|
||||||
virtual_order_cards_partition. "id" = order_row. "id";
|
|
||||||
END LOOP;
|
|
||||||
END IF;
|
|
||||||
RETURN TRUE;
|
|
||||||
END;
|
|
||||||
$$
|
|
||||||
LANGUAGE plpgsql;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION CARD_TIMELINES ()
|
|
||||||
RETURNS TRIGGER
|
|
||||||
AS $$
|
|
||||||
BEGIN
|
|
||||||
IF (TG_OP = 'INSERT') THEN
|
|
||||||
-- 插入数据
|
|
||||||
IF (NEW.virtual_activated_at IS NOT NULL) THEN
|
|
||||||
PERFORM
|
|
||||||
vd.FIX_TIMELINES (NEW.sim,
|
|
||||||
NEW.virtual_activated_at);
|
|
||||||
END IF;
|
|
||||||
ELSIF (TG_OP = 'UPDATE') THEN
|
|
||||||
-- 更新数据
|
|
||||||
IF (OLD.virtual_activated_at IS NOT NULL) OR (NEW.virtual_activated_at IS NOT NULL) THEN
|
|
||||||
PERFORM
|
|
||||||
vd.FIX_TIMELINES (NEW.sim,
|
|
||||||
NEW.virtual_activated_at);
|
|
||||||
END IF;
|
|
||||||
ELSIF (TG_OP = 'DELETE') THEN
|
|
||||||
-- 删除数据
|
|
||||||
PERFORM
|
|
||||||
vd.FIX_TIMELINES (NEW.sim,
|
|
||||||
NULL);
|
|
||||||
END IF;
|
|
||||||
RETURN NULL;
|
|
||||||
END;
|
|
||||||
$$
|
|
||||||
LANGUAGE plpgsql;
|
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS CARD_TIMELINES ON cards;
|
|
||||||
|
|
||||||
CREATE TRIGGER CARD_TIMELINES AFTER INSERT
|
|
||||||
OR
|
|
||||||
UPDATE
|
|
||||||
OR DELETE ON cards FOR EACH ROW EXECUTE PROCEDURE CARD_TIMELINES ();
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION ORDER_TIMELINES ()
|
|
||||||
RETURNS TRIGGER
|
|
||||||
AS $$
|
|
||||||
DECLARE
|
|
||||||
order_row RECORD;
|
|
||||||
BEGIN
|
|
||||||
IF (TG_OP = 'INSERT') THEN
|
|
||||||
-- 插入数据
|
|
||||||
SELECT
|
|
||||||
NEW.sim,
|
|
||||||
virtual_activated_at
|
|
||||||
FROM
|
|
||||||
vd.cards INTO order_row
|
|
||||||
WHERE
|
|
||||||
cards.sim = NEW.sim;
|
|
||||||
PERFORM
|
|
||||||
vd.FIX_TIMELINES (order_row.sim,
|
|
||||||
order_row.virtual_activated_at);
|
|
||||||
ELSIF (TG_OP = 'DELETE') THEN
|
|
||||||
SELECT
|
|
||||||
NEW.sim,
|
|
||||||
virtual_activated_at
|
|
||||||
FROM
|
|
||||||
vd.cards INTO order_row
|
|
||||||
WHERE
|
|
||||||
cards.sim = NEW.sim;
|
|
||||||
PERFORM
|
|
||||||
vd.FIX_TIMELINES (order_row.sim,
|
|
||||||
order_row.virtual_activated_at);
|
|
||||||
END IF;
|
|
||||||
RETURN NULL;
|
|
||||||
END;
|
|
||||||
$$
|
|
||||||
LANGUAGE plpgsql;
|
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS ORDER_TIMELINES ON virtual_order_cards;
|
|
||||||
|
|
||||||
CREATE TRIGGER ORDER_TIMELINES AFTER INSERT
|
|
||||||
OR DELETE ON virtual_order_cards FOR EACH ROW EXECUTE PROCEDURE ORDER_TIMELINES ();
|
|
||||||
|
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS ORDER_TIMELINES ON virtual_order_renewal_cards;
|
|
||||||
|
|
||||||
CREATE TRIGGER ORDER_TIMELINES AFTER INSERT
|
|
||||||
OR DELETE ON virtual_order_renewal_cards FOR EACH ROW EXECUTE PROCEDURE ORDER_TIMELINES ();
|
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS ORDER_TIMELINES ON virtual_order_renewal_package_cards;
|
|
||||||
|
|
||||||
CREATE TRIGGER ORDER_TIMELINES AFTER INSERT
|
|
||||||
OR DELETE ON virtual_order_renewal_package_cards FOR EACH ROW EXECUTE PROCEDURE ORDER_TIMELINES ();
|
|
||||||
|
|
||||||
DROP TRIGGER IF EXISTS ORDER_TIMELINES ON virtual_order_flows_package_cards;
|
|
||||||
|
|
||||||
CREATE TRIGGER ORDER_TIMELINES AFTER INSERT
|
|
||||||
OR DELETE ON virtual_order_flows_package_cards FOR EACH ROW EXECUTE PROCEDURE ORDER_TIMELINES ();
|
|
||||||
|
|
@ -20,7 +20,7 @@ class PostgresGrammar extends Grammar
|
|||||||
public function compileUpdateBatch(QueryBuilder $query, array $values, $filed = 'id')
|
public function compileUpdateBatch(QueryBuilder $query, array $values, $filed = 'id')
|
||||||
{
|
{
|
||||||
$as = 'as_table';
|
$as = 'as_table';
|
||||||
|
|
||||||
$table = $this->wrapTable($query->from);
|
$table = $this->wrapTable($query->from);
|
||||||
|
|
||||||
if (! is_array(reset($values))) {
|
if (! is_array(reset($values))) {
|
||||||
@ -85,7 +85,7 @@ class PostgresGrammar extends Grammar
|
|||||||
$field = "COALESCE($field, '1970-01-01 08:00:00'::timestamp)";
|
$field = "COALESCE($field, '1970-01-01 08:00:00'::timestamp)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$reference = implode(',', $fields);
|
$reference = implode(',', $fields);
|
||||||
|
|
||||||
// excluded fields are all fields except $unique one that will be updated
|
// excluded fields are all fields except $unique one that will be updated
|
||||||
@ -105,7 +105,7 @@ class PostgresGrammar extends Grammar
|
|||||||
$update = join(', ', array_map(function ($e) {
|
$update = join(', ', array_map(function ($e) {
|
||||||
return "\"$e\" = \"excluded\".\"$e\"";
|
return "\"$e\" = \"excluded\".\"$e\"";
|
||||||
}, $excluded));
|
}, $excluded));
|
||||||
|
|
||||||
return "$insert on conflict ($reference) do update set $update";
|
return "$insert on conflict ($reference) do update set $update";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
|
|||||||
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
* @mixin \Illuminate\Database\Eloquent\Builder
|
* @mixin \Illuminate\Database\Eloquent\Builder
|
||||||
|
Loading…
x
Reference in New Issue
Block a user