diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index f14931e..d385ca0 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -24,7 +24,9 @@
"Write",
"Bash",
"mcp__playwright__browser_console_messages",
- "mcp__playwright__browser_navigate_back"
+ "mcp__playwright__browser_navigate_back",
+ "mcp__playwright__browser_run_code",
+ "mcp__playwright__browser_wait_for"
]
}
}
diff --git a/app/Http/Controllers/ScreeningController.php b/app/Http/Controllers/ScreeningController.php
index 8a3161c..7a8b9b4 100644
--- a/app/Http/Controllers/ScreeningController.php
+++ b/app/Http/Controllers/ScreeningController.php
@@ -4,6 +4,7 @@
namespace App\Http\Controllers;
+use App\Http\Requests\Screening\UpdateScreeningRequest;
use App\Models\Category;
use App\Models\Screening;
use Illuminate\Http\RedirectResponse;
@@ -32,14 +33,20 @@ public function show(Screening $screening): Response
{
return Inertia::render('Screening/Show', [
'screening' => $screening,
+ 'questions' => array_values(config('screening.questions')),
]);
}
/**
* Save screening answers and redirect to result.
*/
- public function update(Request $request, Screening $screening): RedirectResponse
+ public function update(UpdateScreeningRequest $request, Screening $screening): RedirectResponse
{
+ $validated = $request->validated();
+
+ $this->saveAnswers($screening, $validated['answers']);
+ $this->calculateAndUpdateScore($screening, $validated['answers']);
+
return redirect()->route('screening.result', $screening);
}
@@ -50,7 +57,58 @@ public function result(Screening $screening): Response
{
return Inertia::render('Screening/Result', [
'screening' => $screening,
- 'categories' => Category::orderBy('sort_order')->get(['id', 'name']),
+ 'passed' => $screening->passed,
+ 'score' => $screening->score,
+ 'totalQuestions' => count(config('screening.questions')),
+ 'categories' => $screening->passed ? Category::orderBy('sort_order')->get(['id', 'name']) : [],
]);
}
+
+ /**
+ * Save screening answers to the database using upsert pattern.
+ */
+ private function saveAnswers(Screening $screening, array $answers): void
+ {
+ foreach ($answers as $questionNumber => $value) {
+ $screening->answers()->updateOrCreate(
+ [
+ 'screening_id' => $screening->id,
+ 'question_number' => (int) $questionNumber,
+ ],
+ [
+ 'value' => $value,
+ ]
+ );
+ }
+ }
+
+ /**
+ * Calculate the score and update the screening record.
+ */
+ private function calculateAndUpdateScore(Screening $screening, array $answers): void
+ {
+ $score = $this->calculateScore($answers);
+ $passed = $score >= config('screening.passing_score', 5);
+
+ $screening->update([
+ 'score' => $score,
+ 'passed' => $passed,
+ ]);
+ }
+
+ /**
+ * Calculate the total score from the answers.
+ */
+ private function calculateScore(array $answers): int
+ {
+ $score = 0;
+
+ foreach ($answers as $value) {
+ if ($value === 'yes') {
+ $score++;
+ }
+ }
+
+ return $score;
+ }
}
diff --git a/app/Http/Controllers/SessionController.php b/app/Http/Controllers/SessionController.php
index 37d5191..e8697cc 100644
--- a/app/Http/Controllers/SessionController.php
+++ b/app/Http/Controllers/SessionController.php
@@ -4,7 +4,9 @@
namespace App\Http\Controllers;
+use App\Http\Requests\Session\UpdateSessionRequest;
use App\Models\Session;
+use App\Services\ScoringService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
@@ -28,22 +30,89 @@ public function store(Request $request): RedirectResponse
}
/**
- * Display the session questionnaire with category.
+ * Display the session questionnaire with category, question groups, questions, and existing answers.
*/
public function show(Session $session): Response
{
$session->load('category');
+ $questionGroups = $session->category
+ ->questionGroups()
+ ->with(['questions' => fn ($q) => $q->orderBy('sort_order')])
+ ->orderBy('sort_order')
+ ->get();
+
+ $answers = $session->answers()->get()->keyBy('question_id');
+
+ $scoringService = new ScoringService;
+ $score = $scoringService->calculateScore($session);
+
return Inertia::render('Session/Show', [
'session' => $session,
+ 'questionGroups' => $questionGroups,
+ 'answers' => $answers,
+ 'score' => $score,
]);
}
/**
- * Save session answers and redirect to result.
+ * Save session basic info, answers, and additional comments.
*/
- public function update(Request $request, Session $session): RedirectResponse
+ public function update(UpdateSessionRequest $request, Session $session): RedirectResponse
{
+ $validated = $request->validated();
+
+ if (isset($validated['basic_info'])) {
+ $session->update(['basic_info' => $validated['basic_info']]);
+ }
+
+ if (isset($validated['answers'])) {
+ $this->saveAnswers($session, $validated['answers']);
+ }
+
+ if (isset($validated['additional_comments'])) {
+ $session->update(['additional_comments' => $validated['additional_comments']]);
+ }
+
+ if ($request->boolean('complete')) {
+ return $this->completeSession($session);
+ }
+
+ return back();
+ }
+
+ /**
+ * Save or update answers for the session using composite key upsert.
+ */
+ private function saveAnswers(Session $session, array $answers): void
+ {
+ foreach ($answers as $questionId => $answer) {
+ $session->answers()->updateOrCreate(
+ ['question_id' => (int) $questionId],
+ [
+ 'value' => $answer['value'] ?? null,
+ 'text_value' => $answer['text_value'] ?? null,
+ ]
+ );
+ }
+ }
+
+ /**
+ * Complete the session by calculating final score and result.
+ */
+ private function completeSession(Session $session): RedirectResponse
+ {
+ $scoringService = new ScoringService;
+ $score = $scoringService->calculateScore($session);
+ $result = $scoringService->determineResult($score);
+
+ $session->update([
+ 'score' => $score,
+ 'result' => $result,
+ 'status' => 'completed',
+ 'completed_at' => now(),
+ ]);
+
return redirect()->route('sessions.result', $session);
}
@@ -52,8 +121,13 @@ public function update(Request $request, Session $session): RedirectResponse
*/
public function result(Session $session): Response
{
+ $session->load('category');
+
return Inertia::render('Session/Result', [
'session' => $session,
+ 'score' => $session->score,
+ 'result' => $session->result,
+ 'categoryName' => $session->category->name,
]);
}
}
diff --git a/app/Http/Requests/Screening/UpdateScreeningRequest.php b/app/Http/Requests/Screening/UpdateScreeningRequest.php
new file mode 100644
index 0000000..8e9ccba
--- /dev/null
+++ b/app/Http/Requests/Screening/UpdateScreeningRequest.php
@@ -0,0 +1,46 @@
+|string>
+ */
+ public function rules(): array
+ {
+ return [
+ 'answers' => ['required', 'array', 'size:10'],
+ 'answers.*' => ['required', 'string', 'in:yes,no'],
+ ];
+ }
+
+ /**
+ * Custom validation messages.
+ */
+ public function messages(): array
+ {
+ return [
+ 'answers.required' => 'All screening questions must be answered.',
+ 'answers.array' => 'Answers must be provided as an array.',
+ 'answers.size' => 'All 10 screening questions must be answered.',
+ 'answers.*.required' => 'Each screening question must have an answer.',
+ 'answers.*.string' => 'Each answer must be a valid text value.',
+ 'answers.*.in' => 'Each answer must be either "yes" or "no".',
+ ];
+ }
+}
diff --git a/app/Http/Requests/Session/UpdateSessionRequest.php b/app/Http/Requests/Session/UpdateSessionRequest.php
new file mode 100644
index 0000000..eac5dba
--- /dev/null
+++ b/app/Http/Requests/Session/UpdateSessionRequest.php
@@ -0,0 +1,67 @@
+ ['sometimes', 'required', 'array'],
+ 'basic_info.client_name' => ['required_with:basic_info', 'string', 'max:255'],
+ 'basic_info.client_contact' => ['required_with:basic_info', 'string', 'max:255'],
+ 'basic_info.lead_firm_name' => ['required_with:basic_info', 'string', 'max:255'],
+ 'basic_info.lead_firm_contact' => ['required_with:basic_info', 'string', 'max:255'],
+ 'answers' => ['sometimes', 'array'],
+ 'answers.*.value' => ['nullable', 'string', 'in:yes,no,not_applicable'],
+ 'answers.*.text_value' => ['nullable', 'string', 'max:10000'],
+ 'additional_comments' => ['sometimes', 'nullable', 'string', 'max:10000'],
+ 'complete' => ['sometimes', 'boolean'],
+ ];
+ }
+
+ /**
+ * Custom validation messages.
+ */
+ public function messages(): array
+ {
+ return [
+ 'basic_info.required' => 'Basic information is required.',
+ 'basic_info.array' => 'Basic information must be a valid data structure.',
+ 'basic_info.client_name.required_with' => 'The client name is required.',
+ 'basic_info.client_name.string' => 'The client name must be text.',
+ 'basic_info.client_name.max' => 'The client name cannot exceed 255 characters.',
+ 'basic_info.client_contact.required_with' => 'The client contact is required.',
+ 'basic_info.client_contact.string' => 'The client contact must be text.',
+ 'basic_info.client_contact.max' => 'The client contact cannot exceed 255 characters.',
+ 'basic_info.lead_firm_name.required_with' => 'The lead firm name is required.',
+ 'basic_info.lead_firm_name.string' => 'The lead firm name must be text.',
+ 'basic_info.lead_firm_name.max' => 'The lead firm name cannot exceed 255 characters.',
+ 'basic_info.lead_firm_contact.required_with' => 'The lead firm contact is required.',
+ 'basic_info.lead_firm_contact.string' => 'The lead firm contact must be text.',
+ 'basic_info.lead_firm_contact.max' => 'The lead firm contact cannot exceed 255 characters.',
+ 'answers.array' => 'Answers must be a valid data structure.',
+ 'answers.*.value.in' => 'Answer value must be yes, no, or not_applicable.',
+ 'answers.*.text_value.string' => 'Answer text must be text.',
+ 'answers.*.text_value.max' => 'Answer text cannot exceed 10000 characters.',
+ 'additional_comments.string' => 'Additional comments must be text.',
+ 'additional_comments.max' => 'Additional comments cannot exceed 10000 characters.',
+ 'complete.boolean' => 'The complete flag must be true or false.',
+ ];
+ }
+}
diff --git a/app/Services/ScoringService.php b/app/Services/ScoringService.php
new file mode 100644
index 0000000..c7cd772
--- /dev/null
+++ b/app/Services/ScoringService.php
@@ -0,0 +1,37 @@
+answers()
+ ->whereHas('question', fn ($q) => $q->where('is_scored', true))
+ ->where('value', 'yes')
+ ->count();
+ }
+
+ /**
+ * Determine the result based on the score.
+ */
+ public function determineResult(int $score): string
+ {
+ if ($score >= 10) {
+ return 'go';
+ }
+
+ if ($score >= 5) {
+ return 'consult_leadership';
+ }
+
+ return 'no_go';
+ }
+}
diff --git a/config/screening.php b/config/screening.php
new file mode 100644
index 0000000..b2998a2
--- /dev/null
+++ b/config/screening.php
@@ -0,0 +1,42 @@
+ [
+ 1 => 'Is the opportunity aligned with our strategic goals?',
+ 2 => 'Do we have the necessary expertise to deliver?',
+ 3 => 'Is the client financially stable?',
+ 4 => 'Are there no significant conflicts of interest?',
+ 5 => 'Is the timeline realistic?',
+ 6 => 'Do we have available resources?',
+ 7 => 'Is the expected fee reasonable for the scope?',
+ 8 => 'Are the client\'s expectations manageable?',
+ 9 => 'Have we successfully completed similar engagements?',
+ 10 => 'Is the risk level acceptable?',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Passing Score Threshold
+ |--------------------------------------------------------------------------
+ |
+ | Minimum score required to proceed to category selection.
+ |
+ */
+
+ 'passing_score' => 5,
+
+];
diff --git a/database/seeders/CategorySeeder.php b/database/seeders/CategorySeeder.php
new file mode 100644
index 0000000..51cb528
--- /dev/null
+++ b/database/seeders/CategorySeeder.php
@@ -0,0 +1,35 @@
+ 'Audit', 'sort_order' => 1],
+ ['name' => 'Outsource', 'sort_order' => 2],
+ ['name' => 'Solution', 'sort_order' => 3],
+ ['name' => 'Digital Solutions', 'sort_order' => 4],
+ ['name' => 'Legal', 'sort_order' => 5],
+ ['name' => 'Tax', 'sort_order' => 6],
+ ];
+
+ foreach ($categories as $category) {
+ DB::table('categories')->insert([
+ 'name' => $category['name'],
+ 'sort_order' => $category['sort_order'],
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+ }
+ }
+}
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
index 41ba990..3b26ff2 100644
--- a/database/seeders/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -1,11 +1,13 @@
call(JonathanSeeder::class);
+ $this->call([
+ JonathanSeeder::class,
+ CategorySeeder::class,
+ QuestionSeeder::class,
+ ]);
}
}
diff --git a/database/seeders/QuestionSeeder.php b/database/seeders/QuestionSeeder.php
new file mode 100644
index 0000000..c4af96c
--- /dev/null
+++ b/database/seeders/QuestionSeeder.php
@@ -0,0 +1,1761 @@
+seedAuditQuestions();
+ $this->seedOutsourceQuestions();
+ $this->seedDigitalSolutionsQuestions();
+ $this->seedLegalQuestions();
+ $this->seedTaxQuestions();
+ }
+
+ /**
+ * Seed questions for Audit category.
+ */
+ private function seedAuditQuestions(): void
+ {
+ $categoryId = DB::table('categories')->where('name', 'Audit')->value('id');
+
+ // Group 1: Opportunity Details (NOT scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Opportunity Details',
+ 'sort_order' => 1,
+ 'description' => null,
+ 'scoring_instructions' => null,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What sort of audit opportunity is it?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 1,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'How many locations involved in this opportunity?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 2,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'List any locations included in this opportunity where we do not have a Baker Tilly firm.',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 3,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Where is the client HQ?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 4,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Who is the competition?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 5,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 2: Client Background and History (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Client Background and History',
+ 'sort_order' => 2,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What is the client\'s business and industry?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 1,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'There have been no significant changes in the client\'s business operations or structure recently?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_no',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Does the sector and/or client come with a reputation which we are comfortable that Baker Tilly is associated with?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any previous audit reports or findings that need to be considered?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 4,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 3: Financial Information (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Financial Information',
+ 'sort_order' => 3,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Has the client provided financial statements or balance sheet?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are the client\'s financial statements complete and accurate?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 4: Regulatory Compliance (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Regulatory Compliance',
+ 'sort_order' => 4,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Does the client comply with all relevant regulatory requirements and standards?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_no',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'The client has no pending legal or regulatory issues that you know of that could impact the audit?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_no',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'The client has been subject to no regulatory investigations or penalties?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_no',
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 5: Risk Assessment (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Risk Assessment',
+ 'sort_order' => 5,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'There are no key risks associated with the audit?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_no',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Have you completed a conflict check?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'required',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are you and other BTI member firms independent with the meaning of local and IESBA rules?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_no',
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 6: Resource Allocation (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Resource Allocation',
+ 'sort_order' => 6,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What resources are required for the audit (personnel, time, budget)?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Does your firm have the scale, seniority and degree of expertise available at the right time to report in accordance with the client\'s schedule?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 7: Reporting Requirements (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Reporting Requirements',
+ 'sort_order' => 7,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do we understand reporting rules, regulatory environment and stakeholder expectations?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+ }
+
+ /**
+ * Seed questions for Outsource category.
+ */
+ private function seedOutsourceQuestions(): void
+ {
+ $categoryId = DB::table('categories')->where('name', 'Outsource')->value('id');
+
+ // Group 1: Opportunity Details (NOT scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Opportunity Details',
+ 'sort_order' => 1,
+ 'description' => null,
+ 'scoring_instructions' => null,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What sort of outsourcing opportunity is it?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 1,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'How many locations involved in this opportunity?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 2,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'List any locations included in this opportunity where we do not have a Baker Tilly firm.',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 3,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Where is the client HQ?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 4,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What is the client\'s business and industry?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 5,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Who are the competitors in this space?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 6,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 2: Client Background and History (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Client Background and History',
+ 'sort_order' => 2,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Have we previously worked with this client, and was the experience positive?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Have we conducted a reputational risk check on the client (negative press, ethical concerns, etc.)?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 3: Regulatory Compliance (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Regulatory Compliance',
+ 'sort_order' => 3,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Does the client comply with all relevant regulatory requirements?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Has the client provided complete and accurate financial records for review?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Does the client have no pending legal, tax or regulatory issues that [you know of] which could impact this opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 4: Risk Assessment (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Risk Assessment',
+ 'sort_order' => 4,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Is there a clear understanding on the scope, responsibilities and deliverables?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do we have the necessary delivery tools (platforms, technology, security measures etc.) to support this opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Have you completed a conflict check?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Can we meet the service-level agreements (SLAs) without overcommitting our resources?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 4,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there no special expectations or requirements from the client that may pose a challenge?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 5,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 5: Resource Allocation (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Resource Allocation',
+ 'sort_order' => 5,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do you have the resources required for the opportunity (personnel, time, budget)?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do you have the right expertise and capacity across our network to deliver high-quality service?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+ }
+
+ /**
+ * Seed questions for Digital Solutions category.
+ */
+ private function seedDigitalSolutionsQuestions(): void
+ {
+ $categoryId = DB::table('categories')->where('name', 'Digital Solutions')->value('id');
+
+ // Group 1: Opportunity Details (NOT scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Opportunity Details',
+ 'sort_order' => 1,
+ 'description' => null,
+ 'scoring_instructions' => null,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What sort of digital consulting opportunity is it?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 1,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'How many locations involved in this opportunity and are there any locations where we do not have digital capabilities in the local Baker Tilly firm.',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 2,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Where is the client HQ? please share more about the clients industry and digital maturity level.',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 3,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Who are the competitors in this space?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 4,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 2: Client Background and History (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Client Background and History',
+ 'sort_order' => 2,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Have we previously worked with this client, and was the experience positive?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Have we conducted a reputational risk check on the client (negative press, ethical concerns, etc.)?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 3: Regulatory Compliance (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Regulatory Compliance',
+ 'sort_order' => 3,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Does the project involve cross-border data transfers, and if so, are necessary safeguards in place?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Does the client have no pending legal, tax or regulatory issues that [you know of] which could impact this opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 4: Risk Assessment (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Risk Assessment',
+ 'sort_order' => 4,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Is there a clear understanding of the project scope, responsibilities, and deliverables?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do we have the necessary delivery tools (platforms, technology, security measures etc.) to support this opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Have we completed a conflict check?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Can we meet the service-level agreements (SLAs) without overcommitting our resources?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 4,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there no special expectations or requirements from the client that may pose a challenge?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 5,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 5: Resource Allocation (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Resource Allocation',
+ 'sort_order' => 5,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do you have the resources required for the opportunity (personnel, time, budget)?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do you have the right expertise and capacity across our network to deliver high-quality service?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 6: Technology & Innovation Fit (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Technology & Innovation Fit',
+ 'sort_order' => 6,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point; if you answer no, you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are the technologies involved within our area of expertise, or do we have partnerships to support the implementation?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => null,
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+ }
+
+ /**
+ * Seed questions for Legal category.
+ */
+ private function seedLegalQuestions(): void
+ {
+ $categoryId = DB::table('categories')->where('name', 'Legal')->value('id');
+
+ // Group 1: Opportunity Details (mixed scored and non-scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Opportunity Details',
+ 'sort_order' => 1,
+ 'description' => null,
+ 'scoring_instructions' => null,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What type of legal opportunity is it (e.g., litigation, corporate, M&A, regulatory)?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 1,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'How many locations involved in this opportunity?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 2,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do we have a presence or a reliable partner in all locations listed in this opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_no',
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Is the client budget realistic?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 4,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Has the client requested any additional information from our firms?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'required',
+ 'sort_order' => 5,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What is the deadline to respond to the client on this opportunity?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 6,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Where is the client HQ?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 7,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Who is the competition?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 8,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 2: Client Background and History (mixed)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Client Background and History',
+ 'sort_order' => 2,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What is the client\'s business and industry?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 1,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Have there been any significant changes in the client\'s business operations or structure recently?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What is our competitive edge in this opportunity (e.g., prior experience with the client, unique expertise, pricing advantage)?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'required',
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 3: Financial Information (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Financial Information',
+ 'sort_order' => 3,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Has the client provided enough financial information about their company?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any significant financial risks or uncertainties that you are aware of?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 4: Regulatory Compliance (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Regulatory Compliance',
+ 'sort_order' => 4,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any pending legal or regulatory issues that you know of that could impact the opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Has the client been subject to any regulatory investigations or penalties?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 5: Risk Assessment for Legal Opportunities (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Risk Assessment for Legal Opportunities',
+ 'sort_order' => 5,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any potential risks or challenges associated with the opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Has a conflict check been completed?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any potential conflicts of interest?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 6: Resource Allocation (mixed)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Resource Allocation',
+ 'sort_order' => 6,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do we have the required skills and capacity within our firm to deliver this work, or would we need support from another firm?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What resources are required for the opportunity (personnel, time, budget)?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any constraints on the availability of your resources?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do you know of the any constraints on the availability of other firms included in this opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 4,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Is the deadline to respond to the client is more than two weeks away. Our experience shows that anything shorter is often unrealistic to pursue.',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 5,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 7: Stakeholder Engagement (mixed)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Stakeholder Engagement',
+ 'sort_order' => 7,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Who are the key stakeholders involved in this opportunity?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 1,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any special expectations and requirements?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 8: Fee Quote (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Fee Quote',
+ 'sort_order' => 8,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Has the client provided sufficient information to enable a fee quote?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+ }
+
+ /**
+ * Seed questions for Tax category.
+ */
+ private function seedTaxQuestions(): void
+ {
+ $categoryId = DB::table('categories')->where('name', 'Tax')->value('id');
+
+ // Group 1: Opportunity Details (mixed)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Opportunity Details',
+ 'sort_order' => 1,
+ 'description' => null,
+ 'scoring_instructions' => null,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What sort of opportunity is it?/Describe the Scope of Work',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 1,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'How many locations involved in this opportunity?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 2,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do we have a Baker Tilly firm in all locations within this opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_no',
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Has the client requested any additional information from our firms?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'required',
+ 'sort_order' => 4,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What is the deadline to respond to the client on this opportunity?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 5,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Where is the client HQ?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 6,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Who is the competition?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 7,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 2: Client Background and History (mixed)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Client Background and History',
+ 'sort_order' => 2,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What is the client\'s business and industry?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 1,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Have there been any significant changes in the client\'s business operations or structure recently?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Is the client an existing client?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'required',
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 3: Financial Information (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Financial Information',
+ 'sort_order' => 3,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Has the client provided enough financial information about their company?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any significant financial risks or uncertainties that you are aware of?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 4: Regulatory Compliance (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Regulatory Compliance',
+ 'sort_order' => 4,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Does the client comply with all relevant regulatory requirements and standards?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_no',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any pending legal or regulatory issues that you know of that could impact the opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Has the client been subject to any regulatory investigations or penalties?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 5: Risk Assessment (scored)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Risk Assessment',
+ 'sort_order' => 5,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any potential risks or challenges associated with the opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any potential conflicts of interest?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'req_on_yes',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 6: Resource Allocation (mixed)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Resource Allocation',
+ 'sort_order' => 6,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What resources are required for the opportunity (personnel, time, budget)?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 1,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any constraints on the availability of your resources?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'optional',
+ 'sort_order' => 2,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Do you know of the any constraints on the availability of other firms included in this opportunity?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 3,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'What is the expected timeline for the opportunity, including any critical deadlines that must be met?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'optional',
+ 'sort_order' => 4,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+
+ // Group 7: Stakeholder Engagement (mixed)
+ $groupId = DB::table('question_groups')->insertGetId([
+ 'category_id' => $categoryId,
+ 'name' => 'Stakeholder Engagement',
+ 'sort_order' => 7,
+ 'description' => null,
+ 'scoring_instructions' => 'If you answer yes, you will score 1 point, if you answer no you will score 0 points',
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ]);
+
+ DB::table('questions')->insert([
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Who are the key stakeholders involved in this opportunity?',
+ 'has_yes' => false,
+ 'has_no' => false,
+ 'has_na' => false,
+ 'details' => 'required',
+ 'sort_order' => 1,
+ 'is_scored' => false,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ [
+ 'question_group_id' => $groupId,
+ 'text' => 'Are there any special expectations and requirements?',
+ 'has_yes' => true,
+ 'has_no' => true,
+ 'has_na' => true,
+ 'details' => 'optional',
+ 'sort_order' => 2,
+ 'is_scored' => true,
+ 'created_at' => now(),
+ 'updated_at' => now(),
+ ],
+ ]);
+ }
+}
diff --git a/resources/js/Components/QuestionCard.vue b/resources/js/Components/QuestionCard.vue
new file mode 100644
index 0000000..b0051fe
--- /dev/null
+++ b/resources/js/Components/QuestionCard.vue
@@ -0,0 +1,119 @@
+
+
+
+ {{ question.text }}
Baker Tilly International Questionnaire Application
++ Baker Tilly International Go/No Go Checklist +
++ This tool helps you evaluate business opportunities through a structured assessment process. + You will first complete a short pre-screening questionnaire, followed by a detailed category-specific checklist + to determine whether to pursue (Go), decline (No Go), or escalate (Consult Leadership) an opportunity. +
Your screening result: Passed
+ ++ {{ score }} / {{ totalQuestions }} +
++ {{ passed ? 'Passed' : 'No Go' }} +
++ {{ passed ? 'You may proceed to select a category for detailed assessment.' : 'The pre-screening score is below the required threshold. You cannot proceed at this time.' }} +
+Answer all 10 questions to proceed. Each "Yes" answer scores 1 point. You need at least 5 points to pass.
-10 Yes/No questions will appear here
+{{ question }}
++ {{ form.errors[`answers.${index + 1}`] }} +
+Your result will appear here
+ ++ {{ score }} points +
++ {{ resultDisplay.description }} +
+Client and lead firm information will appear here
+ +All fields are required before you can proceed to the questionnaire.
+ ++ {{ basicInfoForm.errors['basic_info.client_name'] }} +
++ {{ basicInfoForm.errors['basic_info.client_contact'] }} +
++ {{ basicInfoForm.errors['basic_info.lead_firm_name'] }} +
++ {{ basicInfoForm.errors['basic_info.lead_firm_contact'] }} +
+Category questions will appear here
+{{ group.description }}
+{{ group.scoring_instructions }}
+ +