File: /var/www/vhost/disk-apps/comfama.sports-crowd.com/app/Services/ExperienceService.php
<?php
namespace App\Services;
use App\Models\Experience\Experience;
use App\Models\Experience\ExperiencePayment;
use App\Models\Experience\ExperiencePlanPrice;
use App\Models\Experience\ExperienceUser;
use App\Http\Controllers\PushNotificationController;
use App\Http\Controllers\ServiceChargeController;
use DateInterval;
use DateTime;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
class ExperienceService
{
private $academyService;
public function __construct()
{
$this->academyService = new AcademyService;
}
public function get(Request $request)
{
$experiences = Experience::select(
'experiences.id',
'experiences.name',
'experiences.icon',
'experiences.short_description',
)->where('experiences.active', 1)
->where('experiences.experience_type', $request->type)
->whereHas('plans')->orwhereHas('academy_plans')
->get();
return $experiences;
}
public function detail(Request $request)
{
$query = Experience::select(
'experiences.id',
'experiences.name',
'experiences.icon',
'experiences.description',
'experiences.apply_to',
'experiences.includes',
'experiences.when',
)->with('plans', 'plans.prices');
if ($this->validateAcademyStudents()) {
$query->with('academy_plans', 'academy_plans.prices');
}
$experience = $query->findorFail($request->id);
if ($experience && $experience->plans) {
$uniquePlan = true;
foreach ($experience->plans as $plan) {
if ($plan->prices && $plan->prices->count() > 1) {
$uniquePlan = false;
break;
}
}
$experience->unique_plan = $uniquePlan;
}
return $experience;
}
public function payments(Request $request)
{
DB::statement("SET sql_mode = ''");
$payments = ExperiencePayment::select(
'experience_payments.id',
'experiences.name AS name',
'experiences.icon AS icon',
'experience_payments.description AS plan',
DB::raw('IFNULL(payment_transactions.payment_date, "") AS payment_date'),
'experience_payments.subtotal',
'experience_payments.service_charge',
'experience_payments.total',
'experience_users.name AS student',
'experience_users.document AS document',
'experience_payments.payment_due_date',
DB::raw('IF(experience_payments.payment_due_date IS NOT NULL, experience_payments.payment_due_date >= CURDATE(), true) AS active',),
DB::raw('IF(payment_transactions.state = "CONFIRMED", true, false) AS confirmed'),
DB::raw('true AS enable_pay'),
DB::raw('true AS enable_renew'),
)
->leftjoin('payment_transactions', 'payment_transactions.id', '=', 'experience_payments.payment_transaction_id')
->join('experience_users', 'experience_users.id', '=', 'experience_payments.experience_user_id')
->join('experience_plan_prices', 'experience_plan_prices.experience_plan_id', '=', 'experience_payments.experience_plan_price_id')
->join('experience_plans', 'experience_plans.id', '=', 'experience_plan_prices.experience_plan_id')
->join('experiences', 'experiences.id', '=', 'experience_plans.experience_id')
->where('experience_users.experience_type', $request->type)
->where('experience_users.user_id', Auth::user()->id)
->groupBy('experience_payments.id')
->orderBy('active', 'DESC')
->orderBy('experience_payments.id', 'DESC')
->get();
DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");
return $payments;
}
public function enroll(Request $request)
{
$data = $this->getData($request);
$validation = $this->validateData($data);
$validation = json_decode(json_encode($validation), true);
if ($validation && !$validation['original']['r']) {
return $validation['original'];
}
$experienceUser = $this->createExperienceUser($data);
$payment = $this->createPayment($data, $experienceUser);
return response(array('r' => true, 'd' => $payment));
}
public function renew(Request $request)
{
$data = $this->getData($request);
$experiencePaymentId = $data['experiencePaymentId'];
$payment = $this->renewPayment($experiencePaymentId);
return response(array('r' => true, 'd' => $payment));
}
public function students(Request $request)
{
$students = [];
if ($request->planType == 'academy') {
$students = $this->academyStudents();
} else {
$students = ExperienceUser::select(
'experience_users.name',
'document_types.alias AS document_type',
'document',
)->join('document_types', 'document_types.id', '=', 'experience_users.document_type_id')
->where('user_id', Auth::user()->id)
->where('experience_type', $request->type)
->orderBy('name', 'ASC')
->get();
if (count($students)) {
$students[] = [
'name' => 'Nuevo',
'document' => 0
];
}
}
return $students;
}
public function guardians(Request $request)
{
$guardians = ExperienceUser::select(
'guardian_name',
'guardian_document',
'guardian_email',
'guardian_phone',
)->where('user_id', Auth::user()->id)
->where('experience_type', $request->type)
->whereNotNull('guardian_document')
->groupBy([
'guardian_name',
'guardian_document',
'guardian_email',
'guardian_phone'
])
->orderBy('guardian_name', 'ASC')
->get();
return $guardians;
}
public function finishPayment($paymentTransaction)
{
if ($paymentTransaction->state == 'CONFIRMED') {
$experiencePayment = ExperiencePayment::with('experience_user', 'payment_transaction')->where('payment_transaction_id', $paymentTransaction->id)->first();
$experienceUser = $experiencePayment->experience_user;
$user = $experienceUser->user;
$this->updatePaymentDueDate($experiencePayment);
$message = 'Se confirma pago ' . $paymentTransaction->reference . ', asociado al Pago Experiencia ' . $experiencePayment->description . ' estudiante: ' . $experienceUser->name . ' (' . $experienceUser->document . ')';
$push = new PushNotificationController();
$push->sendToUser($message, $user->pns_id, null, null, null, null, 'U');
// $this->syncERP($academyTournamentPayment);
}
}
private function updatePaymentDueDate($experiencePayment)
{
$experiencePayment->payment_due_date = \Carbon\Carbon::now()->addDays($experiencePayment->experience_plan_price->duration)->toDateString();
$experiencePayment->save();
}
private function validateData($data)
{
// Agregar validaciones de informacioĢn y si ya existe el estudiante
if (!isset($data['plan']) || ExperiencePlanPrice::find($data['plan']['id']) == null) {
return response(array('r' => false, 'm' => 'No existe un plan de experiencia seleccionado/disponible'));
}
if ($data['document'] && ExperienceUser::where('document', $data['document'])->where('user_id', '!=', Auth::user()->id)->exists()) {
return response(array('r' => false, 'm' => 'Ya existe un estudiante registrado con este documento'));
}
return response(array('r' => true));
}
private function getData($request)
{
return $request->all();
}
private function createExperienceUser($data)
{
if (ExperienceUser::where('document', $data['document'])->exists())
return ExperienceUser::where('document', $data['document'])->first();
else if (isset($data['planType']) && $data['planType'] == 'academy') {
$data = $this->mapAcademyData($data);
}
$experienceUser = new ExperienceUser;
$experienceUser->name = $data['name'];
$experienceUser->birthdate = $data['dob'];
$experienceUser->document_type_id = $data['document_type'];
$experienceUser->document = $data['document'];
// Enviar almacenar el base64 de la imagen
$experienceUser->identification_file = $this->validateDataDocument($data['fileIdentificationDocument'], $data['document'] . '_identification_document');
$experienceUser->insurance_file = $this->validateDataDocument($data['fileInsuranceDocument'], $data['document'] . '_insurance_document');
if ($this->isUnder18YearsOld($data['dob'])) {
if (isset($data['guardianName']) && $data['guardianName'])
$experienceUser->guardian_name = $data['guardianName'];
if (isset($data['guardianDocument']) && $data['guardianDocument'])
$experienceUser->guardian_document = $data['guardianDocument'];
if (isset($data['guardianEmail']) && $data['guardianEmail'])
$experienceUser->guardian_email = $data['guardianEmail'];
if (isset($data['guardianPhone']) && $data['guardianPhone'])
$experienceUser->guardian_phone = $data['guardianPhone'];
}
$experienceUser->user_id = Auth::user()->id;
$experienceUser->save();
return $experienceUser;
}
private function createPayment($data, $experienceUser)
{
if (ExperiencePayment::join('payment_transactions', 'experience_payments.payment_transaction_id', '=', 'payment_transactions.id')
->where([['experience_plan_price_id', $data['plan']['id']], ['experience_user_id', $experienceUser->id], ['payment_transactions.state', '!=', 'CONFIRMED']])
->exists()
) {
return ExperiencePayment::select('experience_payments.*')->join('payment_transactions', 'experience_payments.payment_transaction_id', '=', 'payment_transactions.id')
->where([['experience_plan_price_id', $data['plan']['id']], ['experience_user_id', $experienceUser->id], ['payment_transactions.state', '!=', 'CONFIRMED']])->first();
}
$experiencePlanPrice = ExperiencePlanPrice::find($data['plan']['id']);
$controller = new ServiceChargeController;
$serviceCharge = 0;
$serviceChargeEnabled = $controller->validateServiceCharge();
if ($serviceChargeEnabled) {
$request = new Request([
'services' => 'experience',
]);
$serviceCharge = $controller->calculateServiceCharge($request);
}
$price = floatval($data['plan']['price']);
$payment = ExperiencePayment::create(
[
'payment_identifier' => intval(\Carbon\Carbon::now()->getPreciseTimestamp(3)),
'description' => $data['plan']['name'] . " (" . $experiencePlanPrice->description . ")",
'price' => $price,
'price_discount' => 0,
'discount' => 0,
'subtotal' => $price,
'service_charge' => $serviceCharge,
'total' => $price + $serviceCharge,
'payment_due_date' => \Carbon\Carbon::now()->addDays($experiencePlanPrice->duration)->toDateString(),
'experience_plan_price_id' => $experiencePlanPrice->id,
'experience_user_id' => $experienceUser->id,
'sync_with_erp' => false,
]
);
return $payment;
}
private function renewPayment($experiencePaymentId)
{
$experiencePayment = ExperiencePayment::find($experiencePaymentId);
$data = $experiencePayment->toArray();
$data['id'] = null;
$data['payment_identifier'] = intval(\Carbon\Carbon::now()->getPreciseTimestamp(3));
$data['payment_due_date'] = null;
$data['payment_transaction_id'] = null;
$data['sync_with_erp'] = false;
$newExperiencePayment = ExperiencePayment::create($data);
return $newExperiencePayment;
}
private function isUnder18YearsOld($birthdate)
{
$birthdateFormat = new DateTime($birthdate);
$now = new DateTime();
$minimumDate = $now->sub(new DateInterval('P18Y'));
return $birthdateFormat > $minimumDate;
}
private function validateDataDocument($fileBase64, $fileName)
{
if (!str_contains($fileBase64, 'data:image')) {
return $fileBase64;
}
return $this->storeObjectToS3($fileBase64, $fileName);
}
private function storeObjectToS3($fileBase64, $fileName)
{
$streamResource = $this->storeBase64ResourceToStreamResource($fileBase64);
$extension = $this->extensionFromBase64Resource($fileBase64);
$filenameToStore = $fileName . '.' . $extension;
Storage::disk('s3')->put(config('s3.default') . '/experience/' . $filenameToStore, $streamResource, 'public');
$url = config('filesystems.disks.s3.url') . '/experience/' . $filenameToStore;
return $url;
}
private function storeBase64ResourceToStreamResource($dataUrl)
{
$base64String = preg_replace('#^data:image/\w+;base64,#i', '', $dataUrl);
$binaryData = base64_decode($base64String);
$stream = fopen('php://memory', 'r+');
fwrite($stream, $binaryData);
rewind($stream);
return $stream;
}
private function extensionFromBase64Resource($dataUrl)
{
preg_match('#^data:image/(\w+);base64,#i', $dataUrl, $matches);
$extension = isset($matches[1]) ? $matches[1] : null;
return $extension;
}
private function validateAcademyStudents()
{
return $this->academyService->validateAcademyStudents();
}
private function academyStudents()
{
return $this->academyService->academyStudents();
}
private function mapAcademyData($data)
{
return $this->academyService->mapAcademyData($data);
}
}