Merge pull request #4 from karneaud/v5-develop

V5 develop
This commit is contained in:
Kendall Arneaud 2024-06-26 21:38:40 -04:00 committed by GitHub
commit 59ae2be01e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 489 additions and 93 deletions

View File

@ -1 +1 @@
5.10.2 5.10.3

View File

@ -46,7 +46,7 @@ class WebhookFilters extends QueryFilters
{ {
$sort_col = explode('|', $sort); $sort_col = explode('|', $sort);
if (!is_array($sort_col) || count($sort_col) != 2) { if (!is_array($sort_col) || count($sort_col) != 2 || !in_array($sort_col[0], \Illuminate\Support\Facades\Schema::getColumnListing('webhooks'))) {
return $this->builder; return $this->builder;
} }

View File

@ -77,7 +77,11 @@ class UpdateUserRequest extends Request
unset($input['oauth_user_token']); unset($input['oauth_user_token']);
} }
if(isset($input['password']) && strlen($input['password'] ?? '') > 1)
{
$input['password'] = trim($input['password']);
}
$this->replace($input); $this->replace($input);
} }
} }

View File

@ -104,10 +104,10 @@ class Gateway extends StaticModel
} elseif ($this->id == 59) { } elseif ($this->id == 59) {
$link = 'https://www.forte.net/'; $link = 'https://www.forte.net/';
} elseif ($this->id == 62) { } elseif ($this->id == 62) {
$link = 'https://docs.btcpayserver.org'; $link = 'https://docs.btcpayserver.org/InvoiceNinja/';
} elseif ($this->id == 4002) { } elseif ($this->id == 4002) {
$link = 'https://rotessa.com'; $link = 'https://rotessa.com';
} }
return $link; return $link;
} }

View File

@ -11,35 +11,36 @@
namespace App\PaymentDrivers; namespace App\PaymentDrivers;
use App\Events\Invoice\InvoiceWasPaid;
use App\Events\Payment\PaymentWasCreated;
use App\Exceptions\PaymentFailed;
use App\Factory\PaymentFactory;
use App\Jobs\Mail\NinjaMailer;
use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject;
use App\Jobs\Mail\PaymentFailedMailer;
use App\Jobs\Util\SystemLogger;
use App\Mail\Admin\ClientPaymentFailureObject;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\ClientGatewayToken;
use App\Models\CompanyGateway;
use App\Models\GatewayType;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\SystemLog;
use App\Services\Subscription\SubscriptionService;
use App\Utils\Helpers;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Utils\Number; use App\Utils\Number;
use App\Utils\Traits\MakesHash; use App\Models\Client;
use App\Utils\Traits\SystemLogTrait; use App\Utils\Helpers;
use Illuminate\Http\Request; use App\Models\Invoice;
use Illuminate\Support\Carbon; use App\Models\Payment;
use Illuminate\Support\Facades\App; use App\Models\SystemLog;
use App\Models\GatewayType;
use App\Models\PaymentHash;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Models\ClientContact;
use App\Jobs\Mail\NinjaMailer;
use App\Models\CompanyGateway;
use Illuminate\Support\Carbon;
use App\DataMapper\InvoiceItem;
use App\Factory\PaymentFactory;
use App\Jobs\Util\SystemLogger;
use App\Utils\Traits\MakesHash;
use App\Exceptions\PaymentFailed;
use App\Jobs\Mail\NinjaMailerJob;
use App\Models\ClientGatewayToken;
use Illuminate\Support\Facades\App;
use App\Jobs\Mail\NinjaMailerObject;
use App\Utils\Traits\SystemLogTrait;
use App\Events\Invoice\InvoiceWasPaid;
use App\Jobs\Mail\PaymentFailedMailer;
use App\Events\Payment\PaymentWasCreated;
use App\Mail\Admin\ClientPaymentFailureObject;
use App\Services\Subscription\SubscriptionService;
/** /**
* Class BaseDriver. * Class BaseDriver.
@ -394,14 +395,71 @@ class BaseDriver extends AbstractPaymentDriver
/*Fee charged at gateway*/ /*Fee charged at gateway*/
$fee_total = $this->payment_hash->fee_total; $fee_total = $this->payment_hash->fee_total;
/*Hydrate invoices*/ if(!$fee_total || $fee_total == 0)
$invoices = Invoice::query()->whereIn('id', $this->transformKeys(array_column($payment_invoices, 'invoice_id')))->withTrashed()->get(); return;
$invoices->each(function ($invoice) { $invoices = Invoice::query()
if (collect($invoice->line_items)->contains('type_id', '3')) { ->whereIn('id', $this->transformKeys(array_column($payment_invoices, 'invoice_id')))
$invoice->service()->toggleFeesPaid()->save(); ->whereJsonContains('line_items', ['type_id' => '3'])
->withTrashed();
if($invoices->count() == 0){
$invoice = Invoice::query()
->whereIn('id', $this->transformKeys(array_column($payment_invoices, 'invoice_id')))
->orderBy('id','desc')
->withTrashed()
->first();
if(!$invoice)
return;
$balance = $invoice->balance;
App::forgetInstance('translator');
$t = app('translator');
$t->replace(Ninja::transformTranslations($invoice->company->settings));
App::setLocale($invoice->client->locale());
$invoice_item = new InvoiceItem();
$invoice_item->type_id = '4';
$invoice_item->product_key = ctrans('texts.surcharge');
$invoice_item->notes = ctrans('texts.online_payment_surcharge');
$invoice_item->quantity = 1;
$invoice_item->cost = (float)$fee_total;
$invoice_items = (array) $invoice->line_items;
$invoice_items[] = $invoice_item;
$invoice->line_items = $invoice_items;
/**Refresh Invoice values*/
$invoice = $invoice->calc()->getInvoice();
$new_balance = $invoice->balance;
if (floatval($new_balance) - floatval($balance) != 0) {
$adjustment = $new_balance - $balance;
$invoice
->ledger()
->updateInvoiceBalance($adjustment, 'Adjustment for adding gateway fee');
$invoice->client->service()->calculateBalance();
} }
});
}
else {
$invoices
->cursor()
->each(function ($i){
$i->service()->toggleFeesPaid()->save();
});
}
} }
/** /**

View File

@ -43,17 +43,19 @@ trait ChartQueries
return DB::select(" return DB::select("
SELECT SELECT
sum(expenses.amount / IFNULL(CAST(JSON_UNQUOTE(JSON_EXTRACT(clients.settings, '$.currency_id')) AS SIGNED), :company_currency2)) as amount, SUM(
IFNULL(expenses.currency_id, :company_currency) as currency_id CASE
WHEN expenses.currency_id = :company_currency THEN amount
ELSE expenses.amount * expenses.exchange_rate
END
) AS amount
FROM expenses FROM expenses
JOIN clients
ON expenses.client_id=clients.id
WHERE expenses.is_deleted = 0 WHERE expenses.is_deleted = 0
AND expenses.company_id = :company_id AND expenses.company_id = :company_id
AND (expenses.date BETWEEN :start_date AND :end_date) AND (expenses.date BETWEEN :start_date AND :end_date)
{$user_filter} {$user_filter}
GROUP BY currency_id GROUP BY expenses.company_id
", ['company_currency2' => $this->company->settings->currency_id, 'company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); ", ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]);
} }
public function getAggregateExpenseChartQuery($start_date, $end_date) public function getAggregateExpenseChartQuery($start_date, $end_date)
@ -63,11 +65,14 @@ trait ChartQueries
return DB::select(" return DB::select("
SELECT SELECT
sum(expenses.amount / IFNULL(CAST(JSON_UNQUOTE(JSON_EXTRACT(clients.settings, '$.currency_id')) AS SIGNED), :company_currency)) as total, SUM(
CASE
WHEN expenses.currency_id = :company_currency THEN amount
ELSE expenses.amount * expenses.exchange_rate
END
) AS amount,
expenses.date expenses.date
FROM expenses FROM expenses
JOIN clients
ON expenses.client_id=clients.id
WHERE (expenses.date BETWEEN :start_date AND :end_date) WHERE (expenses.date BETWEEN :start_date AND :end_date)
AND expenses.company_id = :company_id AND expenses.company_id = :company_id
AND expenses.is_deleted = 0 AND expenses.is_deleted = 0
@ -268,15 +273,17 @@ trait ChartQueries
return DB::select(" return DB::select("
SELECT SELECT
sum((payments.amount - payments.refunded) * payments.exchange_rate) as paid_to_date, sum((payments.amount - payments.refunded) / payments.exchange_rate) as paid_to_date
payments.currency_id AS currency_id
FROM payments FROM payments
JOIN clients
ON payments.client_id=clients.id
WHERE payments.company_id = :company_id WHERE payments.company_id = :company_id
AND payments.is_deleted = 0 AND payments.is_deleted = 0
AND clients.is_deleted = 0
{$user_filter} {$user_filter}
AND payments.status_id IN (1,4,5,6) AND payments.status_id IN (1,4,5,6)
AND (payments.date BETWEEN :start_date AND :end_date) AND (payments.date BETWEEN :start_date AND :end_date)
GROUP BY payments.currency_id GROUP BY payments.company_id
", ['company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]); ", ['company_id' => $this->company->id, 'start_date' => $start_date, 'end_date' => $end_date]);
} }
@ -290,8 +297,11 @@ trait ChartQueries
sum(payments.amount - payments.refunded) as paid_to_date, sum(payments.amount - payments.refunded) as paid_to_date,
payments.currency_id AS currency_id payments.currency_id AS currency_id
FROM payments FROM payments
JOIN clients
ON payments.client_id=clients.id
WHERE payments.company_id = :company_id WHERE payments.company_id = :company_id
AND payments.is_deleted = 0 AND payments.is_deleted = 0
AND clients.is_deleted = 0
{$user_filter} {$user_filter}
AND payments.status_id IN (1,4,5,6) AND payments.status_id IN (1,4,5,6)
AND (payments.date BETWEEN :start_date AND :end_date) AND (payments.date BETWEEN :start_date AND :end_date)

View File

@ -134,10 +134,10 @@ class ChartService
$aggregate_expenses = $this->getAggregateExpenseQuery($start_date, $end_date); $aggregate_expenses = $this->getAggregateExpenseQuery($start_date, $end_date);
$aggregate_invoices = $this->getAggregateInvoicesQuery($start_date, $end_date); $aggregate_invoices = $this->getAggregateInvoicesQuery($start_date, $end_date);
$data[999]['invoices'] = $aggregate_invoices !== false ? $aggregate_invoices : new \stdClass(); $data[999]['invoices'] = $aggregate_invoices !== false ? reset($aggregate_invoices) : new \stdClass();
$data[999]['expense'] = $aggregate_expenses !== false ? $aggregate_expenses : new \stdClass(); $data[999]['expense'] = $aggregate_expenses !== false ? reset($aggregate_expenses) : new \stdClass();
$data[999]['outstanding'] = $aggregate_outstanding !== false ? $aggregate_outstanding : new \stdClass(); $data[999]['outstanding'] = $aggregate_outstanding !== false ? reset($aggregate_outstanding) : new \stdClass();
$data[999]['revenue'] = $aggregate_revenue !== false ? $aggregate_revenue : new \stdClass(); $data[999]['revenue'] = $aggregate_revenue !== false ? reset($aggregate_revenue) : new \stdClass();
return $data; return $data;

View File

@ -383,7 +383,6 @@ class InvoiceService
return $item; return $item;
})->toArray(); })->toArray();
// $this->deletePdf();
$this->deleteEInvoice(); $this->deleteEInvoice();
return $this; return $this;

View File

@ -169,6 +169,9 @@ class HtmlEngine
$data['$invoice.po_number'] = ['value' => $this->entity->po_number ?: ' ', 'label' => ctrans('texts.po_number')]; $data['$invoice.po_number'] = ['value' => $this->entity->po_number ?: ' ', 'label' => ctrans('texts.po_number')];
$data['$poNumber'] = &$data['$invoice.po_number']; $data['$poNumber'] = &$data['$invoice.po_number'];
$data['$po_number'] = &$data['$invoice.po_number']; $data['$po_number'] = &$data['$invoice.po_number'];
$data['$project.name'] = ['value' => $this->entity->project?->name ?: '', 'label' => ctrans('texts.project')];
$data['$entity.datetime'] = ['value' => $this->formatDatetime($this->entity->created_at, $this->client->date_format()), 'label' => ctrans('texts.date')]; $data['$entity.datetime'] = ['value' => $this->formatDatetime($this->entity->created_at, $this->client->date_format()), 'label' => ctrans('texts.date')];
$data['$invoice.datetime'] = &$data['$entity.datetime']; $data['$invoice.datetime'] = &$data['$entity.datetime'];
$data['$quote.datetime'] = &$data['$entity.datetime']; $data['$quote.datetime'] = &$data['$entity.datetime'];
@ -219,19 +222,14 @@ class HtmlEngine
$data['$credit.custom3'] = &$data['$invoice.custom3']; $data['$credit.custom3'] = &$data['$invoice.custom3'];
$data['$credit.custom4'] = &$data['$invoice.custom4']; $data['$credit.custom4'] = &$data['$invoice.custom4'];
if ($this->entity->project) { $data['$invoice.project'] = &$data['$project.name'];
$data['$project.name'] = ['value' => $this->entity->project->name, 'label' => ctrans('texts.project')]; $data['$quote.project'] = &$data['$project.name'];
$data['$invoice.project'] = &$data['$project.name'];
$data['$quote.project'] = &$data['$project.name'];
}
$data['$status_logo'] = ['value' => '<div class="stamp is-paid"> ' . ctrans('texts.paid') .'</div>', 'label' => '']; $data['$status_logo'] = ['value' => '<div class="stamp is-paid"> ' . ctrans('texts.paid') .'</div>', 'label' => ''];
$data['$show_paid_stamp'] = ['value' => $this->entity->status_id == 4 && $this->settings->show_paid_stamp ? 'flex' : 'none', 'label' => '']; $data['$show_paid_stamp'] = ['value' => $this->entity->status_id == 4 && $this->settings->show_paid_stamp ? 'flex' : 'none', 'label' => ''];
if ($this->entity->vendor) { $data['$invoice.vendor'] = ['value' => $this->entity->vendor?->present()->name() ?: '', 'label' => ctrans('texts.vendor_name')];
$data['$invoice.vendor'] = ['value' => $this->entity->vendor->present()->name(), 'label' => ctrans('texts.vendor_name')];
}
if (strlen($this->company->getSetting('qr_iban')) > 5) { if (strlen($this->company->getSetting('qr_iban')) > 5) {
try { try {
@ -276,16 +274,10 @@ class HtmlEngine
$data['$credit.custom3'] = &$data['$quote.custom3']; $data['$credit.custom3'] = &$data['$quote.custom3'];
$data['$credit.custom4'] = &$data['$quote.custom4']; $data['$credit.custom4'] = &$data['$quote.custom4'];
if ($this->entity->project) { $data['$invoice.project'] = &$data['$project.name'];
$data['$project.name'] = ['value' => $this->entity->project->name, 'label' => ctrans('texts.project')]; $data['$quote.project'] = &$data['$project.name'];
$data['$invoice.project'] = &$data['$project.name'];
$data['$quote.project'] = &$data['$project.name'];
} $data['$invoice.vendor'] = ['value' => $this->entity->vendor?->present()->name() ?: '', 'label' => ctrans('texts.vendor_name')];
if ($this->entity->vendor) {
$data['$invoice.vendor'] = ['value' => $this->entity->vendor->present()->name(), 'label' => ctrans('texts.vendor_name')];
}
} }
if ($this->entity_string == 'credit') { if ($this->entity_string == 'credit') {
@ -663,15 +655,14 @@ class HtmlEngine
if ($this->settings->signature_on_pdf) { if ($this->settings->signature_on_pdf) {
$data['$contact.signature'] = ['value' => $this->invitation->signature_base64, 'label' => ctrans('texts.signature')]; $data['$contact.signature'] = ['value' => $this->invitation->signature_base64, 'label' => ctrans('texts.signature')];
$data['$contact.signature_date'] = ['value' => $this->translateDate($this->invitation->signature_date, $this->client->date_format(), $this->client->locale()), 'label' => ctrans('texts.date')];
$data['$contact.signature_ip'] = ['value' => $this->invitation->signature_ip ?? '', 'label' => ctrans('texts.address')];
} else { } else {
$data['$contact.signature'] = ['value' => '', 'label' => '']; $data['$contact.signature'] = ['value' => '', 'label' => ''];
$data['$contact.signature_date'] = ['value' => '', 'label' => ctrans('texts.date')];
$data['$contact.signature_ip'] = ['value' => '', 'label' => ctrans('texts.address')];
} }
$data['$contact.signature_raw'] = ['value' => $this->invitation->signature_base64, 'label' => ctrans('texts.signature')];
$data['$contact.signature_date'] = ['value' => $this->translateDate($this->invitation->signature_date ?? '1970-01-01', $this->client->date_format(), $this->client->locale()), 'label' => ctrans('texts.date')];
$data['$contact.signature_ip'] = ['value' => $this->invitation->signature_ip ?? '', 'label' => ctrans('texts.address')];
$data['$thanks'] = ['value' => '', 'label' => ctrans('texts.thanks')]; $data['$thanks'] = ['value' => '', 'label' => ctrans('texts.thanks')];
$data['$from'] = ['value' => '', 'label' => ctrans('texts.from')]; $data['$from'] = ['value' => '', 'label' => ctrans('texts.from')];
$data['$to'] = ['value' => '', 'label' => ctrans('texts.to')]; $data['$to'] = ['value' => '', 'label' => ctrans('texts.to')];
@ -741,7 +732,7 @@ class HtmlEngine
$payment_list = '<br><br>'; $payment_list = '<br><br>';
foreach ($this->entity->net_payments as $payment) { foreach ($this->entity->net_payments as $payment) {
$payment_list .= ctrans('texts.payment_subject') . ": " . $this->formatDate($payment->date, $this->client->date_format()) . " :: " . Number::formatMoney($payment->amount, $this->client) ." :: ". GatewayType::getAlias($payment->gateway_type_id) . "<br>"; $payment_list .= ctrans('texts.payment_subject') . ": " . $this->formatDate($payment->date, $this->client->date_format()) . " :: " . Number::formatMoney($payment->amount, $this->client) ." :: ". $payment->translatedType() . "<br>";
} }
$data['$payments'] = ['value' => $payment_list, 'label' => ctrans('texts.payments')]; $data['$payments'] = ['value' => $payment_list, 'label' => ctrans('texts.payments')];
@ -921,7 +912,7 @@ class HtmlEngine
private function getCountryName(): string private function getCountryName(): string
{ {
/** @var \Illuminate\Support\Collection<\App\Models\Country> */ /** @var \Illuminate\Support\Collection<\App\Models\Country> */
$countries = app('countries'); $countries = app('countries');
@ -1173,7 +1164,7 @@ class HtmlEngine
<table align="center" cellspacing="0" cellpadding="0" style="width: 600px;"> <table align="center" cellspacing="0" cellpadding="0" style="width: 600px;">
<tr> <tr>
<td align="center" valign="top"> <td align="center" valign="top">
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" > <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" >
<tbody><tr> <tbody><tr>
<td align="center" class="new_button" style="border-radius: 2px; background-color: '.$this->settings->primary_color.'"> <td align="center" class="new_button" style="border-radius: 2px; background-color: '.$this->settings->primary_color.'">
@ -1196,7 +1187,7 @@ class HtmlEngine
// return ' // return '
// <table border="0" cellspacing="0" cellpadding="0" align="center"> // <table border="0" cellspacing="0" cellpadding="0" align="center">
// <tr style="border: 0 !important; "> // <tr style="border: 0 !important; ">
// <td class="new_button" style="padding: 12px 18px 12px 18px; border-radius:5px;" align="center"> // <td class="new_button" style="padding: 12px 18px 12px 18px; border-radius:5px;" align="center">
// <a href="'. $link .'" target="_blank" style="border: 0 !important;font-size: 18px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; display: inline-block;">'. $text .'</a> // <a href="'. $link .'" target="_blank" style="border: 0 !important;font-size: 18px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; display: inline-block;">'. $text .'</a>
// </td> // </td>
// </tr> // </tr>

View File

@ -78,7 +78,7 @@ trait MakesDates
*/ */
public function formatDatetime($date, string $format): string public function formatDatetime($date, string $format): string
{ {
return Carbon::createFromTimestamp((int)$date)->format($format.' g:i a'); return Carbon::createFromTimestamp((int) ($date ?? 0))->format($format.' g:i a');
} }
/** /**

View File

@ -17,8 +17,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true), 'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => env('APP_VERSION', '5.10.2'), 'app_version' => env('APP_VERSION', '5.10.3'),
'app_tag' => env('APP_TAG', '5.10.2'), 'app_tag' => env('APP_TAG', '5.10.3'),
'minimum_client_version' => '5.0.16', 'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1', 'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false), 'api_secret' => env('API_SECRET', false),

View File

@ -11,11 +11,13 @@ return new class extends Migration
*/ */
public function up(): void public function up(): void
{ {
Schema::table('users', function (Blueprint $table) { if(!in_array('referral_meta', \Illuminate\Support\Facades\Schema::getColumnListing('users')))
$table->mediumText('referral_meta')->nullable(); {
}); Schema::table('users', function (Blueprint $table) {
$table->mediumText('referral_meta')->nullable();
});
}
} }
/** /**

View File

@ -0,0 +1 @@

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,12 @@
{
"Resources/assets/css/app.css": {
"file": "assets/app-5896c2d6.css",
"isEntry": true,
"src": "Resources/assets/css/app.css"
},
"Resources/assets/js/app.js": {
"file": "assets/app-4ed993c7.js",
"isEntry": true,
"src": "Resources/assets/js/app.js"
}
}

View File

@ -29,7 +29,7 @@
<div class="grid grid-cols-12 gap-4 mt-10"> <div class="grid grid-cols-12 gap-4 mt-10">
@if($register_company->client_registration_fields) @if($register_company->client_registration_fields)
@foreach($register_company->client_registration_fields as $field) @foreach($register_company->client_registration_fields as $field)
@if($field['visible']) @if(isset($field['visible']) && $field['visible'])
<div class="col-span-12 md:col-span-6"> <div class="col-span-12 md:col-span-6">
<section class="flex items-center"> <section class="flex items-center">
<label <label

View File

@ -11,13 +11,17 @@
namespace Tests\Unit\Chart; namespace Tests\Unit\Chart;
use App\DataMapper\ClientSettings; use Tests\TestCase;
use App\Models\Client; use App\Models\Client;
use App\Models\Company;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Currency;
use Tests\MockAccountData;
use App\DataMapper\ClientSettings;
use App\DataMapper\CompanySettings;
use App\Models\Expense;
use App\Services\Chart\ChartService; use App\Services\Chart\ChartService;
use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\MockAccountData;
use Tests\TestCase;
/** /**
* @test * @test
@ -35,12 +39,326 @@ class ChartCurrencyTest extends TestCase
$this->makeTestData(); $this->makeTestData();
} }
public function testAggregateRevenues()
{
$settings = CompanySettings::defaults();
$settings->company_logo = 'https://pdf.invoicing.co/favicon-v2.png';
$settings->website = 'www.invoiceninja.com';
$settings->address1 = 'Address 1';
$settings->address2 = 'Address 2';
$settings->city = 'City';
$settings->state = 'State';
$settings->postal_code = 'Postal Code';
$settings->phone = '555-343-2323';
$settings->email = '';
$settings->country_id = '840';
$settings->vat_number = 'vat number';
$settings->id_number = 'id number';
$settings->use_credits_payment = 'always';
$settings->timezone_id = '1';
$settings->entity_send_time = 0;
$company = Company::factory()->create([
'account_id' => $this->account->id,
'settings' => $settings,
]);
$settings = ClientSettings::defaults();
$settings->currency_id = '1'; //USD
$usd = Client::factory()->create([
'user_id' => $this->user->id,
'company_id' => $company->id,
'settings' => $settings,
]);
Currency::query()->where('id', 1)->update(['exchange_rate' => 1]);
Currency::query()->where('id', 2)->update(['exchange_rate' => 0.5]);
$settings = ClientSettings::defaults();
$settings->currency_id = '2'; //GBP
$gbp = Client::factory()->create([
'user_id' => $this->user->id,
'company_id' => $company->id,
'settings' => $settings,
]);
$i1 = Invoice::factory()->create([
'client_id' => $usd->id,
'user_id' => $this->user->id,
'company_id' => $company->id,
'amount' => 100,
'balance' => 100,
'paid_to_date' => 0,
'status_id' => 2,
'date' => now(),
'due_date' => now()
]);
$i2 = Invoice::factory()->create([
'client_id' => $gbp->id,
'user_id' => $this->user->id,
'company_id' => $company->id,
'amount' => 100,
'balance' => 100,
'paid_to_date' => 0,
'status_id' => 2,
'date' => now(),
'due_date' => now()
]);
$i1->service()->markPaid()->save();
$i2->service()->markPaid()->save();
$cs = new ChartService($company, $this->user, true);
$results = $cs->totals('1970-01-01', '2050-01-01');
$this->assertCount(2, $results['currencies']);
// nlog($results);
$this->assertEquals('USD', $results['currencies'][1]);
$this->assertEquals('GBP', $results['currencies'][2]);
$this->assertEquals(100, $results[1]['invoices']->invoiced_amount);
$this->assertEquals(100, $results[2]['invoices']->invoiced_amount);
$this->assertEquals(150, $results[999]['invoices']->invoiced_amount);
$this->assertEquals(150, $results[999]['revenue']->paid_to_date);
$usd->forceDelete();
$gbp->forceDelete();
}
public function testAggregateOutstanding()
{
$settings = CompanySettings::defaults();
$settings->company_logo = 'https://pdf.invoicing.co/favicon-v2.png';
$settings->website = 'www.invoiceninja.com';
$settings->address1 = 'Address 1';
$settings->address2 = 'Address 2';
$settings->city = 'City';
$settings->state = 'State';
$settings->postal_code = 'Postal Code';
$settings->phone = '555-343-2323';
$settings->email = '';
$settings->country_id = '840';
$settings->vat_number = 'vat number';
$settings->id_number = 'id number';
$settings->use_credits_payment = 'always';
$settings->timezone_id = '1';
$settings->entity_send_time = 0;
$company = Company::factory()->create([
'account_id' => $this->account->id,
'settings' => $settings,
]);
$settings = ClientSettings::defaults();
$settings->currency_id = '1'; //USD
$usd = Client::factory()->create([
'user_id' => $this->user->id,
'company_id' => $company->id,
'settings' => $settings,
]);
Currency::query()->where('id', 1)->update(['exchange_rate' => 1]);
Currency::query()->where('id', 2)->update(['exchange_rate' => 0.5]);
$settings = ClientSettings::defaults();
$settings->currency_id = '2'; //GBP
$gbp = Client::factory()->create([
'user_id' => $this->user->id,
'company_id' => $company->id,
'settings' => $settings,
]);
$i1 = Invoice::factory()->create([
'client_id' => $usd->id,
'user_id' => $this->user->id,
'company_id' => $company->id,
'amount' => 100,
'balance' => 100,
'paid_to_date' => 0,
'status_id' => 2,
'date' => now(),
'due_date' => now()
]);
$i1_overdue = Invoice::factory()->create([
'client_id' => $usd->id,
'user_id' => $this->user->id,
'company_id' => $company->id,
'amount' => 100,
'balance' => 100,
'paid_to_date' => 0,
'status_id' => 2,
'date' => now(),
'due_date' => now()->subDays(10)
]);
$i2 = Invoice::factory()->create([
'client_id' => $gbp->id,
'user_id' => $this->user->id,
'company_id' => $company->id,
'amount' => 100,
'balance' => 100,
'paid_to_date' => 0,
'status_id' => 2,
'date' => now(),
'due_date' => now()
]);
$i2_overdue = Invoice::factory()->create([
'client_id' => $gbp->id,
'user_id' => $this->user->id,
'company_id' => $company->id,
'amount' => 100,
'balance' => 100,
'paid_to_date' => 0,
'status_id' => 2,
'date' => now(),
'due_date' => now()->subDays(10)
]);
$i1->service()->markPaid()->save();
$i2->service()->markPaid()->save();
$cs = new ChartService($company, $this->user, true);
$results = $cs->totals('1970-01-01', '2050-01-01');
$this->assertCount(2, $results['currencies']);
nlog($results);
$this->assertEquals('USD', $results['currencies'][1]);
$this->assertEquals('GBP', $results['currencies'][2]);
$this->assertEquals(200, $results[1]['invoices']->invoiced_amount);
$this->assertEquals(200, $results[2]['invoices']->invoiced_amount);
$this->assertEquals(300, $results[999]['invoices']->invoiced_amount);
$this->assertEquals(150, $results[999]['revenue']->paid_to_date);
$this->assertEquals(150, $results[999]['outstanding']->amount);
$this->assertEquals(2, $results[999]['outstanding']->outstanding_count);
$usd->forceDelete();
$gbp->forceDelete();
}
public function testAggregateExpenses()
{
$settings = CompanySettings::defaults();
$settings->company_logo = 'https://pdf.invoicing.co/favicon-v2.png';
$settings->website = 'www.invoiceninja.com';
$settings->address1 = 'Address 1';
$settings->address2 = 'Address 2';
$settings->city = 'City';
$settings->state = 'State';
$settings->postal_code = 'Postal Code';
$settings->phone = '555-343-2323';
$settings->email = '';
$settings->country_id = '840';
$settings->vat_number = 'vat number';
$settings->id_number = 'id number';
$settings->use_credits_payment = 'always';
$settings->timezone_id = '1';
$settings->entity_send_time = 0;
$company = Company::factory()->create([
'account_id' => $this->account->id,
'settings' => $settings,
]);
$settings = ClientSettings::defaults();
$settings->currency_id = '1'; //USD
$usd = Client::factory()->create([
'user_id' => $this->user->id,
'company_id' => $company->id,
'settings' => $settings,
]);
Currency::query()->where('id', 1)->update(['exchange_rate' => 1]);
Currency::query()->where('id', 2)->update(['exchange_rate' => 0.5]);
$settings = ClientSettings::defaults();
$settings->currency_id = '2'; //GBP
$gbp = Client::factory()->create([
'user_id' => $this->user->id,
'company_id' => $company->id,
'settings' => $settings,
]);
$usd_e = Expense::factory()->create([
'company_id' => $company->id,
'user_id' => $this->user->id,
'client_id' => $usd->id,
'amount' => 100,
]);
$gbp_e = Expense::factory()->create([
'company_id' => $company->id,
'user_id' => $this->user->id,
'client_id' => $usd->id,
'amount' => 100,
]);
$cs = new ChartService($company, $this->user, true);
$results = $cs->totals('1970-01-01', '2050-01-01');
$this->assertCount(2, $results['currencies']);
nlog($results);
// $this->assertEquals('USD', $results['currencies'][1]);
// $this->assertEquals('GBP', $results['currencies'][2]);
// $this->assertEquals(200, $results[1]['invoices']->invoiced_amount);
// $this->assertEquals(200, $results[2]['invoices']->invoiced_amount);
// $this->assertEquals(300, $results[999]['invoices']->invoiced_amount);
// $this->assertEquals(150, $results[999]['revenue']->paid_to_date);
// $this->assertEquals(150, $results[999]['outstanding']->amount);
// $this->assertEquals(2, $results[999]['outstanding']->outstanding_count);
$usd->forceDelete();
$gbp->forceDelete();
}
public function testRevenueValues() public function testRevenueValues()
{ {
Invoice::factory()->create([ Invoice::factory()->create([
'client_id' => $this->client->id, 'client_id' => $this->client->id,
'user_id' => $this->user->id, 'user_id' => $this->user->id,
'company_id' => $this->company->id, 'company_id' => $this->company->id,
'amount' => 100,
'balance' => 0,
'paid_to_date' => 100, 'paid_to_date' => 100,
'status_id' => 4, 'status_id' => 4,
'date' => now(), 'date' => now(),