From 0b6c6736ef5c59b4d03135c3383e190419398aa9 Mon Sep 17 00:00:00 2001 From: Jonathan van Rij Date: Tue, 3 Feb 2026 10:50:56 +0100 Subject: [PATCH] plan implementation 6, 7, 8, 9, 10 --- .claude/settings.local.json | 4 +- app/Http/Controllers/ScreeningController.php | 62 +- app/Http/Controllers/SessionController.php | 80 +- .../Screening/UpdateScreeningRequest.php | 46 + .../Requests/Session/UpdateSessionRequest.php | 67 + app/Services/ScoringService.php | 37 + config/screening.php | 42 + database/seeders/CategorySeeder.php | 35 + database/seeders/DatabaseSeeder.php | 10 +- database/seeders/QuestionSeeder.php | 1761 +++++++++++++++++ resources/js/Components/QuestionCard.vue | 119 ++ resources/js/Pages/Landing.vue | 9 +- resources/js/Pages/Screening/Result.vue | 59 +- resources/js/Pages/Screening/Show.vue | 68 +- resources/js/Pages/Session/Result.vue | 91 +- resources/js/Pages/Session/Show.vue | 219 +- 16 files changed, 2665 insertions(+), 44 deletions(-) create mode 100644 app/Http/Requests/Screening/UpdateScreeningRequest.php create mode 100644 app/Http/Requests/Session/UpdateSessionRequest.php create mode 100644 app/Services/ScoringService.php create mode 100644 config/screening.php create mode 100644 database/seeders/CategorySeeder.php create mode 100644 database/seeders/QuestionSeeder.php create mode 100644 resources/js/Components/QuestionCard.vue 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 @@ + + + diff --git a/resources/js/Pages/Landing.vue b/resources/js/Pages/Landing.vue index f0574a8..998d8a3 100644 --- a/resources/js/Pages/Landing.vue +++ b/resources/js/Pages/Landing.vue @@ -16,7 +16,14 @@ const handleContinue = () => {

Go / No Go

-

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. +

Continue diff --git a/resources/js/Pages/Screening/Result.vue b/resources/js/Pages/Screening/Result.vue index 4a823f7..d75e952 100644 --- a/resources/js/Pages/Screening/Result.vue +++ b/resources/js/Pages/Screening/Result.vue @@ -10,6 +10,18 @@ const props = defineProps({ type: Object, required: true, }, + passed: { + type: Boolean, + required: true, + }, + score: { + type: Number, + required: true, + }, + totalQuestions: { + type: Number, + required: true, + }, categories: { type: Array, required: true, @@ -28,23 +40,44 @@ const handleStartCategory = (categoryId) => {
-

Screening Result

+

Pre-Screening Result

-
-

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.' }} +

+
-
+ +
+ + Again + +
+ + +

Select a Category

-
- {{ category.name }} - - Start - +
+
+ {{ category.name }} + + Start + +
diff --git a/resources/js/Pages/Screening/Show.vue b/resources/js/Pages/Screening/Show.vue index 1e094cc..bebea7e 100644 --- a/resources/js/Pages/Screening/Show.vue +++ b/resources/js/Pages/Screening/Show.vue @@ -1,5 +1,6 @@