Skip to content

Commit

Permalink
Merge pull request #286 from liberu-billing/sweep/Add-Customizable-Em…
Browse files Browse the repository at this point in the history
…ail-Templates-for-Billing-Notifications

Add Customizable Email Templates for Billing Notifications
  • Loading branch information
curtisdelicata authored Dec 24, 2024
2 parents d189940 + d7dd85d commit 843b7fb
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 4 deletions.
74 changes: 74 additions & 0 deletions app/Http/Controllers/EmailTemplateController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@


<?php

namespace App\Http\Controllers;

use App\Models\EmailTemplate;
use Illuminate\Http\Request;

class EmailTemplateController extends Controller
{
public function index()
{
$templates = EmailTemplate::where(function($query) {
$query->where('team_id', auth()->user()->currentTeam->id)
->orWhere('is_default', true);
})->get();

return view('email-templates.index', compact('templates'));
}

public function create()
{
$types = [
'invoice_generated' => 'Invoice Generated',
'overdue_reminder' => 'Overdue Reminder',
];
return view('email-templates.create', compact('types'));
}

public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'type' => 'required|string',
'subject' => 'required|string|max:255',
'body' => 'required|string',
]);

$validated['team_id'] = auth()->user()->currentTeam->id;

EmailTemplate::create($validated);

return redirect()->route('email-templates.index')
->with('success', 'Template created successfully');
}

public function edit(EmailTemplate $template)
{
$this->authorize('update', $template);
$types = [
'invoice_generated' => 'Invoice Generated',
'overdue_reminder' => 'Overdue Reminder',
];
return view('email-templates.edit', compact('template', 'types'));
}

public function update(Request $request, EmailTemplate $template)
{
$this->authorize('update', $template);

$validated = $request->validate([
'name' => 'required|string|max:255',
'type' => 'required|string',
'subject' => 'required|string|max:255',
'body' => 'required|string',
]);

$template->update($validated);

return redirect()->route('email-templates.index')
->with('success', 'Template updated successfully');
}
}
27 changes: 23 additions & 4 deletions app/Mail/InvoiceGenerated.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,55 @@
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
use App\Models\Invoice;
use App\Models\EmailTemplate;

class InvoiceGenerated extends Mailable
{
use Queueable, SerializesModels;

public $invoice;
protected $template;

public function __construct(Invoice $invoice)
{
$this->invoice = $invoice;
$this->template = EmailTemplate::getTemplate('invoice_generated', $invoice->team_id);
}

public function envelope(): Envelope
{
return new Envelope(
subject: 'Invoice Generated',
subject: $this->template ?
$this->parseTemplate($this->template->subject) :
'Invoice Generated',
);
}

public function content(): Content
{
return new Content(
view: 'emails.invoice-generated',
view: 'emails.dynamic-template',
with: [
'content' => $this->template ?
$this->parseTemplate($this->template->body) :
view('emails.invoice-generated', ['invoice' => $this->invoice])->render(),
'invoice' => $this->invoice,
'template' => $this->invoice->template
]
],
);
}

protected function parseTemplate($text)
{
$replacements = [
'{{invoice_number}}' => $this->invoice->invoice_number,
'{{amount}}' => $this->invoice->total_amount,
'{{due_date}}' => $this->invoice->due_date->format('Y-m-d'),
'{{customer_name}}' => $this->invoice->customer->name,
];

return strtr($text, $replacements);
}

public function attachments(): array
{
return [];
Expand Down
34 changes: 34 additions & 0 deletions app/Models/EmailTemplate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Traits\HasTeam;

class EmailTemplate extends Model
{
use HasFactory, HasTeam;

protected $fillable = [
'name',
'type',
'subject',
'body',
'team_id',
'is_default'
];

public static function getTemplate($type, $teamId = null)
{
return static::where('type', $type)
->where(function ($query) use ($teamId) {
$query->where('team_id', $teamId)
->orWhere('is_default', true);
})
->orderBy('team_id', 'desc') // Prioritize team templates
->first();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@


<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up()
{
Schema::create('email_templates', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('type'); // invoice_generated, overdue_reminder, etc.
$table->string('subject');
$table->text('body');
$table->foreignId('team_id')->nullable()->constrained()->cascadeOnDelete();
$table->boolean('is_default')->default(false);
$table->timestamps();
});
}

public function down()
{
Schema::dropIfExists('email_templates');
}
};
40 changes: 40 additions & 0 deletions database/seeders/EmailTemplateSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@


<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\EmailTemplate;

class EmailTemplateSeeder extends Seeder
{
public function run()
{
EmailTemplate::create([
'name' => 'Default Invoice Generated',
'type' => 'invoice_generated',
'subject' => 'Invoice #{{invoice_number}} Generated',
'body' => 'Dear {{customer_name}},
Your invoice #{{invoice_number}} has been generated for the amount of {{amount}}.
Due date: {{due_date}}
Thank you for your business!',
'is_default' => true,
]);

EmailTemplate::create([
'name' => 'Default Overdue Reminder',
'type' => 'overdue_reminder',
'subject' => 'Overdue Invoice Reminder #{{invoice_number}}',
'body' => 'Dear {{customer_name}},
This is a reminder that invoice #{{invoice_number}} for {{amount}} is overdue.
Please process the payment as soon as possible.
Thank you for your attention to this matter.',
'is_default' => true,
]);
}
}
11 changes: 11 additions & 0 deletions resources/views/emails/dynamic-template.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
{!! $content !!}
</body>
</html>

0 comments on commit 843b7fb

Please sign in to comment.