You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IncomeStatementReportTransformer.php 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. namespace App\Transformers;
  3. use App\DTO\AccountDTO;
  4. use App\DTO\ReportCategoryDTO;
  5. use App\DTO\ReportDTO;
  6. use App\Utilities\Currency\CurrencyAccessor;
  7. class IncomeStatementReportTransformer extends SummaryReportTransformer
  8. {
  9. protected string $totalRevenue;
  10. protected string $totalCogs;
  11. protected string $totalExpenses;
  12. public function __construct(ReportDTO $report)
  13. {
  14. parent::__construct($report);
  15. $this->calculateTotals();
  16. }
  17. public function getTitle(): string
  18. {
  19. return 'Income Statement';
  20. }
  21. public function calculateTotals(): void
  22. {
  23. foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
  24. match ($accountCategoryName) {
  25. 'Revenue' => $this->totalRevenue = $accountCategory->summary->netMovement ?? '',
  26. 'Cost of Goods Sold' => $this->totalCogs = $accountCategory->summary->netMovement ?? '',
  27. 'Expenses' => $this->totalExpenses = $accountCategory->summary->netMovement ?? '',
  28. };
  29. }
  30. }
  31. public function getCategories(): array
  32. {
  33. $categories = [];
  34. foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
  35. $header = [];
  36. foreach ($this->getColumns() as $column) {
  37. $header[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
  38. }
  39. $data = array_map(function (AccountDTO $account) {
  40. $row = [];
  41. foreach ($this->getColumns() as $column) {
  42. $row[$column->getName()] = match ($column->getName()) {
  43. 'account_code' => $account->accountCode,
  44. 'account_name' => [
  45. 'name' => $account->accountName,
  46. 'id' => $account->accountId ?? null,
  47. 'start_date' => $account->startDate,
  48. 'end_date' => $account->endDate,
  49. ],
  50. 'net_movement' => $account->balance->netMovement ?? '',
  51. default => '',
  52. };
  53. }
  54. return $row;
  55. }, $accountCategory->accounts);
  56. $summary = [];
  57. foreach ($this->getColumns() as $column) {
  58. $summary[$column->getName()] = match ($column->getName()) {
  59. 'account_name' => 'Total ' . $accountCategoryName,
  60. 'net_movement' => $accountCategory->summary->netMovement ?? '',
  61. default => '',
  62. };
  63. }
  64. $categories[] = new ReportCategoryDTO(
  65. header: $header,
  66. data: $data,
  67. summary: $summary,
  68. );
  69. }
  70. return $categories;
  71. }
  72. public function getSummaryCategories(): array
  73. {
  74. $summaryCategories = [];
  75. $columns = $this->getSummaryColumns();
  76. foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
  77. // Header for the main category
  78. $categoryHeader = [];
  79. foreach ($columns as $column) {
  80. $categoryHeader[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
  81. }
  82. // Category-level summary
  83. $categorySummary = [];
  84. foreach ($columns as $column) {
  85. $categorySummary[$column->getName()] = match ($column->getName()) {
  86. 'account_name' => $accountCategoryName,
  87. 'net_movement' => $accountCategory->summary->netMovement ?? '',
  88. default => '',
  89. };
  90. }
  91. // Add the category summary to the final array
  92. $summaryCategories[$accountCategoryName] = new ReportCategoryDTO(
  93. header: $categoryHeader,
  94. data: [], // No direct accounts are needed here, only summaries
  95. summary: $categorySummary,
  96. types: [] // No types for the income statement
  97. );
  98. }
  99. return $summaryCategories;
  100. }
  101. public function getGrossProfit(): array
  102. {
  103. $grossProfit = [];
  104. $columns = $this->getSummaryColumns();
  105. $revenue = money($this->totalRevenue, CurrencyAccessor::getDefaultCurrency())->getAmount();
  106. $cogs = money($this->totalCogs, CurrencyAccessor::getDefaultCurrency())->getAmount();
  107. $grossProfitAmount = $revenue - $cogs;
  108. $grossProfitFormatted = money($grossProfitAmount, CurrencyAccessor::getDefaultCurrency(), true)->format();
  109. foreach ($columns as $column) {
  110. $grossProfit[$column->getName()] = match ($column->getName()) {
  111. 'account_name' => 'Gross Profit',
  112. 'net_movement' => $grossProfitFormatted,
  113. default => '',
  114. };
  115. }
  116. return $grossProfit;
  117. }
  118. public function getOverallTotals(): array
  119. {
  120. $totals = [];
  121. foreach ($this->getColumns() as $column) {
  122. $totals[$column->getName()] = match ($column->getName()) {
  123. 'account_name' => 'Net Earnings',
  124. 'net_movement' => $this->report->overallTotal->netMovement ?? '',
  125. default => '',
  126. };
  127. }
  128. return $totals;
  129. }
  130. public function getSummaryOverallTotals(): array
  131. {
  132. $totals = [];
  133. $columns = $this->getSummaryColumns();
  134. foreach ($columns as $column) {
  135. $totals[$column->getName()] = match ($column->getName()) {
  136. 'account_name' => 'Net Earnings',
  137. 'net_movement' => $this->report->overallTotal->netMovement ?? '',
  138. default => '',
  139. };
  140. }
  141. return $totals;
  142. }
  143. public function getSummary(): array
  144. {
  145. return [
  146. [
  147. 'label' => 'Revenue',
  148. 'value' => $this->totalRevenue,
  149. ],
  150. [
  151. 'label' => 'Cost of Goods Sold',
  152. 'value' => $this->totalCogs,
  153. ],
  154. [
  155. 'label' => 'Expenses',
  156. 'value' => $this->totalExpenses,
  157. ],
  158. [
  159. 'label' => 'Net Earnings',
  160. 'value' => $this->report->overallTotal->netMovement ?? '',
  161. ],
  162. ];
  163. }
  164. }