From e0373006d8fc9e868b57ca497c1703846193a03e Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 13 May 2022 16:42:04 +1000 Subject: [PATCH] PnL Expense tests --- app/Factory/ExpenseFactory.php | 3 + app/Models/Company.php | 13 ++ app/Services/PdfMaker/Design.php | 2 +- app/Services/Report/ProfitLoss.php | 64 +++++++- .../Export/ProfitAndLossReportTest.php | 151 +++++++++++++++++- 5 files changed, 226 insertions(+), 7 deletions(-) diff --git a/app/Factory/ExpenseFactory.php b/app/Factory/ExpenseFactory.php index e41b282415c8..997412ef1b5f 100644 --- a/app/Factory/ExpenseFactory.php +++ b/app/Factory/ExpenseFactory.php @@ -39,6 +39,9 @@ class ExpenseFactory $expense->custom_value2 = ''; $expense->custom_value3 = ''; $expense->custom_value4 = ''; + $expense->tax_amount1 = 0; + $expense->tax_amount2 = 0; + $expense->tax_amount3 = 0; return $expense; } diff --git a/app/Models/Company.php b/app/Models/Company.php index 9b2a11cd5be4..7ff29a5b3c9a 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -551,4 +551,17 @@ class Company extends BaseModel { return ctrans('texts.company'); } + + public function date_format() + { + $date_formats = Cache::get('date_formats'); + + if(!$date_formats) + $this->buildCache(true); + + return $date_formats->filter(function ($item) { + return $item->id == $this->getSetting('date_format_id'); + })->first()->format; + } + } diff --git a/app/Services/PdfMaker/Design.php b/app/Services/PdfMaker/Design.php index 12f8587a0b47..8522ba9133de 100644 --- a/app/Services/PdfMaker/Design.php +++ b/app/Services/PdfMaker/Design.php @@ -226,7 +226,7 @@ class Design extends BaseDesign { if ($this->type === 'statement') { - $s_date = $this->translateDate(now()->format('Y-m-d'), $this->client->date_format(), $this->client->locale()); + $s_date = $this->translateDate(now()->format($client->company->date_format()), $this->client->date_format(), $this->client->locale()); return [ ['element' => 'tr', 'properties' => ['data-ref' => 'statement-label'], 'elements' => [ diff --git a/app/Services/Report/ProfitLoss.php b/app/Services/Report/ProfitLoss.php index 4da0e7794977..0fe847df6821 100644 --- a/app/Services/Report/ProfitLoss.php +++ b/app/Services/Report/ProfitLoss.php @@ -16,7 +16,11 @@ use App\Libraries\MultiDB; use App\Models\Company; use App\Models\Expense; use App\Models\Payment; +use App\Utils\Ninja; +use App\Utils\Number; use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\App; +use League\Csv\Writer; class ProfitLoss { @@ -126,7 +130,9 @@ class ProfitLoss } public function getExpenseBreakDown() :array - { + { + ksort($this->expense_break_down); + return $this->expense_break_down; } @@ -325,6 +331,54 @@ class ProfitLoss ] */ + public function getCsv() + { + + MultiDB::setDb($this->company->db); + App::forgetInstance('translator'); + App::setLocale($this->company->locale()); + $t = app('translator'); + $t->replace(Ninja::transformTranslations($this->company->settings)); + + $csv = Writer::createFromString(); + + $csv->insertOne([ctrans('texts.profit_and_loss')]); + $csv->insertOne([ctrans('texts.company_name'), $this->company->present()->name()]); + $csv->insertOne([ctrans('texts.date_range'), Carbon::parse($this->start_date)->format($this->company->date_format()), Carbon::parse($this->end_date)->format($this->company->date_format())]); + + //gross sales ex tax + + $csv->insertOne(['--------------------']); + + $csv->insertOne([ctrans('texts.total_revenue'), Number::formatMoney($this->income, $this->company)]); + + //total taxes + + $csv->insertOne([ctrans('texts.total_taxes'), Number::formatMoney($this->income_taxes, $this->company)]); + + //expense + + $csv->insertOne(['--------------------']); + foreach($this->expense_break_down as $expense_breakdown) + { + $csv->insertOne([$expense_breakdown['category_name'], Number::formatMoney($expense_breakdown['total'], $this->company)]); + } + //total expense taxes + + $csv->insertOne(['--------------------']); + $csv->insertOne([ctrans('texts.total_expenses'), Number::formatMoney(array_sum(array_column($this->expense_break_down, 'total')), $this->company)]); + + $csv->insertOne([ctrans('texts.total_taxes'), Number::formatMoney(array_sum(array_column($this->expense_break_down, 'tax')), $this->company)]); + + + $csv->insertOne(['--------------------']); + $csv->insertOne([ctrans('texts.total_profit'), Number::formatMoney($this->income - array_sum(array_column($this->expense_break_down, 'total')), $this->company)]); + + //net profit + + return $csv->toString(); + + } private function invoicePaymentIncome() { @@ -392,6 +446,8 @@ class ProfitLoss { $map = new \stdClass; + $amount = $expense->amount; + $map->total = $expense->amount; $map->converted_total = $converted_total = $this->getConvertedTotal($expense->amount, $expense->exchange_rate); $map->tax = $tax = $this->getTax($expense); @@ -438,11 +494,14 @@ class ProfitLoss private function getTax($expense) { $amount = $expense->amount; - //is amount tax if($expense->calculate_tax_by_amount) { + nlog($expense->tax_amount1); + nlog($expense->tax_amount2); + nlog($expense->tax_amount3); + return $expense->tax_amount1 + $expense->tax_amount2 + $expense->tax_amount3; } @@ -459,7 +518,6 @@ class ProfitLoss } - $exclusive = 0; $exclusive += $amount * ($expense->tax_rate1 / 100); diff --git a/tests/Feature/Export/ProfitAndLossReportTest.php b/tests/Feature/Export/ProfitAndLossReportTest.php index b60de2283036..c7b9636cb910 100644 --- a/tests/Feature/Export/ProfitAndLossReportTest.php +++ b/tests/Feature/Export/ProfitAndLossReportTest.php @@ -13,6 +13,7 @@ namespace Tests\Feature\Export; use App\DataMapper\ClientSettings; use App\DataMapper\CompanySettings; use App\Factory\ExpenseCategoryFactory; +use App\Factory\ExpenseFactory; use App\Factory\InvoiceFactory; use App\Models\Account; use App\Models\Client; @@ -336,9 +337,86 @@ class ProfitAndLossReportTest extends TestCase $this->account->delete(); + } + + public function testSimpleExpenseAmountTax() + { + $this->buildData(); + + $e = ExpenseFactory::create($this->company->id, $this->user->id); + $e->amount = 10; + $e->date = '2022-01-01'; + $e->calculate_tax_by_amount = true; + $e->tax_amount1 = 10; + $e->save(); + + $pl = new ProfitLoss($this->company, $this->payload); + $pl->build(); + + $expenses = $pl->getExpenses(); + + $expense = $expenses[0]; + + $this->assertEquals(10, $expense->total); + $this->assertEquals(10, $expense->tax); + + $this->account->delete(); } + public function testSimpleExpenseTaxRateExclusive() + { + $this->buildData(); + + $e = ExpenseFactory::create($this->company->id, $this->user->id); + $e->amount = 10; + $e->date = '2022-01-01'; + $e->tax_rate1 = 10; + $e->tax_name1 = 'GST'; + $e->uses_inclusive_taxes = false; + $e->save(); + + $pl = new ProfitLoss($this->company, $this->payload); + $pl->build(); + + $expenses = $pl->getExpenses(); + + $expense = $expenses[0]; + + $this->assertEquals(10, $expense->total); + $this->assertEquals(1, $expense->tax); + + $this->account->delete(); + + } + + public function testSimpleExpenseTaxRateInclusive() + { + $this->buildData(); + + $e = ExpenseFactory::create($this->company->id, $this->user->id); + $e->amount = 10; + $e->date = '2022-01-01'; + $e->tax_rate1 = 10; + $e->tax_name1 = 'GST'; + $e->uses_inclusive_taxes = false; + $e->save(); + + $pl = new ProfitLoss($this->company, $this->payload); + $pl->build(); + + $expenses = $pl->getExpenses(); + + $expense = $expenses[0]; + + $this->assertEquals(10, $expense->total); + $this->assertEquals(1, $expense->tax); + + $this->account->delete(); + + } + + public function testSimpleExpenseBreakdown() { $this->buildData(); @@ -407,13 +485,80 @@ class ProfitAndLossReportTest extends TestCase $bd = $pl->getExpenseBreakDown(); - -nlog($bd); - $this->assertEquals(array_sum(array_column($bd,'total')), 30); $this->account->delete(); } + + public function testCsvGeneration() + { + $this->buildData(); + + $client = Client::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'is_deleted' => 0, + ]); + + Invoice::factory()->count(1)->create([ + 'client_id' => $client->id, + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'amount' => 10, + 'balance' => 10, + 'status_id' => 2, + 'total_taxes' => 1, + 'date' => '2022-01-01', + 'terms' => 'nada', + 'discount' => 0, + 'tax_rate1' => 10, + 'tax_rate2' => 0, + 'tax_rate3' => 0, + 'tax_name1' => "GST", + 'tax_name2' => '', + 'tax_name3' => '', + 'uses_inclusive_taxes' => true, + ]); + + $ec = ExpenseCategoryFactory::create($this->company->id, $this->user->id); + $ec->name = 'Accounting'; + $ec->save(); + + $e = Expense::factory()->create([ + 'category_id' => $ec->id, + 'amount' => 10, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'date' => '2022-01-01', + 'exchange_rate' => 1, + 'currency_id' => $this->company->settings->currency_id + ]); + + + $ec = ExpenseCategoryFactory::create($this->company->id, $this->user->id); + $ec->name = 'Fuel'; + $ec->save(); + + $e = Expense::factory(2)->create([ + 'category_id' => $ec->id, + 'amount' => 10, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'date' => '2022-01-01', + 'exchange_rate' => 1, + 'currency_id' => $this->company->settings->currency_id + ]); + + + $pl = new ProfitLoss($this->company, $this->payload); + $pl->build(); + + $this->assertNotNull($pl->getCsv()); + + $this->account->delete(); + + } + }