vd/app/Domains/Virtual/Jobs/LogSyncJob.php
2019-02-25 22:54:43 +08:00

247 lines
8.7 KiB
PHP

<?php
namespace App\Domains\Virtual\Jobs;
use App\Models\Card\Card;
use Illuminate\Support\Arr;
use App\Models\Virtual\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Dipper\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Artisan;
use App\Models\Virtual\OrderCardPartition;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Domains\Config\Services\ConfigService;
use App\Domains\Virtual\Commands\Sync\LogSync;
use App\Domains\Virtual\Services\CommonService;
use App\Domains\Virtual\Services\ProductService;
use App\Domains\Card\Repositories\CardRepository;
use App\Domains\Virtual\Repositories\OrderRepository;
use App\Domains\Virtual\Repositories\CompanyRepository;
use App\Domains\Virtual\Repositories\PackageRepository;
use App\Domains\Virtual\Repositories\ProductRepository;
use App\Domains\Virtual\Repositories\OrderCardRepository;
use App\Domains\Virtual\Repositories\OrderRenewalCardRepository;
use App\Domains\Virtual\Repositories\OrderCardPartitionRepository;
use App\Domains\Virtual\Repositories\OrderFlowPackageCardsRepository;
use App\Domains\Virtual\Repositories\OrderRenewalPackageCardRepository;
class LogSyncJob implements ShouldQueue
{
use Queueable, Dispatchable;
public $page;
public $limit;
public $maxId;
protected $packages;
protected $products;
protected $companies;
public static $types = [11 => 1, 13 => 0, 14 => 2, 15 => 3];
protected static $carrierOperators = [10 => 0, 11 => 1, 12 => 2];
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
*
* @param int $page
* @param int $limit
* @param int $maxId
*/
public function __construct($page, $limit, $maxId)
{
$this->page = $page;
$this->limit = $limit;
$this->maxId = $maxId;
}
/**
*
*/
public function handle()
{
Log::info("LogSyncJob #: maxId {$this->maxId} - page {$this->page}");
$this->packages = app(PackageRepository::class)->withTrashed()->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))
->where('id', '>', $this->maxId)->orderBy('id');
$res = $query->forPage($this->page, $this->limit)->get();
if (empty($res)) {
Log::notice('LogSyncJob not result!');
return ;
}
DB::beginTransaction();
$orderArray = [];
$relationArray = [];
foreach ($res as $key => $value) {
$value = (array)$value;
$package = $this->getPackage($value['content']);
$company = $this->getCompany(CommonService::stringifyCompanyId($value['company']));
$unit_price = intval($value['order_account'] * 100);
$product = $this->getProduct($package, $company['id'], $value['order_account']);
$type = self::$types[$value['type']];
$pay_channel = self::$payChannels[$value['pay_type']];
// 按规则生成订单编号 (月6+类型1+公司3+套餐4+价格6)
$sn = date('Ym', $value['create_time']) . $type . sprintf('%03d', $company['id']) . sprintf('%04d', $package['id']) . sprintf('%06d', $unit_price);
$counts = isset($orderArray[$sn]) ? $orderArray[$sn]['counts'] + 1 : 1;
$total_price = isset($orderArray[$sn]) ? $orderArray[$sn]['total_price'] + $unit_price : $unit_price;
$orderArray[$sn] = [
'sn' => $sn,
'source' => 1,
'type' => $type,
'company_id' => $company['id'],
'package_id' => $package['id'],
'product_id' => $product['id'],
'pay_channel' => $pay_channel,
'unit_price' => $unit_price,
'counts' => $counts,
'total_price' => $total_price,
'custom_price' => $total_price,
'order_at' => date('Y-m-d H:i:s', $value['create_time']),
'order_status' => 4,
'transaction_status' => 1,
'created_at' => date('Y-m-d H:i:s', $value['create_time']),
];
$k = $sn . '-' . $value['sim'];
$counts = isset($relationArray[$k]) ? $relationArray[$k]['counts'] + 1 : 1;
$relationArray[$k] = [
'order_sn' => $sn,
'type' => $type,
'sim' => $value['sim'],
'company_id' => $company['id'],
'package_id' => $package['id'],
'counts' => $counts,
'created_at' => date('Y-m-d H:i:s', $value['create_time']),
'updated_at' => date('Y-m-d H:i:s'),
];
}
try {
$builder = Order::query()->toBase();
$sql = $builder->getGrammar()->compileInsert($builder, $orderArray);
$sql .= " on conflict (sn, COALESCE(deleted_at, '1970-01-01 08:00:00'::timestamp)) do update set
counts=virtual_orders.counts + excluded.counts,
total_price=virtual_orders.unit_price * (virtual_orders.counts + excluded.counts),
custom_price=virtual_orders.unit_price * (virtual_orders.counts + excluded.counts)";
$builder->connection->insert($sql, Arr::flatten($orderArray, 1));
$orders = Order::withTrashed()->select(['id', 'sn'])->whereIn('sn', array_pluck($orderArray, 'sn'))->get()->pluck('id', 'sn')->toArray();
foreach ($relationArray as $key => $value) {
$relationArray[$key]['order_id'] = $orders[$value['order_sn']];
unset($relationArray[$key]['order_sn']);
}
$relationArray = array_groupBy($relationArray, 'type');
foreach ($relationArray as $type => $array) {
$class = new self::$orderClasses[$type];
$builder = $class->query()->toBase();
$sql = $builder->getGrammar()->compileInsert($builder, $array);
$sql .= " on conflict (order_id, sim, COALESCE(deleted_at, '1970-01-01 08:00:00'::timestamp)) do update set
counts={$class->getTable()}.counts + excluded.counts";
$builder->connection->insert($sql, Arr::flatten($array, 1));
}
} catch (\Exception $e) {
DB::rollback();
Log::info("LogSyncJob ERROR #: maxId {$this->maxId} - page {$this->page}");
throw $e;
}
DB::commit();
app(OrderRepository::class)->forgetCached();
app(OrderCardRepository::class)->forgetCached();
app(OrderRenewalCardRepository::class)->forgetCached();
app(OrderRenewalPackageCardRepository::class)->forgetCached();
app(OrderFlowPackageCardsRepository::class)->forgetCached();
app(OrderCardPartitionRepository::class)->forgetCached();
Log::info("LogSyncJob END #: maxId {$this->maxId} - page {$this->page}");
}
/**
* 获取套餐
*
* @param string $sn
* @return void
*/
protected function getCompany($sn)
{
if (!$company = $this->companies[$sn]) {
throw new \Exception('企业不存在');
}
return $company;
}
/**
* 获取套餐
*
* @param string $sn
* @return void
*/
protected function getPackage($sn)
{
if (!$package = $this->packages[$sn]) {
throw new \Exception('套餐不存在');
}
return $package;
}
/**
* 获取定价
*
* @param string $sn
* @return void
*/
protected function getProduct($package, $companyId, $orderAccount)
{
$price = intval($orderAccount * 100);
$sn = ProductService::sn($package['sn'], $companyId, $price);
if (!$product = $this->products[$sn]) {
$product = app(ProductService::class)->store([
'name' => $package['name'] . ' ' . $orderAccount,
'company_id' => $companyId,
'package_id' => $package['id'],
'price' => $price,
]);
$this->products[$sn] = $product;
app(ProductRepository::class)->forgetCached();
}
return $product;
}
}