Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions app/Http/Controllers/CronController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace App\Http\Controllers;

use App\Repositories\Interfaces\EmployeeRepositoryInterface as EmployeeRepository;
use Carbon\Carbon;
use Illuminate\Support\Facades\Mail;

class CronController extends Controller
{
public function __construct()
{

}

/**
* This method MUST send emails reminders the the administrators of the
* birthdeys that are coming in two weeks from now.
*
* @return void
*/
public function notifyBirthdeysToAdmin(EmployeeRepository $employeeRepository)
{
$date = new Carbon('+2 weeks');
$employees = $employeeRepository->getEmployeesWithBirtheyOn($date);

// No birthey in two weeks frmon now
if (!count($employees)) {
return;
}

$administrators = $employeeRepository->getAdminUsers();

// No admin users to notify
if (!count($administrators)) {
return;
}

$data = [
'employees' => $employees,
'date' => $date,
];

foreach ($administrators as $admin) {
$data['admin'] = $admin;

Mail::send('emails.birthdays.reminder', $data, function ($message) use ($admin) {
$message->to($admin->email, $admin->email)->subject(trans('emails.birthdays.reminder.subject'));
});
}

var_dump('Birthey reminders sent to ' . count($administrators) . ' administrator(s).');
}
}
1 change: 1 addition & 0 deletions app/Providers/RepositoryServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public function register()
Time\Repositories\ClientRepository::class => [Time\Repositories\Interfaces\ClientRepositoryInterface::class],
Time\Repositories\ProjectRepository::class => [Time\Repositories\Interfaces\ProjectRepositoryInterface::class],
Time\Repositories\TimeLogRepository::class => [Time\Repositories\Interfaces\TimeLogRepositoryInterface::class],
\App\Repositories\EmployeeRepository::class => [\App\Repositories\Interfaces\EmployeeRepositoryInterface::class],
];

foreach ($bindings as $concrete => $interfaces) {
Expand Down
53 changes: 53 additions & 0 deletions app/Providers/ViewComposerServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,58 @@ public function register()
view()->composer('includes.header', function($view) {
$view->with('current', preg_replace('/\..*/', '', Route::currentRouteName()));
});

/**
* In the lines below we define the $style and $fontFamily variable that will be accessible
* in all the emails views.
*/
view()->composer('emails.*', function($view) {
$style = [
/* Layout ------------------------------ */

'body' => 'margin: 0; padding: 0; width: 100%; background-color: #F2F4F6;',
'email-wrapper' => 'width: 100%; margin: 0; padding: 0; background-color: #F2F4F6;',

/* Masthead ----------------------- */

'email-masthead' => 'padding: 25px 0; text-align: center;',
'email-masthead_name' => 'font-size: 16px; font-weight: bold; color: #2F3133; text-decoration: none; text-shadow: 0 1px 0 white;',

'email-body' => 'width: 100%; margin: 0; padding: 0; border-top: 1px solid #EDEFF2; border-bottom: 1px solid #EDEFF2; background-color: #FFF;',
'email-body_inner' => 'width: auto; max-width: 570px; margin: 0 auto; padding: 0;',
'email-body_cell' => 'padding: 35px;',

'email-footer' => 'width: auto; max-width: 570px; margin: 0 auto; padding: 0; text-align: center;',
'email-footer_cell' => 'color: #AEAEAE; padding: 35px; text-align: center;',

/* Body ------------------------------ */

'body_action' => 'width: 100%; margin: 30px auto; padding: 0; text-align: center;',
'body_sub' => 'margin-top: 25px; padding-top: 25px; border-top: 1px solid #EDEFF2;',

/* Type ------------------------------ */

'anchor' => 'color: #3869D4;',
'header-1' => 'margin-top: 0; color: #2F3133; font-size: 19px; font-weight: bold; text-align: left;',
'paragraph' => 'margin-top: 0; color: #74787E; font-size: 16px; line-height: 1.5em;',
'paragraph-sub' => 'margin-top: 0; color: #74787E; font-size: 12px; line-height: 1.5em;',
'paragraph-center' => 'text-align: center;',

/* Buttons ------------------------------ */

'button' => 'display: block; display: inline-block; width: 200px; min-height: 20px; padding: 10px;
background-color: #3869D4; border-radius: 3px; color: #ffffff; font-size: 15px; line-height: 25px;
text-align: center; text-decoration: none; -webkit-text-size-adjust: none;',

'button--green' => 'background-color: #22BC66;',
'button--red' => 'background-color: #dc4d2f;',
'button--blue' => 'background-color: #3869D4;',
'label-small' => 'color:gray; font-size:13px;',
];

$fontFamily = 'font-family: Arial, \'Helvetica Neue\', Helvetica, sans-serif;';

$view->with(compact('style', 'fontFamily'));
});
}
}
39 changes: 39 additions & 0 deletions app/Repositories/EmployeeRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Repositories;

use DB;
use App\Repositories\EloquentRepository;
use App\User;
use Carbon\Carbon;
use App\Repositories\Interfaces\EmployeeRepositoryInterface;

class EmployeeRepository extends EloquentRepository implements EmployeeRepositoryInterface
{
protected $allowedAttributes = ['model'];

public function __construct(User $model)
{
$this->model = $model;
}

public function getAdminUsers()
{
return $this->model->where('role', $this->model::USER_ROLE_ADMIN)->get();
}

public function getEmployeeUsers()
{
return $this->model->where('role', $this->model::USER_ROLE_EMPLOYEE)->get();
}

public function getEmployeesWithBirtheyOn(Carbon $date)
{
$birthday_date = '%' . $date->format('-m-d');

return $this->model
->where('role', $this->model::USER_ROLE_EMPLOYEE)
->where('birth_date', 'LIKE', $birthday_date)
->get();
}
}
39 changes: 39 additions & 0 deletions app/Repositories/Interfaces/EmployeeRepositoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Repositories\Interfaces;

use Carbon\Carbon;

/**
* EmployeeRepositoryInterface defines the functions that every
* concrete repository implementation MUST have in order to not
* break the system workflow.
*/
interface EmployeeRepositoryInterface
{
/**
* This method SHOULD return the collection of admin users
* in the database.
*
* @return Illuminate\Support\Collection
*/
public function getAdminUsers();

/**
* This method SHOULD return the collection of employees
* users in the database.
*
* @return Illuminate\Support\Collection
*/
public function getEmployeeUsers();

/**
* This method SHOULD return the collection of employees
* that have the birth date on the date given as parameter.
*
* @param Carbon\Carbon $date The date to use as reference.
*
* @return Illuminate\Support\Collection
*/
public function getEmployeesWithBirtheyOn(Carbon $date);
}
18 changes: 15 additions & 3 deletions app/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class User extends Authenticatable

public function setEmailAttribute($email)
{
if(!$email) {
if (!$email) {
$this->attributes['email'] = null;
} else {
$this->attributes['email'] = $email;
Expand All @@ -50,7 +50,7 @@ public function setEmailAttribute($email)

public function setBirthDateAttribute($birthDate)
{
if(!$birthDate) {
if (!$birthDate) {
$this->attributes['birth_date'] = null;
} else {
$this->attributes['birth_date'] = $birthDate;
Expand All @@ -59,13 +59,25 @@ public function setBirthDateAttribute($birthDate)

public function setNotesAttribute($notes)
{
if(!$notes) {
if (!$notes) {
$this->attributes['notes'] = null;
} else {
$this->attributes['notes'] = $notes;
}
}

/**
* This mutator allow us to access the attribute 'name'
* on the instantiated objects even if we don't have a
* column in the database for it.
*
* @return String The concatenation of the first_name and last_name.
*/
public function getNameAttribute()
{
return $this->first_name . ' ' . $this->last_name;
}

public function jobs()
{
return $this->belongsTo(UserJobs::class);
Expand Down
38 changes: 38 additions & 0 deletions resources/lang/en/emails.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

return [

/*
|--------------------------------------------------------------------------
| Emails Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default email messages used by
| the email views.
|
*/
'generic' => [
'action_text' => 'Click Here',
'action_trouble' => 'If you’re having trouble clicking the ":actiontext" button, copy and paste the URL below into your web browser:',
],

/*
|--------------------------------------------------------------------------
| Birthday Emails Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the messages used in the birthday
| email views and subject lines.
|
*/
'birthdays' => [
'reminder' => [
'subject' => 'Birthday Reminder!',
'greetings' => 'Hello :name,',
'intro' => 'On day :date is the birthday to your employees listed below:',
'outro' => 'Don\'t miss the chance to organize something and celebrate with them their aging!',
'salutation' => 'Regards, ',
],
],

];
40 changes: 40 additions & 0 deletions resources/views/emails/birthdays/reminder.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

@extends('layouts.mail')

@section('content')

<!-- CTA Button Text Definition -->
<?php $action_text = isset($action_text) ? $action_text : trans('emails.generic.reminder.action_text'); ?>

<table style="{{ $style['email-body_inner'] }}" align="center" width="570" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $fontFamily }} {{ $style['email-body_cell'] }}">
<!-- Greeting -->
<h1 style="{{ $style['header-1'] }}">
{{trans('emails.birthdays.reminder.greetings', ['name' => $admin->name])}}
</h1>

<!-- Intro -->
<p style="{{ $style['paragraph'] }}">
{{trans('emails.birthdays.reminder.intro', ['date' => $date->format('d/m/Y')])}}
</p>

<p style="{{ $style['paragraph'] }}">
@foreach ($employees as $employee)
{{ $employee->name }} <label style="{{ $style['label-small'] }}">({{ $employee->email }})</label> <br>
@endforeach
</p>

<!-- Outro -->
<p style="{{ $style['paragraph'] }}">
{{trans('emails.birthdays.reminder.outro')}}
</p>

<!-- Salutation -->
<p style="{{ $style['paragraph'] }}">
{{ trans('emails.birthdays.reminder.salutation') }} <br> {{ config('app.name') }}
</p>
</td>
</tr>
</table>
@endsection
58 changes: 58 additions & 0 deletions resources/views/layouts/mail.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html>

<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<style type="text/css" rel="stylesheet" media="all">
/* Media Queries */
@media only screen and (max-width: 500px) {
.button {
width: 100% !important;
}
}
</style>
</head>

<body style="{{ $style['body'] }}">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $style['email-wrapper'] }}" align="center">
<table width="100%" cellpadding="0" cellspacing="0">
<!-- Logo -->
<tr>
<td style="{{ $style['email-masthead'] }}">
<a style="{{ $fontFamily }} {{ $style['email-masthead_name'] }}" href="{{ url('/') }}" target="_blank">
{{ config('app.name') }}
</a>
</td>
</tr>
<!-- Email Body -->
<tr>
<td style="{{ $style['email-body'] }}" width="100%">
@yield('content')
</td>
</tr>
<!-- Footer -->
<tr>
<td>
<table style="{{ $style['email-footer'] }}" align="center" width="570" cellpadding="0" cellspacing="0">
<tr>
<td style="{{ $fontFamily }} {{ $style['email-footer_cell'] }}">
<p style="{{ $style['paragraph-sub'] }}">
&copy; {{ date('Y') }}
<a style="{{ $style['anchor'] }}" href="{{ url('/') }}" target="_blank">{{ config('app.name') }}</a>.
All rights reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
Loading