![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/ts.corals.io/corals-api/Corals/modules/Timesheet/database/seeds/ |
<?php namespace Corals\Modules\Timesheet\database\seeds; use Carbon\Carbon; use Corals\Modules\Timesheet\Models\Activity; use Corals\Modules\Timesheet\Models\Client; use Corals\Modules\Timesheet\Models\Entry; use Corals\Modules\Timesheet\Models\Expense; use Corals\Modules\Timesheet\Models\Invoice; use Corals\Modules\Timesheet\Models\Project; use Corals\Modules\Timesheet\Models\TimeOffRequest; use Corals\Modules\Timesheet\Services\ExpenseService; use Corals\Modules\Timesheet\Services\InvoiceService; use Corals\Modules\Timesheet\Services\TimeOffRequestService; use Corals\Modules\Utility\Facades\ListOfValue\ListOfValues; use Corals\Modules\Utility\Models\Category\Category; use Corals\Settings\Facades\Settings; use Corals\User\Models\User; use Faker\Generator as Faker; use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Database\Seeder; use Illuminate\Support\Arr; use Illuminate\Support\Collection; class TimesheetDummyData extends Seeder { /** * @var Faker|mixed */ private $faker; /** * @var string[] */ protected $projectNames = [ 'Newsletters', 'Doctors Without Borders', 'Virus League', 'Screenmetrics', 'Pink Crescent Moon', 'Flux Memory', 'Th Annual Workshop', 'Support For Tomorrow', 'Dawn Charities', 'Room To Read', 'Riviera', 'Global Fund For Women', 'Donation Nnection', 'The Red Crescent', 'Do Something', 'Creative Life Planning', 'Nonprofit Infographics', 'Give More', 'Search Engine Bandits', 'Funding Child Dreams', 'Table Productions', 'The Successful Project', 'Ebooks', 'Animal Legal Defense Fund', 'Donation City', 'Charitable Charm', 'Longshot Variables', 'Rise Optimize', 'Rporate Affairs', 'Libra Foundation', 'Save Nature Org', 'Action Institute', 'Clever Charity', 'Sundance Institute', 'Bulldozer', 'Flash Fusion', 'Labor Power', 'Happy Medicine', 'Proposals', 'Network For Good', 'White Papers' ]; /** * @var array[] */ protected $incomes = [ 'Server Hosting' => ['amount' => 10, 'recurring' => true], 'Support' => ['amount' => 20, 'recurring' => true], 'Consultation' => ['amount' => 10, 'recurring' => false], 'Development' => ['amount' => 40, 'recurring' => false] ]; /** * @var string[] */ protected $users = []; /** * @var array */ protected $categories = []; /** * @var array */ protected $projects = []; /** * @var Collection */ protected $timesheetActivities; /** * @var Collection */ protected $timesheetLimitedActivities; /** * @var string */ protected $startDate = '-2 years'; /** * @var string */ protected $endDate = 'now'; /** * @var int */ protected $workHoursPerDay; /** * @var object */ protected $teamProject; /** * @throws BindingResolutionException */ public function run() { $this->initiateData(); $this->createDummyData(2, 25); } /** * @return void * @throws BindingResolutionException */ protected function initiateData() { $this->workHoursPerDay = Settings::get('total_working_hours_per_day', 8); $this->teamProject = Project::query()->where('id', '=', Settings::get('team_project_id'))->first(); foreach (['income-categories', 'expense-categories'] as $parentCatSlug) { $parentCat = Category::query()->where('slug', $parentCatSlug)->first(); $children = $parentCat->children()->where('status', 'active')->get(); $this->categories[$parentCatSlug] = $children; } $this->timesheetActivities = Activity::query()->where('is_limited', '=', 0)->get(); $this->timesheetLimitedActivities = Activity::query()->where('is_limited', '=', 1)->get(); $this->faker = app()->make(Faker::class); } /** * @param $numberOfClients * @param $numberOfUsers * @return void * @throws \Exception */ private function createDummyData($numberOfClients, $numberOfUsers) { $this->createEmployeeUsers($numberOfUsers); $this->createClients($numberOfClients); $this->createEntry($this->users); } /** * @param $NumberOfUsers * @return void * @throws \Exception */ protected function createEmployeeUsers($NumberOfUsers) { foreach (range(1, $NumberOfUsers) as $i) { $position = $this->faker->randomElement(['junior', 'mid', 'senior']); $salary = $position === 'junior' ? random_int(8, 12) * 100 : random_int(12, 30) * 100; $user = User::create([ 'name' => $this->faker->firstName, 'last_name' => $this->faker->lastName, 'email' => $this->faker->unique()->safeEmail, 'password' => '123456', 'start_date' => Carbon::parse($this->faker->dateTimeBetween($this->startDate, $this->endDate)), 'position' => $position, 'employee_type' => $this->faker->randomKey(trans('Timesheet::attributes.user.employee_type_options')), 'hourly_rate' => round($salary / 176), 'salary' => $salary, 'salary_period' => 'monthly', ]); $user->assignRole('member'); $this->users[] = $user; } } /** * @param $NumberOfClients * @return void * @throws \Exception */ protected function createClients($NumberOfClients) { foreach (range(1, $NumberOfClients) as $i) { tap(Client::create([ 'name' => $this->faker->name, 'bill_cycle' => 'monthly', 'bill_cycle_starts_at' => '1', 'status' => $this->faker->randomKey(config('timesheet.models.client.status_options')), ]), function (Client $client) { $clientUser = $this->createClientUser(); $client->users()->attach($clientUser->id); for ($i = 1; $i <= random_int(1, 4); $i++) { $this->createProject($client->id); } }); } } /** * @return mixed */ protected function createClientUser() { $user = User::create([ 'name' => $this->faker->firstName, 'last_name' => $this->faker->lastName, 'email' => $this->faker->unique()->safeEmail, 'password' => '123456', 'start_date' => Carbon::parse($this->faker->dateTimeBetween($this->startDate, $this->endDate)), ]); $user->assignRole('client'); return $user; } /** * @param $clientId * @return void * @throws \Exception */ protected function createProject($clientId) { $projectNameIndex = array_rand($this->projectNames); tap([ 'name' => $this->projectNames[$projectNameIndex], 'type' => 'time_and_materials', 'currency' => 'USD', 'bill_by' => 'person_billable_rate', 'hourly_rate' => null, 'assignable' => '0', 'client_id' => $clientId, 'start_date' => Carbon::parse($this->faker->dateTimeBetween($this->startDate, $this->endDate)), ], function ($projectData) use ($projectNameIndex) { $this->projectNames = Arr::except($this->projectNames, $this->projectNames[$projectNameIndex]); if ($projectData['bill_by'] == 'project_billable_rate') { $projectData['hourly_rate'] = random_int(1, 10); } elseif ($projectData['bill_by'] == 'person_billable_rate') { $projectData['assignable'] = 1; for ($i = 0; $i < random_int(6, 12); $i++) { $user = $this->faker->randomElement($this->users); $usersToInsert[$user->id]['user_rate'] = $user->hourly_rate; } } $activitiesToInsert = []; for ($i = 0; $i < random_int(4, 8); $i++) { $activity = $this->faker->randomElement($this->timesheetActivities->pluck('id')->toArray()); $activitiesToInsert[$activity]['activity_rate'] = random_int(5, 30); } $project = Project::create($projectData); if (isset($usersToInsert)) { $project->users()->sync($usersToInsert); } if (isset($activitiesToInsert)) { $project->activities()->sync($activitiesToInsert); } $this->createExpense($project); $this->createIncome($project); }); } /** * @param Project $project * @return void * @throws \Exception */ protected function createIncome(Project $project) { $date = $project->start_date; if (!$date->day == '1') { $date->addMonth(); $date->setDay(1); } $initial_date = $date; $today = Carbon::now(); foreach ($this->incomes as $name => $attributes) { $amount = $attributes['amount']; $recurring = $attributes['recurring']; while ($date->lessThanOrEqualTo($today)) { $project->incomes()->create([ 'income_date' => $date, 'amount' => $amount * random_int(10, 50), 'currency' => 'USD', 'category_id' => $this->faker->randomElement($this->categories['income-categories'])->id, 'status' => $this->faker->randomKey(config('timesheet.models.income.status_options')), 'payment_method' => $this->faker->randomKey(ListOfValues::get('payment_method')), 'notes' => $name, 'client_id' => $project->client_id ]); if ($recurring === true) { $date->addMonth(); } else { $date->addMonths(random_int(4, 8)); } } $date = $initial_date; } } /** * @param Project $project * @return void * @throws \Exception */ protected function createExpense(Project $project) { $date = Carbon::parse($this->faker->dateTimeBetween($this->startDate, $this->endDate)); $date->setDay(1); $today = Carbon::now(); while ($date->lessThanOrEqualTo($today)) { foreach (range(1, 3) as $i) { $category = $this->faker->randomElement($this->categories['expense-categories']); $expense = $project->expenses()->create([ 'expense_date' => $date, 'amount' => random_int(10, 100) * 10, 'currency' => 'USD', 'category_id' => $category->id, 'status' => $this->faker->randomKey(config('timesheet.models.expense.status_options')), 'payment_method' => $this->faker->randomKey(ListOfValues::get('payment_method')), 'notes' => $category->name, 'client_id' => $project->client_id, 'user_id' => $this->faker->randomElement(data_get($this->users, 'member.id', [])), 'billable' => random_int(0, 1), ]); if ($expense->billable == 1 && $expense->status == 'pending') { $this->createInvoiceOnExpense($expense); } } $date->addMonth(); } } /** * @param $expense * @return void */ protected function createInvoiceOnExpense($expense) { tap(Invoice::create([ 'code' => Invoice::getCode('INV'), 'project_id' => $expense->project_id, 'client_id' => $expense->client_id, 'subtotal' => $expense->amount, 'tax_total' => 0, 'total' => $expense->amount, 'invoice_date' => $expense->expense_date, 'due_date' => $expense->expense_date, 'status' => 'pending', ]), function (Invoice $invoice) use ($expense) { $invoiceItems[] = [ 'title' => $expense->category->name, 'type' => 'expense', 'rate' => $expense->amount, 'quantity' => 1, 'amount' => $expense->amount, 'notes' => sprintf("Date: %s, %s", format_date($expense->expense_date), $expense->notes), ]; $expense->invoice_id = $invoice->id; $expense->status = 'paid'; $expense->save(); $invoice->items()->createMany($invoiceItems); }); } /** * @return array * @throws \Exception */ protected function generateInvoiceItem() { $item = [ 'title' => $this->faker->jobTitle(), 'rate' => random_int(1, 100) / 10, 'quantity' => random_int(1, 100) / 10, 'type' => $type = $this->faker->randomKey(config('timesheet.models.invoice_item.type_options')), 'amount' => null ]; $amount = $item['rate'] * $item['quantity']; $item['amount'] = $type == 'discount' ? $amount * -1 : $amount; return $item; } /** * @param $users * @return void * @throws \Exception */ protected function createEntry($users) { foreach ($users as $user) { $project = $user->projects()->oldest('start_date')->first(); if (!$project) { foreach (Project::query()->where('id', '!=', $this->teamProject->id)->inRandomOrder()->limit(3)->get() as $toAttachProject) { $userToInsert[$user->id]['user_rate'] = $user->hourly_rate; $toAttachProject->users()->sync($userToInsert); $toAttachProject->save(); } $project = $user->projects()->oldest('start_date')->first(); } if ($user->start_date < $project->start_date) { $user->start_date = $project->start_date; $user->save(); } $date = Carbon::parse($user->start_date); $today = Carbon::now(); while ($date->lessThanOrEqualTo($today)) { $activityId = $project->activities()->where('is_limited', 0)->inRandomOrder()->first()->id; foreach (range(1, random_int(5, 14)) as $item) { if ($date->isFriday() || $date->isSaturday()) { $date->addDay(); continue; } if ($date->lessThanOrEqualTo($today)) { if ($user->employee_type === 'full_time') { $randomTimeOffRate = random_int(1, 100); if ($randomTimeOffRate > 99) { if ($date->isSunday() || $date->isMonday() || $date->isTuesday()) { $randomTimeOffDays = random_int(1, 2); } else if ($date->isWednesday()) { $randomTimeOffDays = 1; } else { $randomTimeOffDays = 0; } $this->createTimeOffRequest($user->id, $date, $randomTimeOffDays); $date->addDays($randomTimeOffDays); continue; } } elseif ($user->employee_type === 'part_time') { $randomNoWorkRate = random_int(1, 100); if ($randomNoWorkRate > 60) { $date->addDay(); continue; } } $randomManyEntryRate = random_int(1, 100); $countProject = $user->projects()->count(); if ($randomManyEntryRate > 90 && $countProject > 2) { $randomEntryCount = random_int(2, 3); $userProjects = $user->projects()->inRandomOrder()->limit($randomEntryCount)->get(); foreach (range(0, $randomEntryCount - 1) as $i) { $entryData = [ 'spent_at' => $date->toDateString(), 'hours' => $hours = $user->employee_type === 'full_time' ? random_int($this->workHoursPerDay / $randomEntryCount - 1, $this->workHoursPerDay / $randomEntryCount + 1) : random_int(2, $this->workHoursPerDay / $randomEntryCount), 'minutes' => $minutes = $hours == 8 ? 0 : random_int(0, 5) * 10, 'user_id' => $user->id, 'project_id' => $userProjects->get($i)->id, 'activity_id' => $userProjects->get($i)->activities()->where('is_limited', 0)->inRandomOrder()->first()->id, 'description' => $this->faker->text(40), 'has_reviewed' => 1, 'evaluation_hours' => $hours - random_int(0, 1), 'evaluation_minutes' => $minutes, ]; Entry::create($entryData); } } else { $entryData = [ 'spent_at' => $date->toDateString(), 'hours' => $hours = $user->employee_type === 'full_time' ? random_int(7, $this->workHoursPerDay) : random_int(1, $this->workHoursPerDay), 'minutes' => $minutes = $hours == 8 ? 0 : random_int(0, 5) * 10, 'user_id' => $user->id, 'project_id' => $project->id, 'activity_id' => $activityId, 'description' => $this->faker->text(40), 'has_reviewed' => 1, 'evaluation_hours' => $hours - random_int(0, 1), 'evaluation_minutes' => $minutes, ]; Entry::create($entryData); } $date->addDay(); } else { break; } } $selectAnotherProject = $user->projects()->inRandomOrder()->first(); if ($date > $selectAnotherProject->start_date) { $project = $selectAnotherProject; } } } $this->generateUsersSalaries(); } /** * @param $userId * @param $startDate * @param $days * @return void * @throws \Exception */ protected function createTimeOffRequest($userId, $startDate, $days) { $statusOption = config('timesheet.models.timeOffRequest.status_options'); $timeOffRequestStatus = $this->faker->randomKey($statusOption); $timeOffRequestData = [ 'activity_id' => $this->faker->randomElement($this->timesheetLimitedActivities->pluck('id')->toArray()), 'project_id' => $this->teamProject->id, 'user_id' => $userId, 'reject_reason' => NULL, 'hours' => $this->workHoursPerDay, 'status' => $timeOffRequestStatus, 'notes' => $this->faker->text(), ]; if ($timeOffRequestStatus === 'pending') { $date = Carbon::now()->addDays(random_int(0, 3)); if ($date->isFriday() || $date->isSaturday()) { $date->addDays(2); $end_date = Carbon::parse($date)->addDays(rand(1, 3)); } else if ($date->isTuesday()) { $end_date = Carbon::parse($date)->addDays(rand(1, 2)); } else { $end_date = Carbon::parse($date); } $timeOffRequestData['start_date'] = $date; $timeOffRequestData['end_date'] = $end_date; TimeOffRequest::create($timeOffRequestData); unset($statusOption['pending']); $timeOffRequestStatus = $this->faker->randomKey($statusOption); $timeOffRequestData['status'] = $timeOffRequestStatus; } $timeOffRequestData['start_date'] = $startDate; $timeOffRequestData['end_date'] = Carbon::parse($startDate)->addDays($days); if ($timeOffRequestStatus === 'rejected') { $timeOffRequestData['reject_reason'] = 'rejected'; } tap(TimeOffRequest::create($timeOffRequestData), function (TimeOffRequest $timeOffRequest) { if ($timeOffRequest->status === 'approved') { app(TimeOffRequestService::class)->approveRequest($timeOffRequest); } }); } private function generateUsersSalaries() { $from_date = Carbon::now()->subYears(2); $from_date->setDay(1); $today = Carbon::now(); $salariesCategory = Category::query()->where('slug', '=', 'salaries')->first(); while ($from_date->lessThan($today)) { $to_date = Carbon::parse($from_date)->addMonth(); if ($to_date->greaterThan($today)){ break; } $users = app(ExpenseService::class)->getUsersPayment($from_date, $to_date); $generationCode = $to_date->format('YmdHis'); $expenses = []; foreach ($users as $user) { $expenses[] = [ 'category_id' => $salariesCategory->id, 'user_id' => $user['user_id'], 'notes' => $user['notes'], 'amount' => $user['payment'], 'expense_date' => $to_date, 'status' => 'paid', 'currency' => 'usd', 'payment_method' => $this->faker->randomKey(ListOfValues::get('payment_method')), 'properties' => json_encode([ 'generation_code' => $generationCode ]) ]; } Expense::query()->insert($expenses); $from_date->addMonth(); } } }