Skip to content
Merged
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
25 changes: 25 additions & 0 deletions app/app/Enums/InvoiceType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Enums;

/**
* Invoice Types
*/
abstract class InvoiceType
{
public const RECURRING_BILL = 'RECURRING_BILL';
public const ONE_TIME_UPGRADE = 'ONE_TIME_UPGRADE';
public const ONE_TIME_CREDITS = 'ONE_TIME_CREDITS';

/**
* Optional: Helper to get all values for validation
*/
public static function all(): array
{
return [
self::RECURRING_BILL,
self::ONE_TIME_UPGRADE,
self::ONE_TIME_CREDITS,
];
}
}
5 changes: 3 additions & 2 deletions app/app/Helpers/EmailHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ private static function isUnsubscribed($user, $templateName)

foreach (self::$categorizedEmails as $category => $templates) {
if (in_array($templateName, $templates, true)) {
return isset($user->$category) && (bool) $user->$category === false;
$attributeName = 'email_mute_' . $category;
return isset($user->$attributeName) && (bool) $user->$attributeName === false;
}
}
return false;
Expand Down Expand Up @@ -264,7 +265,7 @@ public static function sendWithSwift($subject, $to, $template, $data) {
*/
public static function sendEmail($subject, $to, $template, $data, $mailLib='SWIFT') {
$user = NULL;
if (!empty($data['user']) && $data['user'] instanceof Model) {
if (!empty($data['user']) && $data['user']) {
$user = $data['user'];
}

Expand Down
27 changes: 25 additions & 2 deletions app/app/Helpers/InvoiceHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ public static function generatePrettyInvoice($user, $workspace, $invoice)
$accountName = self::placeholderIfEmpty($user->company_name, "N/A");
$taxNumber = self::placeholderIfEmpty($user->tax_number);
if (is_null($tax)) {
$tax1 = "N/A";
$taxPercentage = "N/A";
$tax1 = NULL;
$taxPercentage = NULL;
} else {
$tax1 = $tax['name'];
$taxPercentage = sprintf("%d%%", $tax->tax_percentage);
Expand Down Expand Up @@ -196,4 +196,27 @@ public static function generatePrettyInvoice($user, $workspace, $invoice)
// $pdf = PDF::loadView('pdf.invoice_new', $mergedValues);
return $pdf;
}

public static function generateAccountNumber()
{
$timestamp = time();
$randomPart = str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);
$accountNumber = 'ACC' . substr($timestamp, -6) . $randomPart;

// Ensure uniqueness
$maxAttempts = 10;
$attempt = 0;
while ($attempt < $maxAttempts) {
if (!DB::table('workspaces')->where('account_no', $accountNumber)->exists()) {
return $accountNumber;
}
$randomPart = str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);
$accountNumber = 'ACC' . substr($timestamp, -6) . $randomPart;
$attempt++;
}

// Fallback: use UUID-based approach
return 'ACC' . strtoupper(substr(str_replace('-', '', uniqid('', true)), 0, 10));
}

}
33 changes: 17 additions & 16 deletions app/app/Http/Controllers/EmailController.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,41 +28,42 @@
class EmailController extends BaseController {

private function createOption($key, $optionsRecord) {

$labelKey = str_replace("email_mute_", "", $key);
return [
'name' => $key,
'label' => str_replace("_", " ", ucwords($key)),
'label' => str_replace("_", " ", ucwords($labelKey)),
'enabled' => $optionsRecord->{$key}
];
}
/**
* Show the application dashboard to the user.
* Show email unsubscribe options page.
*
* @return Response
*/
public function unsubscribe()
public function unsubscribe(Request $request)
{
// todo: get user from jwt token
//$user = WorkspaceUser::user();
$user = WorkspaceUser::all()[0];
$optionsRecord = UserEmailOption::where('user_id', $user->id)->first();
$token = $request->query('token');
$user = User::where('unsubscribe_token', $token)->first();

$emailOptions = [
'auditing' => $this->createOption('auditing', $optionsRecord),
'account_changes' => $this->createOption('account_changes', $optionsRecord),
'workspace_changes' => $this->createOption('workspace_changes', $optionsRecord),
'system_status_updates' => $this->createOption('system_status_updates', $optionsRecord),
'debugger' => $this->createOption('debugger', $optionsRecord)
'email_mute_auditing' => $this->createOption('email_mute_auditing', $user),
'email_mute_account_changes' => $this->createOption('email_mute_account_changes', $user),
'email_mute_workspace_changes' => $this->createOption('email_mute_workspace_changes', $user),
'email_mute_system_status_updates' => $this->createOption('email_mute_system_status_updates', $user),
'email_mute_debugger' => $this->createOption('email_mute_debugger', $user)
];

return view('pages.email_unsubscribe', compact('user', 'emailOptions'));
}

public function unsubscribe_update(Request $request)
{
// todo: get user from jwt token
//$user = WorkspaceUser::user();
$user = WorkspaceUser::all()[0];
$emailOptions = UserEmailOption::where('user_id', $user->id)->first();
$token = $request->query('token');
$user = User::where('unsubscribe_token', $token)->first();
$updatedOptions = $this->processEmailOptions( $request->all() );
$emailOptions->update( $updatedOptions );
$user->update( $updatedOptions );
$request->session()->flash('status', 'Email options were updated successfully.');
return redirect("/email/unsubscribe");
}
Expand Down
5 changes: 4 additions & 1 deletion app/app/Http/Controllers/RegisterController.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public function register(Request $request)
$planKey = $data['plan'] ?? 'pay-as-you-go';
$mainRouter = SIPRouter::getMainRouter();
$servicePlan = ServicePlan::where('key_name', $planKey)->firstOrFail();
$accountNo = InvoiceHelper::generateAccountNumber();


$workspace = Workspace::create([
'creator_id' => $user->id,
Expand All @@ -83,7 +85,8 @@ public function register(Request $request)
'api_secret' => MainHelper::createAPISecret(),
'plan' => $planKey,
'trial_mode' => TRUE,
'default_router_id' => $mainRouter->id
'default_router_id' => $mainRouter->id,
'account_no' => $accountNo
]);

PlanUsagePeriod::create([
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

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

class AddEmailSubscribingOptsToUsers extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
//
$table->boolean('email_mute_auditing')->default(TRUE);
$table->boolean('email_mute_account_changes')->default(TRUE);
$table->boolean('email_mute_workspace_changes')->default(TRUE);
$table->boolean('email_mute_system_status_updates')->default(TRUE);
$table->boolean('email_mute_debugger')->default(TRUE);
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
//
$table->dropColumn('email_mute_auditing');
$table->dropColumn('email_mute_account_changes');
$table->dropColumn('email_mute_workspace_changes');
$table->dropColumn('email_mute_system_status_updates');
$table->dropColumn('email_mute_debugger');
});
}
}
32 changes: 32 additions & 0 deletions app/database/migrations/2026_06_26_200147_add_invoice_type.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

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

class AddInvoiceType extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users_invoices', function (Blueprint $table) {
//
$table->string('invoice_type')->default('RECURRING_BILL');
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users_invoices', function (Blueprint $table) {
$table->dropColumn('invoice_type');
});
}
}
2 changes: 1 addition & 1 deletion app/generate_monthly_invoice.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
$month = new DateTime();
$month->modify('first day of this month');
$end = new DateTime();
$end->modify('last day of this month');
$end->modify('last day of next month');
$invoiceSubtotal = 100*100;
$callCosts = 100*20;
$recordingCosts = 100*20;
Expand Down
23 changes: 13 additions & 10 deletions app/resources/views/pdf/pretty_monthly_invoice.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@
}

.status-pill {
display: inline-block;
padding: 6px 12px;
border-radius: 16px;
background: #fff7ed;
Expand Down Expand Up @@ -337,21 +336,23 @@
</table>
</div>

<table class="header-table" border="0" cellspacing="0" cellpadding="0">
<table class="header-table" width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="header-logo-cell" valign="top">
<img src="{{$logo}}" alt="{{$site}}" class="logo" />
</td>
<td class="header-meta-cell" valign="top">
<td class="header-meta-cell" valign="top" align="right">
<div class="invoice-title">Invoice</div>
<div class="statement-label">{{$site}} monthly statement</div>
<div class="status-wrap"><span class="status-pill">{{$statusText}}</span></div>
<div class="status-wrap">
<span class="status-pill">{{$statusText}}</span>
</div>
</td>
</tr>
</table>
<div class="brand-rule">&nbsp;</div>

<table class="summary" border="0" cellspacing="0" cellpadding="0">
<table class="summary" width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<span class="label">Invoice Number</span>
Expand All @@ -368,7 +369,7 @@
@endif
</span>
</td>
<td>
<td align="right">
<span class="label">Total Due</span>
<span class="value total">{{MainHelper::toDollars($vars['invoice_amount'])}}</span>
</td>
Expand Down Expand Up @@ -459,10 +460,12 @@
<td>Total excluding tax</td>
<td class="right">{{MainHelper::toDollars($vars['invoice_amount_no_tax'])}}</td>
</tr>
<tr>
<td>{{$vars['tax_name']}} {{$vars['tax_percentage']}}</td>
<td class="right">{{MainHelper::toDollars($vars['tax_amount'])}}</td>
</tr>
@if (!empty($vars['tax_name']) && !empty($vars['tax_percentage']))
<tr>
<td>{{$vars['tax_name']}} {{$vars['tax_percentage']}}</td>
<td class="right">{{MainHelper::toDollars($vars['tax_amount'])}}</td>
</tr>
@endif
<tr class="grand">
<td>Total payment due</td>
<td class="right">{{MainHelper::toDollars($vars['invoice_amount'])}}</td>
Expand Down
Loading