diff --git a/VERSION.txt b/VERSION.txt
index 7620216932..f5ac77f2d0 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1 +1 @@
-5.12.26
\ No newline at end of file
+5.12.27
\ No newline at end of file
diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php
index 993e733175..c5820ba29d 100644
--- a/app/Http/Controllers/AccountController.php
+++ b/app/Http/Controllers/AccountController.php
@@ -86,8 +86,8 @@ class AccountController extends BaseController
}
- if ($request->has('hash') && config('ninja.cloudflare.turnstile.secret')) { //@todo once all platforms are implemented, we disable access to the rest of this route without a success response.
-
+ if ($request->has('hash') && config('ninja.cloudflare.turnstile.secret')) {
+
if (Secure::decrypt($request->input('hash')) !== $request->input('email')) {
return response()->json(['message' => 'Invalid Signup Payload'], 400);
}
diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php
index bb84d17abb..2a42b720a1 100644
--- a/app/Http/Controllers/Auth/ResetPasswordController.php
+++ b/app/Http/Controllers/Auth/ResetPasswordController.php
@@ -84,6 +84,24 @@ class ResetPasswordController extends Controller
*/
public function reset(Request $request)
{
+ // Safely decode URL-encoded token and email before validation
+ if ($request->has('token')) {
+ $token = $request->input('token');
+ // Only decode if it contains URL encoding characters
+ if (strpos($token, '%') !== false) {
+ $request->merge(['token' => urldecode($token)]);
+ }
+ }
+
+ if ($request->has('email')) {
+ $email = $request->input('email');
+ // Only decode if it contains URL encoding characters
+ if (strpos($email, '%') !== false) {
+ $request->merge(['email' => urldecode($email)]);
+ }
+
+ }
+
$request->validate($this->rules(), $this->validationErrorMessages());
// Here we will attempt to reset the user's password. If it is successful we
diff --git a/app/Http/Controllers/ConnectedAccountController.php b/app/Http/Controllers/ConnectedAccountController.php
index 2748b6d6b2..d08372a158 100644
--- a/app/Http/Controllers/ConnectedAccountController.php
+++ b/app/Http/Controllers/ConnectedAccountController.php
@@ -111,7 +111,7 @@ class ConnectedAccountController extends BaseController
nlog("microsoft");
nlog($email);
- if (auth()->user()->email != $email && MultiDB::checkUserEmailExists($email)) {
+ if (strtolower(auth()->user()->email) != strtolower($email) && MultiDB::checkUserEmailExists(strtolower($email))) {
return response()->json(['message' => ctrans('texts.email_already_register')], 400);
}
diff --git a/app/Http/Controllers/TaskController.php b/app/Http/Controllers/TaskController.php
index 1cc28e55ee..f62913fc6b 100644
--- a/app/Http/Controllers/TaskController.php
+++ b/app/Http/Controllers/TaskController.php
@@ -514,11 +514,13 @@ class TaskController extends BaseController
$tasks = Task::withTrashed()->whereIn('id', $this->transformKeys($ids))->company();
- if ($request->action == 'bulk_update' && $user->can('edit', $tasks->first())) {
+ $_tasks = (clone $tasks);
+
+ if ($request->action == 'bulk_update' && $user->can('edit', $_tasks->first())) {
$this->task_repo->bulkUpdate($tasks, $request->column, $request->new_value);
- return $this->listResponse(Task::withTrashed()->whereIn('id', $this->transformKeys($ids)));
+ return $this->listResponse(Task::withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
}
diff --git a/app/Http/Requests/Account/CreateAccountRequest.php b/app/Http/Requests/Account/CreateAccountRequest.php
index 2c39856c21..ac488dd0b5 100644
--- a/app/Http/Requests/Account/CreateAccountRequest.php
+++ b/app/Http/Requests/Account/CreateAccountRequest.php
@@ -62,7 +62,7 @@ class CreateAccountRequest extends Request
public function prepareForValidation()
{
- nlog(array_merge(['signup' => 'true', 'ipaddy' => request()->ip()], $this->all()));
+ nlog(array_merge(['signup' => 'true', 'ipaddy' => request()->ip(), 'headers' => request()->headers->all()], $this->all()));
$input = $this->all();
diff --git a/app/Jobs/EDocument/EInvoicePullDocs.php b/app/Jobs/EDocument/EInvoicePullDocs.php
index 26c2808dbe..2afaab0359 100644
--- a/app/Jobs/EDocument/EInvoicePullDocs.php
+++ b/app/Jobs/EDocument/EInvoicePullDocs.php
@@ -16,8 +16,12 @@ use App\Utils\Ninja;
use App\Models\Account;
use App\Models\Company;
use App\Utils\TempFile;
+use App\Services\Email\Email;
use Illuminate\Bus\Queueable;
+use App\Services\Email\EmailObject;
+use Illuminate\Support\Facades\App;
use App\Utils\Traits\SavesDocuments;
+use Illuminate\Mail\Mailables\Address;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
@@ -36,6 +40,8 @@ class EInvoicePullDocs implements ShouldQueue
public $tries = 1;
+ private int $einvoice_received_count = 0;
+
public function __construct()
{
}
@@ -64,6 +70,8 @@ class EInvoicePullDocs implements ShouldQueue
})
->each(function ($company) {
+ $this->einvoice_received_count = 0;
+
$response = \Illuminate\Support\Facades\Http::baseUrl(config('ninja.hosted_ninja_url'))
->withHeaders([
'Content-Type' => 'application/json',
@@ -86,6 +94,24 @@ class EInvoicePullDocs implements ShouldQueue
nlog($response->body());
}
+
+
+ if($this->einvoice_received_count > 0) {
+ App::setLocale($company->getLocale());
+
+ $mo = new EmailObject();
+ $mo->subject = ctrans('texts.einvoice_received_subject');
+ $mo->body = ctrans('texts.einvoice_received_body', ['count' => $this->einvoice_received_count]);
+ $mo->text_body = ctrans('texts.einvoice_received_body', ['count' => $this->einvoice_received_count]);
+ $mo->company_key = $company->company_key;
+ $mo->html_template = 'email.template.admin';
+ $mo->to = [new Address($company->owner()->email, $company->owner()->present()->name())];
+ // $mo->email_template_body = 'einvoice_received_body';
+ // $mo->email_template_subject = 'einvoice_received_subject';
+
+ Email::dispatch($mo, $company);
+ }
+
});
});
@@ -96,6 +122,8 @@ class EInvoicePullDocs implements ShouldQueue
$storecove = new Storecove();
+ $mail_payload = [];
+
foreach ($received_documents as $document) {
nlog($document);
$storecove_invoice = $storecove->expense->getStorecoveInvoice(json_encode($document['document']['invoice']));
@@ -125,6 +153,7 @@ class EInvoicePullDocs implements ShouldQueue
}
+ $this->einvoice_received_count++;
}
@@ -145,6 +174,8 @@ class EInvoicePullDocs implements ShouldQueue
if ($response->successful()) {
}
+
+
}
public function failed(\Throwable $exception)
diff --git a/app/Jobs/EDocument/MergeEDocument.php b/app/Jobs/EDocument/MergeEDocument.php
index 77881736c9..8c7a3654cc 100644
--- a/app/Jobs/EDocument/MergeEDocument.php
+++ b/app/Jobs/EDocument/MergeEDocument.php
@@ -31,6 +31,7 @@ class MergeEDocument implements ShouldQueue
*/
public function handle(): string
{
+ nlog("MergeEDocument:: handle");
$settings_entity = ($this->document instanceof PurchaseOrder) ? $this->document->vendor : $this->document->client;
$e_document_type = strlen($settings_entity->getSetting('e_invoice_type')) > 2 ? $settings_entity->getSetting('e_invoice_type') : "XInvoice_3_0";
diff --git a/app/Repositories/TaskRepository.php b/app/Repositories/TaskRepository.php
index 93c31d0131..e34ac8723a 100644
--- a/app/Repositories/TaskRepository.php
+++ b/app/Repositories/TaskRepository.php
@@ -16,6 +16,7 @@ use App\Models\Task;
use App\Models\Project;
use App\Factory\TaskFactory;
use App\Jobs\Task\TaskAssigned;
+use App\Utils\Traits\MakesHash;
use App\Utils\Traits\GeneratesCounter;
use Illuminate\Database\QueryException;
@@ -25,6 +26,7 @@ use Illuminate\Database\QueryException;
class TaskRepository extends BaseRepository
{
use GeneratesCounter;
+ use MakesHash;
public $new_task = true;
@@ -432,9 +434,14 @@ class TaskRepository extends BaseRepository
public function bulkUpdate(\Illuminate\Database\Eloquent\Builder $models, string $column, mixed $new_value): void
{
+
// First, filter out tasks that have been invoiced
$models->whereNull('invoice_id');
-
+
+ if(stripos($column, '_id') !== false) {
+ $new_value = $this->decodePrimaryKey($new_value);
+ }
+
if ($column === 'project_id') {
// Handle project_id updates with client_id synchronization
$project = Project::withTrashed()
@@ -449,7 +456,7 @@ class TaskRepository extends BaseRepository
'client_id' => $project->client_id,
]);
}
- } elseif ($column === 'client_id') {
+ } elseif ($column === 'client_id') {
// If you are updating the client - we will unset the project id!
$models->update([$column => $new_value, 'project_id' => null]);
}
diff --git a/app/Services/Client/ClientService.php b/app/Services/Client/ClientService.php
index 624059f0e3..7ed1f14d78 100644
--- a/app/Services/Client/ClientService.php
+++ b/app/Services/Client/ClientService.php
@@ -45,28 +45,31 @@ class ClientService
public function calculateBalance(?Invoice $invoice = null)
{
- $balance = Invoice::withTrashed()
- ->where('client_id', $this->client->id)
- ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
- ->where('is_deleted', false)
- ->sum('balance');
-
- $pre_client_balance = $this->client->balance;
+ // $pre_client_balance = $this->client->balance;
try {
+
+ $balance = Invoice::withTrashed()
+ ->where('client_id', $this->client->id)
+ ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
+ ->where('is_deleted', false)
+ ->sum('balance');
+
DB::connection(config('database.default'))->transaction(function () use ($balance) {
$this->client = Client::withTrashed()->where('id', $this->client->id)->lockForUpdate()->first();
$this->client->balance = $balance;
$this->client->saveQuietly();
}, 2);
+
+
} catch (\Throwable $throwable) {
nlog("DB ERROR " . $throwable->getMessage());
}
- if ($invoice && floatval($this->client->balance) != floatval($pre_client_balance)) {
- $diff = $this->client->balance - $pre_client_balance;
- $invoice->ledger()->insertInvoiceBalance($diff, $this->client->balance, "Update Adjustment Invoice # {$invoice->number} => {$diff}");
- }
+ // if ($invoice && floatval($this->client->balance) != floatval($pre_client_balance)) {
+ // $diff = $this->client->balance - $pre_client_balance;
+ // $invoice->ledger()->insertInvoiceBalance($diff, $this->client->balance, "Update Adjustment Invoice # {$invoice->number} => {$diff}");
+ // }
return $this;
}
@@ -116,14 +119,16 @@ class ClientService
public function updatePaymentBalance()
{
- $amount = Payment::query()
- ->withTrashed()
- ->where('client_id', $this->client->id)
- ->where('is_deleted', 0)
- ->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])
- ->selectRaw('SUM(payments.amount - payments.applied) as amount')->first()->amount ?? 0;
- DB::connection(config('database.default'))->transaction(function () use ($amount) {
+ DB::connection(config('database.default'))->transaction(function () {
+
+ $amount = Payment::query()
+ ->withTrashed()
+ ->where('client_id', $this->client->id)
+ ->where('is_deleted', 0)
+ ->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])
+ ->selectRaw('SUM(payments.amount - payments.applied) as amount')->first()->amount ?? 0;
+
$this->client = Client::withTrashed()->where('id', $this->client->id)->lockForUpdate()->first();
$this->client->payment_balance = $amount;
$this->client->saveQuietly();
diff --git a/app/Services/EDocument/Standards/ZugferdEDocument.php b/app/Services/EDocument/Standards/ZugferdEDocument.php
index 1a5eac1222..13c4770ca8 100644
--- a/app/Services/EDocument/Standards/ZugferdEDocument.php
+++ b/app/Services/EDocument/Standards/ZugferdEDocument.php
@@ -92,8 +92,8 @@ class ZugferdEDocument extends AbstractService
->setPaymentTerms() // 3. Then payment terms
->setLineItems() // 4. Then line items
->setCustomSurcharges() // 4a. Surcharges
- ->setDocumentSummation() // 5. Finally document summation
- ->setAdditionalReferencedDocument(); // 6. Additional referenced document
+ ->setDocumentSummation(); // 5. Finally document summation
+ // ->setAdditionalReferencedDocument(); // 6. Additional referenced document
return $this;
@@ -127,7 +127,17 @@ class ZugferdEDocument extends AbstractService
return $this;
}
-
+
+ /**
+ * setAdditionalReferencedDocument
+ *
+ * circular reference causing the file to never be created.
+ * PDF => xml => PDF => xml
+ *
+ * Need to abstract the insertion of the base64 document into the XML.
+ *
+ * @return self
+ */
private function setAdditionalReferencedDocument(): self
{
if($this->document->client->getSetting('merge_e_invoice_to_pdf')) {
diff --git a/app/Services/Email/AdminEmailMailable.php b/app/Services/Email/AdminEmailMailable.php
index 94842e495c..8a1370f5db 100644
--- a/app/Services/Email/AdminEmailMailable.php
+++ b/app/Services/Email/AdminEmailMailable.php
@@ -56,13 +56,12 @@ class AdminEmailMailable extends Mailable
*/
public function content()
{
-
return new Content(
view: 'email.admin.generic',
text: 'email.admin.generic_text',
with: [
'title' => $this->email_object->subject,
- 'message' => $this->email_object->body,
+ 'content' => $this->email_object->body,
'url' => $this->email_object->url ?? null,
'button' => $this->email_object->button ?? null,
'signature' => $this->email_object->company->owner()->signature,
diff --git a/app/Services/Payment/DeletePayment.php b/app/Services/Payment/DeletePayment.php
index 401fd70ce9..1246c113a5 100644
--- a/app/Services/Payment/DeletePayment.php
+++ b/app/Services/Payment/DeletePayment.php
@@ -154,7 +154,7 @@ class DeletePayment
if (abs(floatval($paymentable_invoice->balance) - floatval($paymentable_invoice->amount)) < 0.005) {
$paymentable_invoice->service()->setStatus(Invoice::STATUS_SENT)->save();
- } elseif (floatval($paymentable_invoice->balance) == 0) {
+ } elseif (abs(floatval($paymentable_invoice->balance)) < 0.005) {
$paymentable_invoice->service()->setStatus(Invoice::STATUS_PAID)->save();
} else {
$paymentable_invoice->service()->setStatus(Invoice::STATUS_PARTIAL)->save();
@@ -255,4 +255,4 @@ class DeletePayment
return $this->payment;
}
-}
+}
\ No newline at end of file
diff --git a/app/Utils/BcMath.php b/app/Utils/BcMath.php
new file mode 100644
index 0000000000..2b68052c5c
--- /dev/null
+++ b/app/Utils/BcMath.php
@@ -0,0 +1,375 @@
+= 0;
+ }
+
+ /**
+ * Check if left number is less than right number using bcmath
+ *
+ * @param string|float|int $left
+ * @param string|float|int $right
+ * @param int|null $scale
+ * @return bool
+ */
+ public static function lessThan($left, $right, ?int $scale = null): bool
+ {
+ return self::comp($left, $right, $scale) === -1;
+ }
+
+ /**
+ * Check if left number is less than or equal to right number using bcmath
+ *
+ * @param string|float|int $left
+ * @param string|float|int $right
+ * @param int|null $scale
+ * @return bool
+ */
+ public static function lessThanOrEqual($left, $right, ?int $scale = null): bool
+ {
+ return self::comp($left, $right, $scale) <= 0;
+ }
+
+ /**
+ * Check if a number is zero using bcmath
+ *
+ * @param string|float|int $number
+ * @param int|null $scale
+ * @return bool
+ */
+ public static function isZero($number, ?int $scale = null): bool
+ {
+ return self::equal($number, '0', $scale);
+ }
+
+ /**
+ * Check if a number is positive using bcmath
+ *
+ * @param string|float|int $number
+ * @param int|null $scale
+ * @return bool
+ */
+ public static function isPositive($number, ?int $scale = null): bool
+ {
+ return self::greaterThan($number, '0', $scale);
+ }
+
+ /**
+ * Check if a number is negative using bcmath
+ *
+ * @param string|float|int $number
+ * @param int|null $scale
+ * @return bool
+ */
+ public static function isNegative($number, ?int $scale = null): bool
+ {
+ return self::lessThan($number, '0', $scale);
+ }
+
+ /**
+ * Get the absolute value using bcmath
+ *
+ * @param string|float|int $number
+ * @param int|null $scale
+ * @return string
+ */
+ public static function abs($number, ?int $scale = null): string
+ {
+ $scale = $scale ?? self::DEFAULT_SCALE;
+ $number = (string)$number;
+
+ if (self::isNegative($number, $scale)) {
+ return self::mul($number, '-1', $scale);
+ }
+
+ return $number;
+ }
+
+ /**
+ * Calculate percentage using bcmath
+ *
+ * @param string|float|int $part
+ * @param string|float|int $total
+ * @param int|null $scale
+ * @return string
+ */
+ public static function percentage($part, $total, ?int $scale = null): string
+ {
+ $scale = $scale ?? self::DEFAULT_SCALE;
+
+ if (self::isZero($total, $scale)) {
+ return '0';
+ }
+
+ return self::mul(self::div($part, $total, $scale + 2), '100', $scale);
+ }
+
+ /**
+ * Calculate sum of an array of numbers using bcmath
+ *
+ * @param array $numbers
+ * @param int|null $scale
+ * @return string
+ */
+ public static function sum(array $numbers, ?int $scale = null): string
+ {
+ $scale = $scale ?? self::DEFAULT_SCALE;
+ $result = '0';
+
+ foreach ($numbers as $number) {
+ $result = self::add($result, $number, $scale);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Calculate average of an array of numbers using bcmath
+ *
+ * @param array $numbers
+ * @param int|null $scale
+ * @return string
+ */
+ public static function avg(array $numbers, ?int $scale = null): string
+ {
+ $scale = $scale ?? self::DEFAULT_SCALE;
+ $count = count($numbers);
+
+ if ($count === 0) {
+ return '0';
+ }
+
+ $sum = self::sum($numbers, $scale);
+ return self::div($sum, (string)$count, $scale);
+ }
+
+ /**
+ * Format a number as currency string with proper precision
+ *
+ * @param string|float|int $number
+ * @param int $precision
+ * @return string
+ */
+ public static function formatCurrency($number, int $precision = self::DEFAULT_SCALE): string
+ {
+ $rounded = self::round($number, $precision);
+ return number_format((float)$rounded, $precision, '.', '');
+ }
+
+ /**
+ * Convert a number to float for compatibility with existing code
+ * Use this sparingly and only when you need to pass values to functions that expect floats
+ *
+ * @param string|float|int $number
+ * @return float
+ */
+ public static function toFloat($number): float
+ {
+ return (float)$number;
+ }
+
+ /**
+ * Convert a number to string for consistent handling
+ *
+ * @param string|float|int $number
+ * @return string
+ */
+ public static function toString($number): string
+ {
+ return (string)$number;
+ }
+}
diff --git a/app/Utils/Statics.php b/app/Utils/Statics.php
index c82d7ec44e..dbbe3d3b79 100644
--- a/app/Utils/Statics.php
+++ b/app/Utils/Statics.php
@@ -127,6 +127,7 @@ class Statics
'client' => \App\Models\Client::$bulk_update_columns,
'expense' => \App\Models\Expense::$bulk_update_columns,
'recurring_invoice' => \App\Models\RecurringInvoice::$bulk_update_columns,
+ 'task' => \App\Models\Task::$bulk_update_columns,
];
return $data;
diff --git a/composer.lock b/composer.lock
index 08eb077d3e..2c7dfe7bef 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1119,25 +1119,25 @@
},
{
"name": "brick/math",
- "version": "0.13.1",
+ "version": "0.14.0",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
- "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04"
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04",
- "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04",
+ "url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
+ "reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
"shasum": ""
},
"require": {
- "php": "^8.1"
+ "php": "^8.2"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
- "phpunit/phpunit": "^10.1",
- "vimeo/psalm": "6.8.8"
+ "phpstan/phpstan": "2.1.22",
+ "phpunit/phpunit": "^11.5"
},
"type": "library",
"autoload": {
@@ -1167,7 +1167,7 @@
],
"support": {
"issues": "https://github.com/brick/math/issues",
- "source": "https://github.com/brick/math/tree/0.13.1"
+ "source": "https://github.com/brick/math/tree/0.14.0"
},
"funding": [
{
@@ -1175,7 +1175,7 @@
"type": "github"
}
],
- "time": "2025-03-29T13:50:30+00:00"
+ "time": "2025-08-29T12:40:03+00:00"
},
{
"name": "btcpayserver/btcpayserver-greenfield-php",
@@ -8518,16 +8518,16 @@
},
{
"name": "open-telemetry/api",
- "version": "1.4.0",
+ "version": "1.5.0",
"source": {
"type": "git",
"url": "https://github.com/opentelemetry-php/api.git",
- "reference": "b3a9286f9c1c8247c83493c5b1fa475cd0cec7f7"
+ "reference": "7692075f486c14d8cfd37fba98a08a5667f089e5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/b3a9286f9c1c8247c83493c5b1fa475cd0cec7f7",
- "reference": "b3a9286f9c1c8247c83493c5b1fa475cd0cec7f7",
+ "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/7692075f486c14d8cfd37fba98a08a5667f089e5",
+ "reference": "7692075f486c14d8cfd37fba98a08a5667f089e5",
"shasum": ""
},
"require": {
@@ -8584,7 +8584,7 @@
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
"source": "https://github.com/open-telemetry/opentelemetry-php"
},
- "time": "2025-06-19T23:36:51+00:00"
+ "time": "2025-08-07T23:07:38+00:00"
},
{
"name": "open-telemetry/context",
@@ -9521,16 +9521,16 @@
},
{
"name": "phpoffice/phpspreadsheet",
- "version": "2.4.0",
+ "version": "2.4.1",
"source": {
"type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
- "reference": "3a3cad86101a77019eb2fc693aab1a8c11b18b94"
+ "reference": "096ae6faf94b49b2cf53e92a0073133c941e1f57"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/3a3cad86101a77019eb2fc693aab1a8c11b18b94",
- "reference": "3a3cad86101a77019eb2fc693aab1a8c11b18b94",
+ "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/096ae6faf94b49b2cf53e92a0073133c941e1f57",
+ "reference": "096ae6faf94b49b2cf53e92a0073133c941e1f57",
"shasum": ""
},
"require": {
@@ -9620,9 +9620,9 @@
],
"support": {
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
- "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/2.4.0"
+ "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/2.4.1"
},
- "time": "2025-08-10T06:45:13+00:00"
+ "time": "2025-09-01T18:41:37+00:00"
},
{
"name": "phpoption/phpoption",
@@ -10752,20 +10752,20 @@
},
{
"name": "ramsey/uuid",
- "version": "4.9.0",
+ "version": "4.9.1",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
- "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0"
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0",
- "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+ "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
"shasum": ""
},
"require": {
- "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13",
+ "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
"php": "^8.0",
"ramsey/collection": "^1.2 || ^2.0"
},
@@ -10824,9 +10824,9 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
- "source": "https://github.com/ramsey/uuid/tree/4.9.0"
+ "source": "https://github.com/ramsey/uuid/tree/4.9.1"
},
- "time": "2025-06-25T14:20:11+00:00"
+ "time": "2025-09-04T20:59:21+00:00"
},
{
"name": "razorpay/razorpay",
@@ -11266,23 +11266,23 @@
},
{
"name": "sentry/sentry-laravel",
- "version": "4.15.1",
+ "version": "4.15.3",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-laravel.git",
- "reference": "7e0675e8e06d1ec5cb623792892920000a3aedb5"
+ "reference": "c3f71a83e8b3a1451e811199d145e864519cecc1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/7e0675e8e06d1ec5cb623792892920000a3aedb5",
- "reference": "7e0675e8e06d1ec5cb623792892920000a3aedb5",
+ "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/c3f71a83e8b3a1451e811199d145e864519cecc1",
+ "reference": "c3f71a83e8b3a1451e811199d145e864519cecc1",
"shasum": ""
},
"require": {
"illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0",
"nyholm/psr7": "^1.0",
"php": "^7.2 | ^8.0",
- "sentry/sentry": "^4.14.1",
+ "sentry/sentry": "^4.15.2",
"symfony/psr-http-message-bridge": "^1.0 | ^2.0 | ^6.0 | ^7.0"
},
"require-dev": {
@@ -11339,7 +11339,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-laravel/issues",
- "source": "https://github.com/getsentry/sentry-laravel/tree/4.15.1"
+ "source": "https://github.com/getsentry/sentry-laravel/tree/4.15.3"
},
"funding": [
{
@@ -11351,7 +11351,7 @@
"type": "custom"
}
],
- "time": "2025-06-24T12:39:03+00:00"
+ "time": "2025-09-04T14:37:41+00:00"
},
{
"name": "setasign/fpdf",
@@ -18084,16 +18084,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
- "version": "v3.87.0",
+ "version": "v3.87.1",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
- "reference": "50a13c4c5f25d2c6894e30e92c051474cf0e115a"
+ "reference": "2f5170365e2a422d0c5421f9c8818b2c078105f6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/50a13c4c5f25d2c6894e30e92c051474cf0e115a",
- "reference": "50a13c4c5f25d2c6894e30e92c051474cf0e115a",
+ "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/2f5170365e2a422d0c5421f9c8818b2c078105f6",
+ "reference": "2f5170365e2a422d0c5421f9c8818b2c078105f6",
"shasum": ""
},
"require": {
@@ -18126,7 +18126,7 @@
"require-dev": {
"facile-it/paraunit": "^1.3.1 || ^2.7",
"infection/infection": "^0.29.14",
- "justinrainbow/json-schema": "^6.4",
+ "justinrainbow/json-schema": "^6.5",
"keradus/cli-executor": "^2.2",
"mikey179/vfsstream": "^1.6.12",
"php-coveralls/php-coveralls": "^2.8",
@@ -18176,7 +18176,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
- "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v97773{PHP_CS_FIXER_VERSION}"
+ "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.87.1"
},
"funding": [
{
@@ -18184,7 +18184,7 @@
"type": "github"
}
],
- "time": "2025-09-02T10:58:35+00:00"
+ "time": "2025-09-02T15:27:36+00:00"
},
{
"name": "hamcrest/hamcrest-php",
@@ -19194,16 +19194,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "11.5.35",
+ "version": "11.5.36",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "d341ee94ee5007b286fc7907b383aae6b5b3cc91"
+ "reference": "264a87c7ef68b1ab9af7172357740dc266df5957"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d341ee94ee5007b286fc7907b383aae6b5b3cc91",
- "reference": "d341ee94ee5007b286fc7907b383aae6b5b3cc91",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/264a87c7ef68b1ab9af7172357740dc266df5957",
+ "reference": "264a87c7ef68b1ab9af7172357740dc266df5957",
"shasum": ""
},
"require": {
@@ -19275,7 +19275,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.35"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.36"
},
"funding": [
{
@@ -19299,7 +19299,7 @@
"type": "tidelift"
}
],
- "time": "2025-08-28T05:13:54+00:00"
+ "time": "2025-09-03T06:24:17+00:00"
},
{
"name": "react/cache",
diff --git a/config/ninja.php b/config/ninja.php
index 282acdac63..4c0508de02 100644
--- a/config/ninja.php
+++ b/config/ninja.php
@@ -17,7 +17,7 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
- 'app_version' => env('APP_VERSION', '5.12.26'),
+ 'app_version' => env('APP_VERSION', '5.12.27'),
'app_tag' => env('APP_TAG', '5.12.26'),
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
diff --git a/lang/en/texts.php b/lang/en/texts.php
index 582a6abb28..733146f182 100644
--- a/lang/en/texts.php
+++ b/lang/en/texts.php
@@ -5631,7 +5631,10 @@ $lang = array(
'replaced' => 'Replaced',
'ses_from_address' => 'SES From Address',
'ses_from_address_help' => 'The Sending Email Address, must be verified in AWS',
- 'unauthorized_action' => 'You are not authorized to perform this action',
+ 'unauthorized_action' => 'You are not authorized to perform this action',
+ 'einvoice_received_subject' => 'E-Invoice/s Received',
+ 'einvoice_received_body' => 'You have received :count new E-Invoice/s.
Login to view.',
+
);
return $lang;
diff --git a/resources/views/auth/passwords/reset.blade.php b/resources/views/auth/passwords/reset.blade.php
index 664ef7838a..b22748f253 100644
--- a/resources/views/auth/passwords/reset.blade.php
+++ b/resources/views/auth/passwords/reset.blade.php
@@ -12,7 +12,7 @@