mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
Working on aggregate charts
This commit is contained in:
parent
702d8992e5
commit
96766d33b8
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -660,7 +660,7 @@ class HtmlEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
$data['$contact.signature_raw'] = ['value' => $this->invitation->signature_base64, 'label' => ctrans('texts.signature')];
|
$data['$contact.signature_raw'] = ['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_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['$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')];
|
||||||
|
@ -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');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +19,7 @@ use App\Models\Currency;
|
|||||||
use Tests\MockAccountData;
|
use Tests\MockAccountData;
|
||||||
use App\DataMapper\ClientSettings;
|
use App\DataMapper\ClientSettings;
|
||||||
use App\DataMapper\CompanySettings;
|
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;
|
||||||
|
|
||||||
@ -86,30 +87,156 @@ class ChartCurrencyTest extends TestCase
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
Invoice::factory()->create([
|
$i1 = Invoice::factory()->create([
|
||||||
'client_id' => $usd->id,
|
'client_id' => $usd->id,
|
||||||
'user_id' => $this->user->id,
|
'user_id' => $this->user->id,
|
||||||
'company_id' => $company->id,
|
'company_id' => $company->id,
|
||||||
'amount' => 100,
|
'amount' => 100,
|
||||||
'balance' => 0,
|
'balance' => 100,
|
||||||
'paid_to_date' => 100,
|
'paid_to_date' => 0,
|
||||||
'status_id' => 4,
|
'status_id' => 2,
|
||||||
'date' => now(),
|
'date' => now(),
|
||||||
'due_date' => now()
|
'due_date' => now()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Invoice::factory()->create([
|
$i2 = Invoice::factory()->create([
|
||||||
'client_id' => $gbp->id,
|
'client_id' => $gbp->id,
|
||||||
'user_id' => $this->user->id,
|
'user_id' => $this->user->id,
|
||||||
'company_id' => $company->id,
|
'company_id' => $company->id,
|
||||||
'amount' => 100,
|
'amount' => 100,
|
||||||
'balance' => 0,
|
'balance' => 100,
|
||||||
'paid_to_date' => 100,
|
'paid_to_date' => 0,
|
||||||
'status_id' => 4,
|
'status_id' => 2,
|
||||||
'date' => now(),
|
'date' => now(),
|
||||||
'due_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);
|
$cs = new ChartService($company, $this->user, true);
|
||||||
$results = $cs->totals('1970-01-01', '2050-01-01');
|
$results = $cs->totals('1970-01-01', '2050-01-01');
|
||||||
@ -121,13 +248,109 @@ class ChartCurrencyTest extends TestCase
|
|||||||
$this->assertEquals('USD', $results['currencies'][1]);
|
$this->assertEquals('USD', $results['currencies'][1]);
|
||||||
$this->assertEquals('GBP', $results['currencies'][2]);
|
$this->assertEquals('GBP', $results['currencies'][2]);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $results[1]['invoices']->invoiced_amount);
|
||||||
|
$this->assertEquals(200, $results[2]['invoices']->invoiced_amount);
|
||||||
|
|
||||||
nlog(array_sum(array_column($results['currencies'][1]['invoices'],'invoiced_amount')));
|
$this->assertEquals(300, $results[999]['invoices']->invoiced_amount);
|
||||||
|
$this->assertEquals(150, $results[999]['revenue']->paid_to_date);
|
||||||
|
|
||||||
$this->assertEquals(100, array_sum(array_column($results['currencies'][1]['invoices'],'invoiced_amount')));
|
$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([
|
||||||
|
Loading…
x
Reference in New Issue
Block a user