204 lines
9.2 KiB
PHP
204 lines
9.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
|
|
use App\Models\Inquiry;
|
|
use Illuminate\Support\Str;
|
|
|
|
class LandingInquiryController extends Controller
|
|
{
|
|
public function store(Request $request)
|
|
{
|
|
// Honeypot Bot Check
|
|
if ($request->filled('hp_website')) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Spam submission detected.',
|
|
], 422);
|
|
}
|
|
|
|
$desiredSubdomain = Str::slug($request->desired_subdomain);
|
|
$request->merge(['desired_subdomain' => $desiredSubdomain]);
|
|
|
|
$allowedModules = \App\Constants\ModuleContract::getAllInquiryKeys();
|
|
|
|
// Find existing inquiry by email to allow resubmissions by same user
|
|
$existingInquiry = Inquiry::where('email', $request->email)->first();
|
|
|
|
// Prevent modifying subdomain slug if inquiry was already approved or activated
|
|
if ($existingInquiry && in_array($existingInquiry->status, ['approved', 'active', 'provisioning'])) {
|
|
if ($existingInquiry->desired_subdomain !== $desiredSubdomain) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Your subdomain request has already been approved. Subdomain slug cannot be altered.',
|
|
], 422);
|
|
}
|
|
}
|
|
|
|
$ignoreInquiryId = $existingInquiry ? $existingInquiry->id : null;
|
|
|
|
$request->validate([
|
|
'company_name' => 'required|string|max:255',
|
|
'contact_name' => 'required|string|max:255',
|
|
'email' => 'required|email|max:255',
|
|
'phone' => 'nullable|string|max:50',
|
|
'desired_subdomain' => [
|
|
'required',
|
|
'string',
|
|
'max:50',
|
|
'alpha_dash',
|
|
function ($attribute, $value, $fail) use ($ignoreInquiryId) {
|
|
$slug = Str::slug($value);
|
|
if (\App\Models\Tenant::where('id', $slug)->exists()) {
|
|
$fail(__('This desired subdomain is already in use by an active tenant. Please choose a different subdomain.'));
|
|
}
|
|
if (\Stancl\Tenancy\Database\Models\Domain::where('domain', 'LIKE', $slug . '.%')->orWhere('domain', $slug)->exists()) {
|
|
$fail(__('This desired subdomain is already in use by an active domain. Please choose a different subdomain.'));
|
|
}
|
|
$inquiryQuery = Inquiry::where('desired_subdomain', $slug);
|
|
if ($ignoreInquiryId) {
|
|
$inquiryQuery->where('id', '!=', $ignoreInquiryId);
|
|
}
|
|
if ($inquiryQuery->exists()) {
|
|
$fail(__('This desired subdomain is already reserved or requested. Please choose a different subdomain slug.'));
|
|
}
|
|
},
|
|
],
|
|
'employee_count' => 'nullable|integer|min:1|max:10000',
|
|
'requested_features' => 'nullable|array',
|
|
'requested_features.*' => 'string|in:' . implode(',', $allowedModules),
|
|
'notes' => 'nullable|string|max:2000',
|
|
'payment_reference' => 'nullable|string|max:255',
|
|
], [
|
|
'requested_features.*.in' => 'One or more selected modules are invalid.',
|
|
]);
|
|
|
|
$verificationCode = (string) rand(100000, 999999);
|
|
|
|
// Store pending submission payload in Cache for 1 hour until email OTP is verified
|
|
$cacheKey = 'pending_inquiry_' . md5(strtolower($request->email));
|
|
\Illuminate\Support\Facades\Cache::put($cacheKey, [
|
|
'email' => $request->email,
|
|
'company_name' => $request->company_name,
|
|
'contact_name' => $request->contact_name,
|
|
'phone' => $request->phone,
|
|
'desired_subdomain' => $desiredSubdomain,
|
|
'employee_count' => $request->employee_count ?? 10,
|
|
'requested_features' => $request->requested_features ?? [],
|
|
'notes' => $request->notes ? Str::limit($request->notes, 2000, '...') : null,
|
|
'payment_reference' => $request->payment_reference ?? 'SUBDOMAIN-INQUIRY-WIZARD',
|
|
'verification_code' => $verificationCode,
|
|
], now()->addHour());
|
|
|
|
// Dispatch verification code email to inquiring user
|
|
try {
|
|
\Illuminate\Support\Facades\Mail::to($request->email)->send(
|
|
new \App\Mail\InquiryVerificationCodeMail($request->company_name, $verificationCode)
|
|
);
|
|
} catch (\Exception $e) {
|
|
\Illuminate\Support\Facades\Log::warning("Could not send verification email to {$request->email}: " . $e->getMessage());
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'requires_verification' => true,
|
|
'verification_code' => config('app.env') === 'testing' || config('app.debug') ? $verificationCode : null,
|
|
'message' => 'Subdomain inquiry details validated! Please enter the 6-digit verification code sent to your email to complete submission.',
|
|
], 200);
|
|
}
|
|
|
|
public function verifyEmail(Request $request)
|
|
{
|
|
$request->validate([
|
|
'email' => 'required|email',
|
|
'verification_code' => 'required|string',
|
|
]);
|
|
|
|
$cacheKey = 'pending_inquiry_' . md5(strtolower($request->email));
|
|
$pendingData = \Illuminate\Support\Facades\Cache::get($cacheKey);
|
|
|
|
if (!$pendingData) {
|
|
// Check if existing verified inquiry exists
|
|
$existing = Inquiry::where('email', $request->email)->first();
|
|
if ($existing && $existing->email_verified_at) {
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Your email has already been verified.',
|
|
'data' => $existing,
|
|
]);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Verification session expired or no pending submission found. Please resubmit the inquiry form.',
|
|
], 422);
|
|
}
|
|
|
|
if ($pendingData['verification_code'] !== trim($request->verification_code)) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Invalid verification code. Please check your email and try again.',
|
|
], 422);
|
|
}
|
|
|
|
// Save / Update Inquiry DB record ONLY after successful OTP verification!
|
|
$existingInquiry = Inquiry::where('email', $pendingData['email'])->first();
|
|
|
|
if ($existingInquiry) {
|
|
$inquiry = $existingInquiry;
|
|
$combinedNotes = $pendingData['notes']
|
|
? ($existingInquiry->notes ? $existingInquiry->notes . "\n---\n" . $pendingData['notes'] : $pendingData['notes'])
|
|
: $existingInquiry->notes;
|
|
|
|
$inquiry->update([
|
|
'company_name' => $pendingData['company_name'],
|
|
'contact_name' => $pendingData['contact_name'],
|
|
'phone' => $pendingData['phone'],
|
|
'desired_subdomain' => $pendingData['desired_subdomain'],
|
|
'employee_count' => $pendingData['employee_count'],
|
|
'requested_features' => $pendingData['requested_features'],
|
|
'notes' => Str::limit($combinedNotes, 2000, ''),
|
|
'verification_code' => null,
|
|
'email_verified_at' => now(),
|
|
'payment_reference' => $pendingData['payment_reference'] ?? $existingInquiry->payment_reference,
|
|
'status' => 'pending_payment_approval',
|
|
]);
|
|
} else {
|
|
$inquiry = Inquiry::create([
|
|
'email' => $pendingData['email'],
|
|
'company_name' => $pendingData['company_name'],
|
|
'contact_name' => $pendingData['contact_name'],
|
|
'phone' => $pendingData['phone'],
|
|
'desired_subdomain' => $pendingData['desired_subdomain'],
|
|
'employee_count' => $pendingData['employee_count'],
|
|
'requested_features' => $pendingData['requested_features'],
|
|
'notes' => $pendingData['notes'],
|
|
'verification_code' => null,
|
|
'email_verified_at' => now(),
|
|
'payment_reference' => $pendingData['payment_reference'],
|
|
'status' => 'pending_payment_approval',
|
|
]);
|
|
}
|
|
|
|
// Create matching Contact history entry ONLY after successful OTP verification!
|
|
\App\Models\Contact::create([
|
|
'email' => $pendingData['email'],
|
|
'name' => $pendingData['contact_name'],
|
|
'subject' => 'Subdomain Inquiry: ' . $pendingData['company_name'] . ' (' . $pendingData['desired_subdomain'] . ')',
|
|
'message' => $pendingData['notes'] ?? ('Subdomain request for ' . $pendingData['company_name'] . ' with ' . $pendingData['employee_count'] . ' employees.'),
|
|
'status' => 'New',
|
|
]);
|
|
|
|
\Illuminate\Support\Facades\Cache::forget($cacheKey);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Email verified and inquiry submitted successfully! Your subdomain request is ready for Executive approval.',
|
|
'data' => $inquiry,
|
|
]);
|
|
}
|
|
}
|