Skip to content

Instantly share code, notes, and snippets.

@brytey2k
Created July 9, 2025 12:34
Show Gist options
  • Save brytey2k/eff9df60bd4b3ed58f567c35c6131a23 to your computer and use it in GitHub Desktop.
Save brytey2k/eff9df60bd4b3ed58f567c35c6131a23 to your computer and use it in GitHub Desktop.
Simple service to create google form like questions and store answers.
<?php
declare(strict_types=1);
namespace App\Services;
use App\Dto\Appraisal\CreateAppraisalFormResponseAnswerDto;
use App\Dto\Appraisal\CreateAppraisalFormResponseDto;
use App\Enums\StoragePath;
use App\Models\AppraisalFormQuestion;
use App\Models\AppraisalFormResponse;
use App\Models\AppraisalFormResponseAnswer;
use App\Models\Loan;
use App\Models\LoanAppraisal;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
class AppraisalService
{
/**
* @param array $appraisalIds
*
* @return Collection<int, AppraisalFormQuestion>
*/
public function getAppraisalFormQuestionsByIds(array $appraisalIds): Collection
{
return AppraisalFormQuestion::with(['appraisalQuestion'])->whereIn('id', $appraisalIds)->get();
}
/**
* @param Loan $loan
* @param array<string, int|string|UploadedFile|array<string|null>> $formData
* @param Collection<int, AppraisalFormQuestion> $questions
*
* @throws \Throwable
*
* @return LoanAppraisal
*/
public function saveLoanAppraisal(Loan $loan, array $formData, Collection $questions): LoanAppraisal
{
$loan->loadMissing(['stage.appraisalForm']);
return DB::transaction(function () use ($loan, $formData, $questions) {
$formResponse = $this->createAppraisalFormResponse(new CreateAppraisalFormResponseDto($loan->stage->appraisalForm, auth()->user(), now()));
foreach ($formData as $key => $value) {
$filePath = null;
$answer = $value;
if ($value instanceof UploadedFile) {
$fileName = Str::uuid7()->toString() . '.' . $value->getClientOriginalExtension();
$filePath = $value->storePubliclyAs(StoragePath::LOAN_APPRAISAL_FILES->value, $fileName, 'public');
$answer = null;
}
if (is_array($answer)) {
if ($answer[0] === null) { // this is to deal with hidden input for multiple select to deal input omission for empty array
unset($answer[0]);
}
$answer = rtrim(implode(', ', $answer), ', ');
}
$this->createAppraisalFormResponseAnswer(new CreateAppraisalFormResponseAnswerDto(
$formResponse,
$questions->firstWhere('id', explode('_', $key, 2)[1]),
$answer,
$filePath,
));
}
return $this->createLoanAppraisal($loan, $formResponse);
});
}
public function createAppraisalFormResponse(CreateAppraisalFormResponseDto $appraisalResponseDto): AppraisalFormResponse
{
return AppraisalFormResponse::create($appraisalResponseDto->toArray());
}
public function createAppraisalFormResponseAnswer(CreateAppraisalFormResponseAnswerDto $answerDto): AppraisalFormResponseAnswer
{
return AppraisalFormResponseAnswer::create($answerDto->toArray());
}
public function createLoanAppraisal(Loan $loan, AppraisalFormResponse $appraisalFormResponse): LoanAppraisal
{
$loan->loadMissing(['stage']);
return LoanAppraisal::create([
'loan_id' => $loan->id,
'appraisal_form_response_id' => $appraisalFormResponse->id,
'approval_flow_id' => $loan->stage->id,
]);
}
/**
* @param Collection<int, AppraisalFormQuestion> $questions
* @param array $requestData
*
* @return \Illuminate\Validation\Validator
*/
public function buildAppraisalFormValidator(Collection $questions, array $requestData): \Illuminate\Validation\Validator
{
$rules = [];
$messages = [];
$questions->each(static function (AppraisalFormQuestion $appraisalFormQuestion) use (&$rules, &$messages) {
$rules['question_' . $appraisalFormQuestion->id] = $appraisalFormQuestion->appraisalQuestion->answer_type->baseValidationRules();
foreach ($appraisalFormQuestion->appraisalQuestion->answer_type->baseValidationMessages() as $rule => $message) {
$messages['question_' . $appraisalFormQuestion->id . '.' . $rule] = sprintf($message, $appraisalFormQuestion->appraisalQuestion->question);
}
if ($appraisalFormQuestion->isRequired()) {
$rules['question_' . $appraisalFormQuestion->id][] = 'required';
$messages['question_' . $appraisalFormQuestion->id . '.required'] = sprintf('Field "%s" is required', $appraisalFormQuestion->appraisalQuestion->question);
} else {
$rules['question_' . $appraisalFormQuestion->id][] = 'nullable';
}
});
return Validator::make($requestData, $rules, $messages);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment