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.

BalanceSheetReportTransformer.php 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <?php
  2. namespace App\Transformers;
  3. use App\DTO\AccountDTO;
  4. use App\DTO\ReportCategoryDTO;
  5. use App\DTO\ReportTypeDTO;
  6. use App\Support\Column;
  7. use App\Utilities\Currency\CurrencyAccessor;
  8. class BalanceSheetReportTransformer extends BaseReportTransformer
  9. {
  10. protected string $totalAssets = '$0.00';
  11. protected string $totalLiabilities = '$0.00';
  12. protected string $totalEquity = '$0.00';
  13. public function getTitle(): string
  14. {
  15. return 'Balance Sheet';
  16. }
  17. public function getHeaders(): array
  18. {
  19. return array_map(fn (Column $column) => $column->getLabel(), $this->getColumns());
  20. }
  21. public function calculateTotals(): void
  22. {
  23. foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
  24. match ($accountCategoryName) {
  25. 'Assets' => $this->totalAssets = $accountCategory->summary->endingBalance ?? '',
  26. 'Liabilities' => $this->totalLiabilities = $accountCategory->summary->endingBalance ?? '',
  27. 'Equity' => $this->totalEquity = $accountCategory->summary->endingBalance ?? '',
  28. };
  29. }
  30. }
  31. public function getCategories(): array
  32. {
  33. $categories = [];
  34. foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
  35. // Header for the main category
  36. $header = [];
  37. foreach ($this->getColumns() as $index => $column) {
  38. if ($column->getName() === 'account_name') {
  39. $header[$index] = $accountCategoryName;
  40. } else {
  41. $header[$index] = '';
  42. }
  43. }
  44. // Category-level summary
  45. $categorySummary = [];
  46. foreach ($this->getColumns() as $column) {
  47. $categorySummary[] = match ($column->getName()) {
  48. 'account_name' => 'Total ' . $accountCategoryName,
  49. 'ending_balance' => $accountCategory->summary->endingBalance ?? '',
  50. default => '',
  51. };
  52. }
  53. // Accounts directly under the main category
  54. $data = array_map(function (AccountDTO $account) {
  55. $row = [];
  56. foreach ($this->getColumns() as $column) {
  57. $row[] = match ($column->getName()) {
  58. 'account_code' => $account->accountCode,
  59. 'account_name' => [
  60. 'name' => $account->accountName,
  61. 'id' => $account->accountId ?? null,
  62. 'start_date' => $account->startDate,
  63. 'end_date' => $account->endDate,
  64. ],
  65. 'ending_balance' => $account->balance->endingBalance ?? '',
  66. default => '',
  67. };
  68. }
  69. return $row;
  70. }, $accountCategory->accounts ?? []);
  71. // Subcategories (types) under the main category
  72. $types = [];
  73. foreach ($accountCategory->types as $typeName => $type) {
  74. // Header for subcategory (type)
  75. $typeHeader = [];
  76. foreach ($this->getColumns() as $index => $column) {
  77. $typeHeader[$index] = $column->getName() === 'account_name' ? $typeName : '';
  78. }
  79. // Account data for the subcategory
  80. $typeData = array_map(function (AccountDTO $account) {
  81. $row = [];
  82. foreach ($this->getColumns() as $column) {
  83. $row[] = match ($column->getName()) {
  84. 'account_code' => $account->accountCode,
  85. 'account_name' => [
  86. 'name' => $account->accountName,
  87. 'id' => $account->accountId ?? null,
  88. 'start_date' => $account->startDate,
  89. 'end_date' => $account->endDate,
  90. ],
  91. 'ending_balance' => $account->balance->endingBalance ?? '',
  92. default => '',
  93. };
  94. }
  95. return $row;
  96. }, $type->accounts);
  97. // Subcategory (type) summary
  98. $typeSummary = [];
  99. foreach ($this->getColumns() as $column) {
  100. $typeSummary[] = match ($column->getName()) {
  101. 'account_name' => 'Total ' . $typeName,
  102. 'ending_balance' => $type->summary->endingBalance ?? '',
  103. default => '',
  104. };
  105. }
  106. // Add subcategory (type) to the list
  107. $types[$typeName] = new ReportTypeDTO(
  108. header: $typeHeader,
  109. data: $typeData,
  110. summary: $typeSummary,
  111. );
  112. }
  113. // Add the category to the final array with its direct accounts and subcategories (types)
  114. $categories[$accountCategoryName] = new ReportCategoryDTO(
  115. header: $header,
  116. data: $data, // Direct accounts under the category
  117. summary: $categorySummary,
  118. types: $types, // Subcategories (types) under the category
  119. );
  120. }
  121. return $categories;
  122. }
  123. public function getSummaryCategories(): array
  124. {
  125. $summaryCategories = [];
  126. $columns = [
  127. 'account_name',
  128. 'ending_balance',
  129. ];
  130. foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
  131. $categoryHeader = [];
  132. foreach ($columns as $index => $column) {
  133. $categoryHeader[$index] = $column === 'account_name' ? $accountCategoryName : '';
  134. }
  135. $categorySummary = [];
  136. foreach ($columns as $column) {
  137. $categorySummary[] = match ($column) {
  138. 'account_name' => 'Total ' . $accountCategoryName,
  139. 'ending_balance' => $accountCategory->summary->endingBalance ?? '',
  140. default => '',
  141. };
  142. }
  143. $types = [];
  144. $totalTypeSummaries = 0;
  145. // Iterate through each account type and calculate type summaries
  146. foreach ($accountCategory->types as $typeName => $type) {
  147. $typeSummary = [];
  148. $typeEndingBalance = 0;
  149. foreach ($columns as $column) {
  150. $typeSummary[] = match ($column) {
  151. 'account_name' => 'Total ' . $typeName,
  152. 'ending_balance' => $type->summary->endingBalance ?? '',
  153. default => '',
  154. };
  155. if ($column === 'ending_balance') {
  156. $typeEndingBalance = $type->summary->endingBalance ?? 0;
  157. }
  158. }
  159. $typeEndingBalance = money($typeEndingBalance, CurrencyAccessor::getDefaultCurrency())->getAmount();
  160. $totalTypeSummaries += $typeEndingBalance;
  161. $types[$typeName] = new ReportTypeDTO(
  162. header: [],
  163. data: [],
  164. summary: $typeSummary,
  165. );
  166. }
  167. // Only for the "Equity" category, calculate and add "Total Other Equity"
  168. if ($accountCategoryName === 'Equity') {
  169. $totalEquitySummary = $accountCategory->summary->endingBalance ?? 0;
  170. $totalEquitySummary = money($totalEquitySummary, CurrencyAccessor::getDefaultCurrency())->getAmount();
  171. $totalOtherEquity = $totalEquitySummary - $totalTypeSummaries;
  172. $totalOtherEquity = money($totalOtherEquity, CurrencyAccessor::getDefaultCurrency(), true)->format();
  173. // Add "Total Other Equity" as a new "type"
  174. $otherEquitySummary = [];
  175. foreach ($columns as $column) {
  176. $otherEquitySummary[] = match ($column) {
  177. 'account_name' => 'Total Other Equity',
  178. 'ending_balance' => $totalOtherEquity,
  179. default => '',
  180. };
  181. }
  182. $types['Total Other Equity'] = new ReportTypeDTO(
  183. header: [],
  184. data: [],
  185. summary: $otherEquitySummary,
  186. );
  187. }
  188. // Add the category with its types and summary to the final array
  189. $summaryCategories[$accountCategoryName] = new ReportCategoryDTO(
  190. header: $categoryHeader,
  191. data: [],
  192. summary: $categorySummary,
  193. types: $types,
  194. );
  195. }
  196. return $summaryCategories;
  197. }
  198. public function getOverallTotals(): array
  199. {
  200. return [];
  201. }
  202. public function getSummary(): array
  203. {
  204. $this->calculateTotals();
  205. return [
  206. [
  207. 'label' => 'Total Assets',
  208. 'value' => $this->totalAssets,
  209. ],
  210. [
  211. 'label' => 'Total Liabilities',
  212. 'value' => $this->totalLiabilities,
  213. ],
  214. [
  215. 'label' => 'Net Assets',
  216. 'value' => $this->report->overallTotal->endingBalance ?? '',
  217. ],
  218. ];
  219. }
  220. }