Refactor ProcessRecurrings job by moving database transactions to repositories
MODIFY
app/Http/Controllers/EarningController.php
app/Http/Controllers/EarningController.php
@@ -37,6 +37,7 @@ class EarningController extends Controller
$this->earningRepository->create(
session('space')->id,
+ null,
$request->input('date'),
$request->input('description'),
Helper::rawNumberToInteger($request->input('amount'))

MODIFY
app/Http/Controllers/ImportController.php
app/Http/Controllers/ImportController.php
@@ -158,6 +158,7 @@ class ImportController extends Controller
$this->spendingRepository->create(
session('space')->id,
$import->id,
+ null,
$row['tag_id'],
$row['happened_on'],
$row['description'],

MODIFY
app/Http/Controllers/SpendingController.php
app/Http/Controllers/SpendingController.php
@@ -39,6 +39,7 @@ class SpendingController extends Controller
$this->spendingRepository->create(
session('space')->id,
null,
+ null,
$request->input('tag_id'),
$request->input('date'),
$request->input('description'),

MODIFY
app/Jobs/ProcessRecurrings.php
app/Jobs/ProcessRecurrings.php
namespace App\Jobs;
-use App\Models\Earning;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
-use App\Models\Recurring;
-use App\Models\Spending;
+use App\Repositories\EarningRepository;
+use App\Repositories\RecurringRepository;
+use App\Repositories\SpendingRepository;
use Exception;
class ProcessRecurrings implements ShouldQueue
@@ -19,31 +19,25 @@ class ProcessRecurrings implements ShouldQueue
use Queueable;
use SerializesModels;
+ private $recurringRepository;
+ private $earningRepository;
+ private $spendingRepository;
+
public function __construct()
{
//
}
- public function handle()
- {
- $day = (int) date('j');
+ public function handle(
+ RecurringRepository $recurringRepository,
+ EarningRepository $earningRepository,
+ SpendingRepository $spendingRepository
+ ) {
+ $this->recurringRepository = $recurringRepository;
+ $this->earningRepository = $earningRepository;
+ $this->spendingRepository = $spendingRepository;
- $recurrings = Recurring::where('interval', 'monthly')
- ->when((int) date('t') == $day, function ($query) use ($day) {
- return $query->where('day', '>=', $day);
- }, function ($query) use ($day) {
- return $query->where('day', $day);
- })
- ->where('starts_on', '<=', date('Y-m-d'))
- ->where(function ($query) {
- $query
- ->where('ends_on', '>=', date('Y-m-d'))
- ->orWhere('ends_on', null);
- })->where(function ($query) {
- $query
- ->where('last_used_on', '<', date('Y-m-d'))
- ->orWhere('last_used_on', null);
- })->get();
+ $recurrings = $this->recurringRepository->getDueByDayOfMonth();
foreach ($recurrings as $recurring) {
if ($recurring->type !== 'earning' && $recurring->type !== 'spending') {
@@ -51,28 +45,30 @@ class ProcessRecurrings implements ShouldQueue
}
if ($recurring->type === 'earning') {
- $earning = new Earning();
- $earning->space_id = $recurring->space_id;
- $earning->recurring_id = $recurring->id;
- $earning->happened_on = date('Y-m-d');
- $earning->description = $recurring->description;
- $earning->amount = $recurring->amount;
- $earning->save();
+ $this->earningRepository->create(
+ $recurring->space_id,
+ $recurring->id,
+ date('Y-m-d'),
+ $recurring->description,
+ $recurring->amount
+ );
}
if ($recurring->type === 'spending') {
- $spending = new Spending();
- $spending->space_id = $recurring->space_id;
- $spending->recurring_id = $recurring->id;
- $spending->tag_id = $recurring->tag_id;
- $spending->happened_on = date('Y-m-d');
- $spending->description = $recurring->description;
- $spending->amount = $recurring->amount;
- $spending->save();
+ $this->spendingRepository->create(
+ $recurring->space_id,
+ null,
+ $recurring->id,
+ $recurring->tag_id,
+ date('Y-m-d'),
+ $recurring->description,
+ $recurring->amount
+ );
}
- $recurring->last_used_on = date('Y-m-d');
- $recurring->save();
+ $this->recurringRepository->update($recurring->id, [
+ 'last_used_on' => date('Y-m-d')
+ ]);
}
}
}

MODIFY
app/Models/Earning.php
app/Models/Earning.php
@@ -16,6 +16,7 @@ class Earning extends Model
protected $fillable = [
'space_id',
+ 'recurring_id',
'happened_on',
'description',
'amount'

MODIFY
app/Models/Spending.php
app/Models/Spending.php
@@ -17,6 +17,7 @@ class Spending extends Model
protected $fillable = [
'space_id',
'import_id',
+ 'recurring_id',
'tag_id',
'happened_on',
'description',

MODIFY
app/Repositories/EarningRepository.php
app/Repositories/EarningRepository.php
@@ -16,10 +16,11 @@ class EarningRepository
];
}
- public function create(int $spaceId, string $date, string $description, int $amount): Earning
+ public function create(int $spaceId, ?int $recurringId, string $date, string $description, int $amount): Earning
{
return Earning::create([
'space_id' => $spaceId,
+ 'recurring_id' => $recurringId,
'happened_on' => $date,
'description' => $description,
'amount' => $amount

MODIFY
app/Repositories/RecurringRepository.php
app/Repositories/RecurringRepository.php
@@ -21,6 +21,40 @@ class RecurringRepository
];
}
+ /**
+ * Grabs recurrings that checks all of the following statements
+ * targeted day is today, or in future if today is last day of the month
+ * has a starting date of today, or earlier
+ * has no expiration date, or one that is in the future
+ * has not been used yet, or prior to today
+ */
+ public function getDueByDayOfMonth(): iterable
+ {
+ $dayOfMonth = (int) date('j');
+
+ $dateToday = date('Y-m-d');
+ $daysInMonth = (int) date('t');
+
+ return Recurring::where('interval', 'monthly')
+ ->when($daysInMonth == $dayOfMonth, function ($query) use ($dayOfMonth) {
+ return $query->where('day', '>=', $dayOfMonth);
+ }, function ($query) use ($dayOfMonth) {
+ return $query->where('day', $dayOfMonth);
+ })
+ ->where('starts_on', '<=', $dateToday)
+ ->where(function ($query) use ($dateToday) {
+ $query
+ ->where('ends_on', '>=', $dateToday)
+ ->orWhere('ends_on', null);
+ })
+ ->where(function ($query) use ($dateToday) {
+ $query
+ ->where('last_used_on', '<', $dateToday)
+ ->orWhere('last_used_on', null);
+ })
+ ->get();
+ }
+
public function create(
int $spaceId,
string $type,
@@ -46,4 +80,15 @@ class RecurringRepository
'amount' => $amount
]);
}
+
+ public function update(int $id, array $data): void
+ {
+ $recurring = Recurring::find($id);
+
+ if (!$recurring) {
+ throw new Exception('Could not find recurring with ID ' . $id);
+ }
+
+ $recurring->fill($data)->save();
+ }
}

MODIFY
app/Repositories/SpendingRepository.php
app/Repositories/SpendingRepository.php
@@ -20,6 +20,7 @@ class SpendingRepository
public function create(
int $spaceId,
?int $importId = null,
+ ?int $recurringId,
?int $tagId,
string $date,
string $description,
@@ -28,6 +29,7 @@ class SpendingRepository
return Spending::create([
'space_id' => $spaceId,
'import_id' => $importId,
+ 'recurring_id' => $recurringId,
'tag_id' => $tagId,
'happened_on' => $date,
'description' => $description,

Refactor ProcessRecurrings job by moving database transactions to repositories