You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
11 KiB
223 lines
11 KiB
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Helpers\ResponseCode;
|
|
use App\Models\Company;
|
|
use App\Models\CompanyQccAccount;
|
|
use App\Models\OperateLog;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Database\QueryException;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use RuntimeException;
|
|
|
|
class QccEnterpriseAccountController extends CommonController
|
|
{
|
|
public function candidates(Request $request)
|
|
{
|
|
if ($error = $this->validateStudentFilters($request)) return $error;
|
|
$keyword = trim((string) $request->input('keyword', ''));
|
|
$status = $request->input('status');
|
|
$pageSize = min(max((int) $request->input('page_size', 20), 1), 100);
|
|
$query = Company::query()->select('id', 'company_name', 'credit_code', 'updated_at')->with('qccAccount');
|
|
if ($keyword !== '') {
|
|
$query->where(function ($subQuery) use ($keyword) {
|
|
$subQuery->where('company_name', 'like', '%' . $keyword . '%')
|
|
->orWhere('credit_code', 'like', '%' . $keyword . '%');
|
|
});
|
|
}
|
|
$this->applyStudentFilters($query, $request);
|
|
$query->with(['users' => $this->studentRelation()]);
|
|
if ($status === 'none') {
|
|
$query->doesntHave('qccAccount');
|
|
} elseif (in_array($status, [CompanyQccAccount::STATUS_SELECTED, CompanyQccAccount::STATUS_OCCUPIED, CompanyQccAccount::STATUS_UNKNOWN], true)) {
|
|
$query->whereHas('qccAccount', fn($relation) => $relation->where('status', $status));
|
|
}
|
|
return $this->studentResponse($query->orderByDesc('id')->paginate($pageSize));
|
|
}
|
|
|
|
public function index(Request $request)
|
|
{
|
|
if ($error = $this->validateStudentFilters($request)) return $error;
|
|
$status = $request->input('status');
|
|
$pageSize = min(max((int) $request->input('page_size', 20), 1), 100);
|
|
$query = CompanyQccAccount::query()->with(['company:id,company_name,credit_code', 'company.users' => $this->studentRelation()]);
|
|
$query->whereHas('company', function ($company) use ($request) {
|
|
$keyword = trim((string) $request->input('keyword', ''));
|
|
if ($keyword !== '') $company->where(fn ($q) => $q->where('company_name', 'like', '%'.$keyword.'%')->orWhere('credit_code', 'like', '%'.$keyword.'%'));
|
|
$this->applyStudentFilters($company, $request);
|
|
});
|
|
if (in_array($status, [CompanyQccAccount::STATUS_SELECTED, CompanyQccAccount::STATUS_OCCUPIED, CompanyQccAccount::STATUS_UNKNOWN], true)) {
|
|
$query->where('status', $status);
|
|
}
|
|
return $this->studentResponse($query->orderByDesc('id')->paginate($pageSize));
|
|
}
|
|
|
|
private function studentResponse($page)
|
|
{
|
|
foreach ($page as $row) {
|
|
$company = $row instanceof Company ? $row : $row->company;
|
|
foreach ($company ? $company->users : [] as $user) {
|
|
// Avoid unrelated appointment/company accessors and extra queries during serialization.
|
|
$user->setAppends([]);
|
|
foreach ($user->courseSigns as $sign) {
|
|
$sign->setAppends([]);
|
|
if ($sign->course) $sign->course->setAppends([]);
|
|
}
|
|
}
|
|
}
|
|
return $this->success($page);
|
|
}
|
|
|
|
private function validateStudentFilters(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'keyword' => 'nullable|string|max:200', 'user_name' => 'nullable|string|max:100',
|
|
'is_schoolmate' => 'nullable|in:0,1', 'course_type_id' => 'nullable|integer|min:1',
|
|
'course_name' => 'nullable|string|max:200',
|
|
]);
|
|
return $validator->fails() ? $this->fail([ResponseCode::ERROR_PARAMETER, $validator->errors()->first()]) : null;
|
|
}
|
|
|
|
private function studentRelation(): \Closure
|
|
{
|
|
return function ($users) {
|
|
$users->select('id', 'company_id', 'no', 'name', 'username', 'is_schoolmate', 'company_position')
|
|
->whereHas('courseSigns', fn ($sign) => $sign->where('status', 1))
|
|
->with(['courseSigns' => fn ($sign) => $sign->select('id', 'user_id', 'course_id', 'status')
|
|
->where('status', 1)->with('course:id,name,type,start_date')]);
|
|
};
|
|
}
|
|
|
|
private function applyStudentFilters($companies, Request $request): void
|
|
{
|
|
if (!$request->filled('user_name') && !$request->filled('is_schoolmate') && !$request->filled('course_type_id') && !$request->filled('course_name')) return;
|
|
$companies->whereHas('users', function ($user) use ($request) {
|
|
if ($request->filled('user_name')) {
|
|
$name = trim($request->user_name);
|
|
$user->where(fn ($q) => $q->where('name', 'like', '%'.$name.'%')->orWhere('username', 'like', '%'.$name.'%'));
|
|
}
|
|
if ($request->filled('is_schoolmate')) $user->where('is_schoolmate', $request->is_schoolmate);
|
|
$user->whereHas('courseSigns', function ($sign) use ($request) {
|
|
$sign->where('status', 1);
|
|
if ($request->filled('course_type_id') || $request->filled('course_name')) {
|
|
$sign->whereHas('course', function ($course) use ($request) {
|
|
if ($request->filled('course_type_id')) $course->where('type', $request->course_type_id);
|
|
if ($request->filled('course_name')) $course->where('name', 'like', '%'.trim($request->course_name).'%');
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
public function select(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), ['company_ids' => 'required|array|min:1', 'company_ids.*' => 'integer|distinct']);
|
|
if ($validator->fails()) {
|
|
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
|
|
}
|
|
$companyIds = $request->input('company_ids');
|
|
$companies = Company::query()->whereIn('id', $companyIds)->get()->keyBy('id');
|
|
foreach ($companyIds as $companyId) {
|
|
$company = $companies->get($companyId);
|
|
if (!$company || empty(trim((string) $company->credit_code))) {
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, '存在不存在或缺少统一社会信用代码的企业']);
|
|
}
|
|
}
|
|
|
|
try {
|
|
DB::transaction(function () use ($companyIds) {
|
|
$existingCompanyIds = CompanyQccAccount::query()->whereIn('company_id', $companyIds)->lockForUpdate()->pluck('company_id');
|
|
if ($existingCompanyIds->isNotEmpty()) {
|
|
throw new RuntimeException('存在已纳入企业户标注的企业');
|
|
}
|
|
foreach ($companyIds as $companyId) {
|
|
CompanyQccAccount::query()->create([
|
|
'company_id' => $companyId,
|
|
'status' => CompanyQccAccount::STATUS_SELECTED,
|
|
'selected_by' => $this->getUserId(),
|
|
'selected_at' => now(),
|
|
]);
|
|
}
|
|
});
|
|
} catch (RuntimeException|QueryException $exception) {
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, $exception->getMessage()]);
|
|
}
|
|
$this->log('纳入企查查企业户候选池', implode(',', $companyIds));
|
|
return $this->success('已纳入候选池');
|
|
}
|
|
|
|
public function cancel(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), ['id' => 'required|integer']);
|
|
if ($validator->fails()) {
|
|
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
|
|
}
|
|
try {
|
|
$companyId = DB::transaction(function () use ($request) {
|
|
$account = CompanyQccAccount::query()->whereKey($request->input('id'))->lockForUpdate()->first();
|
|
if (!$account) {
|
|
throw new RuntimeException('企业户关系不存在');
|
|
}
|
|
if ($account->status !== CompanyQccAccount::STATUS_SELECTED) {
|
|
throw new RuntimeException('仅候选状态可以取消');
|
|
}
|
|
$companyId = $account->company_id;
|
|
$account->delete();
|
|
return $companyId;
|
|
});
|
|
} catch (RuntimeException $exception) {
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, $exception->getMessage()]);
|
|
}
|
|
$this->log('取消企查查企业户候选关系', (string) $companyId);
|
|
return $this->success('已取消候选关系');
|
|
}
|
|
|
|
public function unknownConfirm(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'id' => 'required|integer',
|
|
'decision' => 'required|in:retry,occupied',
|
|
'evidence' => 'required|string|max:2000',
|
|
]);
|
|
if ($validator->fails()) {
|
|
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
|
|
}
|
|
$decision = $request->input('decision');
|
|
$evidence = trim($request->input('evidence'));
|
|
try {
|
|
$account = DB::transaction(function () use ($request, $decision, $evidence) {
|
|
$account = CompanyQccAccount::query()->whereKey($request->input('id'))->lockForUpdate()->first();
|
|
if (!$account || $account->status !== CompanyQccAccount::STATUS_UNKNOWN) {
|
|
throw new RuntimeException('仅未知状态可以人工确认');
|
|
}
|
|
if ($decision === 'occupied') {
|
|
$account->update([
|
|
'status' => CompanyQccAccount::STATUS_OCCUPIED,
|
|
'first_success_at' => now(),
|
|
'first_success_source' => 'manual-confirmation',
|
|
'first_success_ref' => $evidence,
|
|
'unknown_note' => $evidence,
|
|
]);
|
|
} else {
|
|
$account->update(['status' => CompanyQccAccount::STATUS_SELECTED, 'unknown_note' => $evidence]);
|
|
}
|
|
return $account->fresh();
|
|
});
|
|
} catch (RuntimeException $exception) {
|
|
return $this->fail([ResponseCode::ERROR_BUSINESS, $exception->getMessage()]);
|
|
}
|
|
$this->log('人工确认企查查企业户未知状态:' . $decision, $evidence);
|
|
return $this->success($account);
|
|
}
|
|
|
|
protected function log(string $name, string $remark = ''): void
|
|
{
|
|
$admin = $this->getUser();
|
|
if ($admin) {
|
|
OperateLog::addLogs($admin, $name, $remark);
|
|
}
|
|
}
|
|
}
|