Advertisement
Guest User

Untitled

a guest
Feb 14th, 2018
352
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 17.66 KB | None | 0 0
  1. <?php
  2.  
  3. use App\Exceptions\ApiExceptions\SystemException;
  4. use App\Model\Category;
  5. use App\Model\City;
  6. use App\Model\Company;
  7. use App\Model\CompanyService;
  8. use App\Model\CompanyTimetable;
  9. use App\Model\Image;
  10. use App\Model\Location;
  11. use App\Model\Provider;
  12. use App\Model\ProviderService;
  13. use App\Model\Reservation;
  14. use App\Model\Service;
  15. use App\Model\User;
  16. use Carbon\Carbon;
  17. use Illuminate\Support\Collection;
  18.  
  19. class SpecialTestSeeder extends DefaultTableSeeder
  20. {
  21.     // ~ reservations: 20915
  22.     const FROM_YEAR = 2017;
  23.     const FROM_MONTH = 05;
  24.  
  25.     const CHANCE_OF_NO_PAST_RESERVATION = 70;
  26.     const PAST_RESERVATION_CHANCE_COMPLETED = 40;
  27.     const PAST_RESERVATION_CHANCE_CANCELLED_BY_USER = 20;
  28.     const PAST_RESERVATION_CHANCE_CANCELLED_BY_PROVIDER = 7;
  29.     const PAST_RESERVATION_CHANCE_NOT_SHOW = 30;
  30.     const PAST_RESERVATION_CHANCE_CANCELLED_BY_ADMIN = 3;
  31.  
  32.     const CHANCE_OF_NO_FUTURE_RESERVATION = 80;
  33.     const FUTURE_RESERVATION_CHANCE_ACTIVE = 80;
  34.     const FUTURE_RESERVATION_CHANCE_CANCELLED_BY_USER = 15;
  35.     const FUTURE_RESERVATION_CHANCE_CANCELLED_BY_PROVIDER = 4;
  36.     const FUTURE_RESERVATION_CHANCE_CANCELLED_BY_ADMIN = 1;
  37.  
  38.     const NO_CATEGORIES = 2;
  39.     const NO_SERVICES_EACH_CATEGORY = 3;
  40.  
  41.     const COMPANY_EMAIL = 'system+company@book-a-look-eu.com';
  42.     const USER_PASSWORD = 'drujba_special_secret';
  43.  
  44.     /** @var Faker\Generator */
  45.     private $faker;
  46.  
  47.     /**
  48.      * firstName, lastName, imagePrefixPath
  49.      * @var array
  50.      */
  51.     private $providers = [
  52.         1 => ['Jora', 'Kardan', '1.jpg'],
  53.         2 => ['Vitea', 'Buric', '2.jpg'],
  54.         3 => ['Borea', 'Guzgan', '3.png'],
  55.         4 => ['Hasan', 'Turbatu', '4.jpg'],
  56.         5 => ['Vova', 'Furculita', '5.jpg'],
  57.         6 => ['Leonea', 'Jitelu', '6.jpg'],
  58.         7 => ['Vanea', 'Plaskagupts', '7.jpeg'],
  59.     ];
  60.     /**
  61.      * duration_slots, price, providers
  62.      * @var array
  63.      */
  64.     private $companyServices = [
  65.         1 => [1, 20.5, [1]],
  66.         2 => [2, 15.0, [2, 3, 4, 5]],
  67.         3 => [3, 18.25, [3, 4, 6]],
  68.         4 => [4, 45.0, [3, 4, 5, 6, 7]],
  69.         5 => [5, 90.0, [5, 6]],
  70.         6 => [6, 66.6, [2, 4, 5, 6, 7]],
  71.     ];
  72.  
  73.     public function __construct()
  74.     {
  75.         $this->faker = Faker\Factory::create('ro');
  76.         $this->faker->seed('2018');
  77.     }
  78.  
  79.     /**
  80.      * @param boolean $isPassed
  81.      * @return integer
  82.      * @throws SystemException
  83.      */
  84.     private function getRandomReservationStatus($isPassed)
  85.     {
  86.         $chances = $isPassed ? [
  87.             self::PAST_RESERVATION_CHANCE_COMPLETED => Reservation::STATUS_COMPLETED,
  88.             self::PAST_RESERVATION_CHANCE_NOT_SHOW => Reservation::STATUS_NOT_SHOW,
  89.             self::PAST_RESERVATION_CHANCE_CANCELLED_BY_USER => Reservation::STATUS_CANCELLED_BY_USER,
  90.             self::PAST_RESERVATION_CHANCE_CANCELLED_BY_PROVIDER => Reservation::STATUS_CANCELLED_BY_PROVIDER,
  91.             self::PAST_RESERVATION_CHANCE_CANCELLED_BY_ADMIN => Reservation::STATUS_CANCELLED_BY_ADMIN,
  92.         ] : [
  93.             self::FUTURE_RESERVATION_CHANCE_ACTIVE => Reservation::STATUS_ACTIVE,
  94.             self::FUTURE_RESERVATION_CHANCE_CANCELLED_BY_USER => Reservation::STATUS_CANCELLED_BY_USER,
  95.             self::FUTURE_RESERVATION_CHANCE_CANCELLED_BY_PROVIDER => Reservation::STATUS_CANCELLED_BY_PROVIDER,
  96.             self::FUTURE_RESERVATION_CHANCE_CANCELLED_BY_ADMIN => Reservation::STATUS_CANCELLED_BY_ADMIN,
  97.         ];
  98.         $number = $this->faker->numberBetween(1, 100);
  99.         foreach ($chances as $chance => $status) {
  100.             if ($number <= $chance) {
  101.                 return $status;
  102.             }
  103.             $number -= $chance;
  104.         }
  105.  
  106.         throw new SystemException('Incomplete chances (100%)');
  107.     }
  108.  
  109.     /**
  110.      * @param City $city
  111.      * @return Location
  112.      */
  113.     private function addLocation(City $city)
  114.     {
  115.         return factory(Location::class)->create([
  116.             'address' => 'Special test address',
  117.             'city_id' => $city->id,
  118.             'lat' => '46.7738502',
  119.             'lng' => '23.6253739',
  120.         ]);
  121.     }
  122.  
  123.     /**
  124.      * @return User
  125.      */
  126.     private function addCompanyAdminUser()
  127.     {
  128.         return factory(User::class)->create([
  129.             'email' => self::COMPANY_EMAIL,
  130.             'first_name' => 'CompanyUser',
  131.             'last_name' => 'SpecialTest',
  132.             'password' => self::USER_PASSWORD,
  133.             'is_password_confirmed' => true,
  134.             'status' => User::STATUS_ACTIVE,
  135.             'role' => User::ROLE_COMPANY_ADMIN,
  136.         ]);
  137.     }
  138.  
  139.     /**
  140.      * @param int $key
  141.      * @return User
  142.      */
  143.     private function addProviderUser($key)
  144.     {
  145.         return factory(User::class)->create([
  146.             'email' => "system+provider{$key}@book-a-look-eu.com",
  147.             'first_name' => $this->providers[$key][0],
  148.             'last_name' => "{$this->providers[$key][1]}{$key}",
  149.             'password' => self::USER_PASSWORD,
  150.             'is_password_confirmed' => true,
  151.             'status' => User::STATUS_ACTIVE,
  152.             'role' => User::ROLE_PROVIDER,
  153.         ]);
  154.     }
  155.  
  156.  
  157.     /**
  158.      * @param int $key
  159.      * @return User
  160.      */
  161.     private function addClientUser($key)
  162.     {
  163.         return factory(User::class)->create([
  164.             'email' => "system+client{$key}@book-a-look-eu.com",
  165.             'first_name' => $this->faker->firstName,
  166.             'last_name' => "{$this->faker->lastName}{$key}",
  167.             'password' => self::USER_PASSWORD,
  168.             'is_password_confirmed' => true,
  169.             'status' => User::STATUS_ACTIVE,
  170.             'role' => User::ROLE_USER,
  171.         ]);
  172.     }
  173.  
  174.     /**
  175.      * @return Image
  176.      */
  177.     private function addCompanyImage()
  178.     {
  179.         return Image::create([
  180.             'path' => 'images/special_test/company.png',
  181.         ]);
  182.     }
  183.  
  184.     /**
  185.      * @param int $key
  186.      * @return Image
  187.      */
  188.     private function addProviderImage($key)
  189.     {
  190.         $prefix = $this->providers[$key][2];
  191.  
  192.         return Image::create([
  193.             'path' => "images/special_test/providers/$prefix",
  194.         ]);
  195.     }
  196.  
  197.     /**
  198.      * @param Carbon $companyCreated
  199.      * @return Company
  200.      */
  201.     private function addCompany(Carbon $companyCreated)
  202.     {
  203.         $city = City::whereName('Cluj-Napoca')->firstOrFail();
  204.         $location = $this->addLocation($city);
  205.         $companyAdminUser = $this->addCompanyAdminUser();
  206.         $companyImage = $this->addCompanyImage();
  207.         $country = $city->country;
  208.         $currency = $country->currency;
  209.  
  210.         return factory(Company::class)->create([
  211.             'name' => 'Book-a-look SpecialTestCompany',
  212.             'description' => 'This is our special test company',
  213.             'email' => $companyAdminUser->email,
  214.             'location_id' => $location->id,
  215.             'image_id' => $companyImage->id,
  216.             'setup_step' => Company::SETUP_STEP_FINISHED,
  217.             'currency_id' => $currency->id,
  218.             'timezone' => $city->timezone,
  219.             'active' => true,
  220.             'max_schedule_days' => 40,
  221.             'online' => true,
  222.             'created_at' => $companyCreated,
  223.         ]);
  224.     }
  225.  
  226.     /**
  227.      * @param Company $company
  228.      * @return CompanyTimetable
  229.      */
  230.     private function addCompanyTimetable(Company $company)
  231.     {
  232.         $timetableData = [
  233.             'company_id' => $company->id,
  234.         ];
  235.         foreach ([
  236.             'monday' => [1, '08:00:00', '19:00:00'],
  237.             'tuesday' => [1, '09:00:00', '21:00:00'],
  238.             'wednesday' => [0, '06:00:00', '22:00:00'],
  239.             'thursday' => [1, '07:00:00', '16:00:00'],
  240.             'friday' => [1, '11:00:00', '15:00:00'],
  241.         ] as $day => $data) {
  242.             $timetableData += [
  243.                 "{$day}_enabled" => $data[0],
  244.                 "{$day}_start" => $data[1],
  245.                 "{$day}_end" => $data[2],
  246.             ];
  247.         }
  248.  
  249.         return CompanyTimetable::create($timetableData);
  250.     }
  251.  
  252.     /**
  253.      * @param Company $company
  254.      * @param int $key
  255.      * @return Provider
  256.      */
  257.     private function addProvider(Company $company, $key)
  258.     {
  259.         $user = $this->addProviderUser($key);
  260.         $image = $this->addProviderImage($key);
  261.        
  262.         return factory(Provider::class)->create([
  263.             'user_id' => $user->id,
  264.             'company_id' => $company->id,
  265.             'image_id' => $image->id,
  266.         ]);
  267.     }
  268.  
  269.     /**
  270.      * @param int $key
  271.      * @return Category
  272.      */
  273.     private function addCategory($key)
  274.     {
  275.         return factory(Category::class)->create([
  276.             'name' => "SpecialTest Category {$key}",
  277.         ]);
  278.     }
  279.  
  280.     /**
  281.      * @param Category $category
  282.      * @param int $key
  283.      * @return Service
  284.      */
  285.     private function addService(Category $category, $key)
  286.     {
  287.         return factory(Service::class)->create([
  288.             'category_id' => $category->id,
  289.             'name' => "SpecialTest Service {$key}",
  290.             'active' => true,
  291.         ]);
  292.     }
  293.  
  294.     /**
  295.      * @param Company $company
  296.      * @param Service service
  297.      * @param int $key
  298.      * @return CompanyService
  299.      */
  300.     private function addCompanyService(Company $company, Service $service, $key)
  301.     {
  302.         return factory(CompanyService::class)->create([
  303.             'company_id' => $company->id,
  304.             'service_id' => $service->id,
  305.             'duration_slots' => $this->companyServices[$key][0],
  306.             'price' => $this->companyServices[$key][1],
  307.         ]);
  308.     }
  309.  
  310.     /**
  311.      * @param Company $company
  312.      * @param Service $service
  313.      * @param Provider $provider
  314.      * @return CompanyService
  315.      */
  316.     private function addProviderService(Company $company, Service $service, Provider $provider)
  317.     {
  318.         return factory(ProviderService::class)->create([
  319.             'company_id' => $company->id,
  320.             'service_id' => $service->id,
  321.             'provider_id' => $provider->id,
  322.         ]);
  323.     }
  324.  
  325.     /**
  326.      * @param Company $company
  327.      * @return Collection
  328.      */
  329.     private function addProviders(Company $company)
  330.     {
  331.         $providers = collect();
  332.         foreach (range(1, 7) as $i) {
  333.             $provider = $this->addProvider($company, $i);
  334.             $providers->put($i, $provider);
  335.         }
  336.  
  337.         return $providers;
  338.     }
  339.  
  340.     /**
  341.      * @param Company $company
  342.      * @param Collection $providers
  343.      * @return Collection
  344.      */
  345.     private function addProviderServices(Company $company, Collection $providers)
  346.     {
  347.         $providerServicesAndCompanyServices = collect();
  348.         foreach (range(1, self::NO_CATEGORIES) as $i) {
  349.             $category = $this->addCategory($i);
  350.             foreach (range(1, $noServices = self::NO_SERVICES_EACH_CATEGORY) as $j) {
  351.                 $key = $noServices * ($i - 1) + $j;
  352.                 $service = $this->addService($category, $key);
  353.                 $providerServiceAndCompanyService = collect();
  354.                 $companyService = $this->addCompanyService($company, $service, $key);
  355.                 $providerServiceAndCompanyService->put('companyService', $companyService);
  356.                 foreach ($this->companyServices[$key][2] as $providerKey) {
  357.                     $provider = $providers->get($providerKey);
  358.                     $providerService = $this->addProviderService($company, $service, $provider);
  359.                     $providerServiceAndCompanyService->put('providerService', $providerService);
  360.                     $providerServicesAndCompanyServices->push($providerServiceAndCompanyService);
  361.                 }
  362.             }
  363.         }
  364.  
  365.         return $providerServicesAndCompanyServices;
  366.     }
  367.  
  368.     /**
  369.      * @return Collection
  370.      */
  371.     private function addClients()
  372.     {
  373.         $clients = collect();
  374.         collect(range(1, 100))->each(function ($index) use ($clients) {
  375.             $user = $this->addClientUser($index);
  376.             $clients->put($index, $user);
  377.         });
  378.  
  379.         return $clients;
  380.     }
  381.  
  382.     /**
  383.      * @param CompanyTimetable $timetable
  384.      * @param Carbon $date
  385.      * @return array|null
  386.      */
  387.     private function getCompanyTimetableStartAndEnd(CompanyTimetable $timetable, Carbon $date)
  388.     {
  389.         foreach ([
  390.             Carbon::MONDAY => CompanyTimetable::MONDAY,
  391.             Carbon::TUESDAY => CompanyTimetable::TUESDAY,
  392.             Carbon::WEDNESDAY => CompanyTimetable::WEDNESDAY,
  393.             Carbon::THURSDAY => CompanyTimetable::THURSDAY,
  394.             Carbon::FRIDAY => CompanyTimetable::FRIDAY,
  395.             Carbon::SATURDAY => CompanyTimetable::SATURDAY,
  396.             Carbon::SUNDAY => CompanyTimetable::SUNDAY,
  397.         ] as $carbonDayOfWeek => $timetableDayOfWeek) {
  398.             if ($date->dayOfWeek !== $carbonDayOfWeek) {
  399.                 continue;
  400.             }
  401.             if (!$timetable->isEnabled($timetableDayOfWeek)) {
  402.                 return null;
  403.             }
  404.             return [
  405.                 $timetable->getStartDateOf($timetableDayOfWeek),
  406.                 $timetable->getEndDateOf($timetableDayOfWeek),
  407.             ];
  408.         }
  409.     }
  410.  
  411.     /**
  412.      * @param Collection $providerServices
  413.      * @param Collection $clients
  414.      * @param CompanyTimetable $companyTimetable
  415.      * @param Carbon $companyCreated
  416.      * @return Collection
  417.      */
  418.     private function addReservations(
  419.         Collection $providerServicesAndCompanyServices,
  420.         Collection $clients,
  421.         CompanyTimetable $companyTimetable,
  422.         Carbon $companyCreated
  423.     ) {
  424.         $reservations = collect();
  425.         $oneSlotInMinutes = config('schedules.one_slot_in_minutes');
  426.         $maxScheduleDays = $companyTimetable->company->max_schedule_days;
  427.         $now = Carbon::now();
  428.         $futureMax = Carbon::now()->addDays($maxScheduleDays);
  429.  
  430.         $providerServicesAndCompanyServices->each(
  431.             function (Collection $providerServiceAndCompanyService) use (
  432.             $companyTimetable,
  433.             $clients,
  434.             $companyCreated,
  435.             $oneSlotInMinutes,
  436.             $reservations,
  437.             $futureMax,
  438.             $now
  439.         ) {
  440.             /** @var ProviderService $providerService */
  441.             $providerService = $providerServiceAndCompanyService->get('providerService');
  442.             /** @var CompanyService $companyService */
  443.             $companyService = $providerServiceAndCompanyService->get('companyService');
  444.             $durationSlots = $companyService->duration_slots;
  445.             $durationMinutes = $durationSlots * $oneSlotInMinutes;
  446.             $date = $companyCreated->copy()->subDay();
  447.  
  448.             while ($date < $futureMax) {
  449.                 $isPassed = $date < $now;
  450.                 $date->addDay();
  451.                 if (!$startAndEndTime = $this->getCompanyTimetableStartAndEnd($companyTimetable, $date)) {
  452.                     continue;
  453.                 }
  454.                 list($startTime, $endTime) = $startAndEndTime;
  455.                 $time = $date->copy()->setTimeFromTimeString($startTime);
  456.                 $lastTime = $date->copy()->setTimeFromTimeString($endTime)->subMinutes($durationMinutes);
  457.                 while ($time < $lastTime) {
  458.                     $noReservation = $this->faker->boolean(
  459.                         $isPassed
  460.                             ? self::CHANCE_OF_NO_PAST_RESERVATION
  461.                             : self::CHANCE_OF_NO_FUTURE_RESERVATION
  462.                     );
  463.                     if ($noReservation) {
  464.                         $time->addMinutes($oneSlotInMinutes);
  465.                         continue;
  466.                     }
  467.                     $client = $this->faker->randomElement($clients->all());
  468.                     $reservation = Reservation::query()->forceCreate([
  469.                         'reserved_at' => $time,
  470.                         'provider_service_id' => $providerService->id,
  471.                         'client_id' => $client->id,
  472.                         'by_user_id' => $client->id,
  473.                         'provider_id' => $providerService->provider_id,
  474.                         'service_id' => $providerService->service_id,
  475.                         'status' => $this->getRandomReservationStatus($isPassed),
  476.                         'company_id' => $providerService->company_id,
  477.                         'price' => $companyService->price,
  478.                         'duration_slots' => $companyService->duration_slots,
  479.                     ]);
  480.                     $reservations->push($reservation);
  481.  
  482.                     $time->addMinutes($durationMinutes);
  483.                 }
  484.             }
  485.         });
  486.  
  487.         return $reservations;
  488.     }
  489.  
  490.     private function addSchedules()
  491.     {
  492.         Artisan::call('new-provider:schedules');
  493.     }
  494.  
  495.     /**
  496.      * @param string $email
  497.      * @return int
  498.      */
  499.     private function deleteExistingCompany($email)
  500.     {
  501.         return Company::whereEmail($email)->delete();
  502.     }
  503.  
  504.     /**
  505.      * @param string $email
  506.      * @return int
  507.      */
  508.     private function deleteExistingUser($email)
  509.     {
  510.         return User::whereEmail($email)->delete();
  511.     }
  512.  
  513.     public function testRun()
  514.     {
  515.         $this->deleteExistingCompany(self::COMPANY_EMAIL);
  516.         $this->deleteExistingUser(self::COMPANY_EMAIL);
  517.         $companyCreated = Carbon::createFromDate(self::FROM_YEAR,self::FROM_MONTH)->firstOfMonth();
  518.         $company = $this->addCompany($companyCreated);
  519.         $companyTimetable = $this->addCompanyTimetable($company);
  520.         $providers = $this->addProviders($company);
  521.         // $this->addSchedules();
  522.         $providerServicesAndCompanyServices = $this->addProviderServices($company, $providers);
  523.         $clients = $this->addClients();
  524.  
  525.         $this->addReservations($providerServicesAndCompanyServices, $clients, $companyTimetable, $companyCreated);
  526.     }
  527. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement