vd/app/Domains/Virtual/Services/PropertyService.php
2020-03-25 17:54:56 +08:00

416 lines
14 KiB
PHP

<?php
namespace App\Domains\Virtual\Services;
use App\Dicts;
use App\Core\Service;
use Illuminate\Support\Facades\DB;
use App\Exceptions\NotExistException;
use App\Exceptions\NotAllowedException;
use App\Models\Virtual\PropertySetting;
use App\Exceptions\InvalidArgumentException;
use App\Domains\Virtual\Repositories\ProductRepository;
use App\Domains\Virtual\Repositories\PropertyRepository;
use App\Domains\Virtual\Repositories\OrderCardRepository;
use App\Domains\Virtual\Repositories\PropertySettingRepository;
use App\Domains\Virtual\Repositories\OrderCardPartitionRepository;
class PropertyService extends Service
{
protected $productRepository;
protected $propertyRepository;
protected $propertySettingRepository;
public static $property_types = [
'vehicle_group' => '车型分组',
'vehicle_type' => '车型选项',
'vehicle' => '车辆类型',
'company' => '公司类型',
'platform' => '平台/API类型',
'customer' => '客户类型',
'package' => '套餐分类',
'product' => '产品类型',
'package_type' => '套餐类型',
'province' => '省份设置',
'agent' => '机构设置',
];
public static $default = [
'vehicle' => '',
'commercial_vehicle' => '',
'company' => '',
'platform' => '',
'customer' => '',
'package' => '',
'product' => '',
'province' => null,
'province_status' => 0,
'agent' => null,
'agent_status' => 0,
'created_at' => null,
'updated_at' => null,
];
protected static $properties;
/**
* 构造函数
*
* @return void
*/
public function __construct(ProductRepository $productRepository, PropertyRepository $propertyRepository, PropertySettingRepository $propertySettingRepository)
{
$this->productRepository = $productRepository;
$this->propertyRepository = $propertyRepository;
$this->propertySettingRepository = $propertySettingRepository;
}
/**
* 配置设置查看
*
* @param array $conditions
* @return void
*/
public function settings($conditions = [])
{
$settings = $this->propertySettingRepository->getAll();
$products = $settings['product'];
foreach ($settings as $key => $setting) {
if ($setting['name'] === 'package') {
$values = $setting['value'];
foreach ($values as $k => $value) {
foreach ($value as $i => $v) {
if (!in_array($v, $products)) {
unset($settings[$key]['value'][$k][$i]);
$settings[$key]['value'][$k] = array_values($settings[$key]['value'][$k]);
}
}
}
}
}
$vehicleTypes = $settings['vehicle_type'];
foreach ($settings as $key => $setting) {
if ($setting['name'] === 'vehicle') {
$values = $setting['value'];
foreach ($values as $k => $value) {
foreach ($value as $i => $v) {
if (!in_array($v, $vehicleTypes)) {
unset($settings[$key]['value'][$k][$i]);
$settings[$key]['value'][$k] = array_values($settings[$key]['value'][$k]);
}
}
}
}
}
if ($conditions['names']) {
$conditions['names'] = array_wrap($conditions['names']);
$settings = array_where($settings, function ($value) use ($conditions) {
return in_array($value['name'], $conditions['names']);
});
};
return $settings;
}
/**
* 配置设置写入
*
* @param array $values
* @return void
*/
public function settingsStore(array $values)
{
$settings = $this->propertySettingRepository->getAll();
foreach ($values as $key => $value) {
if (!in_array($key, array_keys(self::$property_types))) {
throw new NotExistException("分类{$key}不存在");
}
if ($key !== 'province' && $key !== 'package' && $key !== 'vehicle') {
$value = array_values(array_unique(array_merge($value)));
$value = array_map(function ($item) {
return is_string($item) ? trim($item) : $item;
}, $value);
}
$values[$key] = $value;
}
if (isset($values['package'])) {
$packages = $values['package'];
$products = $values['product'];
foreach ($packages as $k => $v) {
if (!is_array($v)) {
throw new InvalidArgumentException('传入的产品参数错误');
}
foreach ($v as $m) {
if (!in_array($m, $products)) {
throw new NotExistException("产品({$m})未配置或已删除");
}
foreach ($packages as $i => $j) {
if ($i !== $k && in_array($m, $j)) {
throw new NotAllowedException('一个产品仅能归属一个套餐');
}
}
}
}
}
if (isset($values['vehicle'])) {
$vehicles = $values['vehicle'];
$vehicleTypes = $values['vehicle_type'];
foreach ($vehicles as $k => $v) {
if (!is_array($v)) {
throw new InvalidArgumentException('传入的车型配置错误');
}
foreach ($v as $m) {
if (!in_array($m, $vehicleTypes)) {
throw new NotExistException("车型({$m})未配置或已删除");
}
foreach ($vehicles as $i => $j) {
if ($i !== $k && in_array($m, $j)) {
throw new NotAllowedException('一个车型仅能归属一个分组');
}
}
}
}
}
$data = [];
foreach ($values as $key => $value) {
$data[] = [
'name' => $key,
'value' => json_encode($value, 256),
];
}
PropertySetting::upsert($data, 'name');
$settings = $this->propertySettingRepository->getAll(true);
return $settings;
}
/**
* 客户套餐配置列表
*
* @return void
*/
public function index($conditions = [])
{
$product = $this->productRepository->whereHas('package', function ($query) {
$query->whereNull('deleted_at');
})->whereHas('company', function ($query) {
$query->whereNull('deleted_at');
})->withConditions($conditions)->applyConditions()->get();
$properties = $this->propertyRepository->whereHas('package', function ($query) {
$query->whereNull('deleted_at');
})->whereHas('company', function ($query) {
$query->whereNull('deleted_at');
})->withConditions($conditions)->applyConditions()->get()->keyBy(function ($item) {
return $item->company_id . '_' . $item->package_id;
})->toArray();
$sells = app(OrderCardRepository::class)->selectRaw('company_id, package_id, count(*) as counts')
->groupBy(['company_id', 'package_id'])->get()->keyBy(function ($item) {
return $item->company_id . '_' . $item->package_id;
})->toArray();
$actives = app(OrderCardRepository::class)->selectRaw('company_id, package_id, count(*) as counts')
->withConditions(['card_status' => 2])->groupBy(['company_id', 'package_id'])->get()->keyBy(function ($item) {
return $item->company_id . '_' . $item->package_id;
})->toArray();
$carrierOperators = app(Dicts::class)->get('carrier_operator');
$list = $product->map(function ($item) use ($properties, $sells, $actives, $carrierOperators) {
$item = $item->toArray();
$package = PackageService::load($item['package_id']);
$item['company_name'] = CompanyService::load($item['company_id'])['name'] ?? '';
$item['package_name'] = $package['name'] ?? '';
$item['flows'] = $package['flows'] ?? 0;
$item['carrier_operator'] = $package['carrier_operator'];
$item['carrier_operator_name'] = $carrierOperators[$item['carrier_operator']] ?? '未知';
$property = $properties[$item['company_id'] . '_' . $item['package_id']];
$sell = $sells[$item['company_id'] . '_' . $item['package_id']];
$active = $actives[$item['company_id'] . '_' . $item['package_id']];
$item['counts'] = $sell ? $sell['counts'] : 0;
$item['actives'] = $active ? $active['counts'] : 0;
return array_merge($item, $property ?: self::$default);
});
return $list;
}
/**
* 客户套餐配置修改
*
* @param array $values
* @return void
*/
public function store(array $values)
{
if (! is_array(reset($values))) {
$values = [$values];
}
$only = ['company_id', 'package_id', 'product', 'vehicle_type', 'company', 'platform', 'customer', 'province', 'agent'];
$checks = ['product', 'vehicle_type', 'company', 'customer'];
$settings = $this->propertySettingRepository->getAll();
$agents = app(AgentService::class)->listGroupByCompanyId();
$data = [];
foreach ($values as $value) {
if (!isset($value['company_id']) || !isset($value['package_id'])) {
continue;
}
$value['platform'] = $value['platform'] ?: '';
$value = array_only($value, $only);
foreach ($value as $k => $v) {
if (in_array($k, $checks) && empty($v)) {
throw new InvalidArgumentException(self::$property_types[$k] . '值不能为空');
}
if (in_array($k, $checks) && !in_array($v, $settings[$k])) {
throw new InvalidArgumentException(self::$property_types[$k] . '值不正确');
}
if (in_array($k, ['platform']) && !in_array($v, $settings[$k]) && ($v !== '')) {
throw new InvalidArgumentException(self::$property_types[$k] . '值不正确');
}
}
if (!is_null($value['province'])) {
if (!empty(array_diff(array_keys($value['province']), $settings['province']))) {
throw new InvalidArgumentException('省份配置不正确');
}
if (array_sum($value['province']) != 0 && sprintf("%.2f", array_sum($value['province'])) != 100) {
throw new InvalidArgumentException('百分比配置不正确');
}
$value['province'] = json_encode($value['province'], 256);
}
if (!is_null($value['agent'])) {
$itemAgents = $agents[$value['company_id']];
$index = [];
foreach ($value['agent'] as $agent) {
if (in_array($agent['company_id'] . '_' . $agent['platform'], $index)) {
throw new InvalidArgumentException('机构平台重复配置');
} else {
array_push($index, $agent['company_id'] . '_' . $agent['platform']);
}
if (!in_array($agent['agent'], array_pluck($itemAgents, 'id'))) {
throw new InvalidArgumentException('机构配置不正确');
}
if (!in_array($agent['platform'], array_keys($settings['platform']))) {
throw new InvalidArgumentException('机构平台配置不正确');
}
}
if (array_sum(array_pluck($value['agent'], 'percentages')) != 0 && sprintf("%.2f", array_sum(array_pluck($value['agent'], 'percentages'))) != 100) {
throw new InvalidArgumentException('机构百分比配置不正确');
}
$value['agent'] = json_encode($value['agent'], 256);
}
if (!$package = $this->getPackage($value['product'])) {
throw new NotExistException('产品套餐关系未配置');
}
if (!$vehicle = $this->getVehicle($value['vehicle_type'])) {
throw new NotExistException('车型分组关系未配置');
}
$value['package'] = $package;
$value['vehicle'] = $vehicle;
$value['created_at'] = date('Y-m-d H:i:s');
$value['updated_at'] = date('Y-m-d H:i:s');
$data[$value['company_id'] . '_' . $value['package_id']] = $value;
}
if (empty($data)) {
throw new NotAllowedException('数据未修改');
}
$values = array_values($data);
$this->propertyRepository->upsert($values, ['company_id', 'package_id']);
$this->propertyRepository->forgetCached();
return true;
}
protected function getPackage($product)
{
if (!$package = $this->package) {
$settings = $this->propertySettingRepository->getAll();
$packages = $settings['package'];
$this->package = $package;
}
foreach ($packages as $key => $products) {
if (in_array($product, $products)) {
return $key;
}
}
return null;
}
protected function getVehicle($vehicleType)
{
if (!$vehicle = $this->vehicle) {
$settings = $this->propertySettingRepository->getAll();
$vehicles = $settings['vehicle'];
$this->vehicle = $vehicle;
}
foreach ($vehicles as $key => $vehicleTypes) {
if (in_array($vehicleType, $vehicleTypes)) {
return $key;
}
}
return null;
}
public static function load($company_id, $package_id)
{
if (!self::$properties) {
$properties = app(PropertyRepository::class)
->select(['company_id', 'package_id', 'product', 'package'])->get();
self::$properties = $properties->keyBy(function ($item) {
return $item['company_id'] . '_' . $item['package_id'];
})->toArray();
}
return self::$properties[$company_id . '_' . $package_id];
}
}