選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

CashFlowStatementReportTransformer.php 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <?php
  2. namespace App\Transformers;
  3. use App\DTO\AccountDTO;
  4. use App\DTO\ReportCategoryDTO;
  5. use App\DTO\ReportDTO;
  6. use App\DTO\ReportTypeDTO;
  7. use App\Utilities\Currency\CurrencyConverter;
  8. class CashFlowStatementReportTransformer extends SummaryReportTransformer
  9. {
  10. protected string $totalOperatingActivities;
  11. protected string $totalInvestingActivities;
  12. protected string $totalFinancingActivities;
  13. protected string $grossCashInflow;
  14. protected string $grossCashOutflow;
  15. public function __construct(ReportDTO $report)
  16. {
  17. parent::__construct($report);
  18. $this->calculateTotals();
  19. }
  20. public function getTitle(): string
  21. {
  22. return 'Cash Flow Statement';
  23. }
  24. public function calculateTotals(): void
  25. {
  26. $cashInflow = 0;
  27. $cashOutflow = 0;
  28. foreach ($this->report->categories as $categoryName => $category) {
  29. $netMovement = CurrencyConverter::convertToCents($category->summary->netMovement);
  30. match ($categoryName) {
  31. 'Operating Activities' => $this->totalOperatingActivities = $netMovement,
  32. 'Investing Activities' => $this->totalInvestingActivities = $netMovement,
  33. 'Financing Activities' => $this->totalFinancingActivities = $netMovement,
  34. };
  35. // Sum inflows and outflows separately
  36. if ($netMovement > 0) {
  37. $cashInflow += $netMovement;
  38. } else {
  39. $cashOutflow += $netMovement;
  40. }
  41. }
  42. // Store gross totals
  43. $this->grossCashInflow = CurrencyConverter::formatCentsToMoney($cashInflow);
  44. $this->grossCashOutflow = CurrencyConverter::formatCentsToMoney(abs($cashOutflow));
  45. }
  46. public function getCategories(): array
  47. {
  48. $categories = [];
  49. foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
  50. // Header for the main category
  51. $header = [];
  52. foreach ($this->getColumns() as $column) {
  53. $header[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
  54. }
  55. // Category-level summary
  56. $categorySummary = [];
  57. foreach ($this->getColumns() as $column) {
  58. $categorySummary[$column->getName()] = match ($column->getName()) {
  59. 'account_name' => 'Total ' . $accountCategoryName,
  60. 'net_movement' => $accountCategory->summary->netMovement ?? '',
  61. default => '',
  62. };
  63. }
  64. // Accounts directly under the main category
  65. $data = array_map(function (AccountDTO $account) {
  66. $row = [];
  67. foreach ($this->getColumns() as $column) {
  68. $row[$column->getName()] = match ($column->getName()) {
  69. 'account_code' => $account->accountCode,
  70. 'account_name' => [
  71. 'name' => $account->accountName,
  72. 'id' => $account->accountId ?? null,
  73. 'start_date' => $account->startDate,
  74. 'end_date' => $account->endDate,
  75. ],
  76. 'net_movement' => $account->balance->netMovement ?? '',
  77. default => '',
  78. };
  79. }
  80. return $row;
  81. }, $accountCategory->accounts ?? []);
  82. // Subcategories (types) under the main category
  83. $types = [];
  84. foreach ($accountCategory->types as $typeName => $type) {
  85. // Header for subcategory (type)
  86. $typeHeader = [];
  87. foreach ($this->getColumns() as $column) {
  88. $typeHeader[$column->getName()] = $column->getName() === 'account_name' ? $typeName : '';
  89. }
  90. // Account data for the subcategory
  91. $typeData = array_map(function (AccountDTO $account) {
  92. $row = [];
  93. foreach ($this->getColumns() as $column) {
  94. $row[$column->getName()] = match ($column->getName()) {
  95. 'account_code' => $account->accountCode,
  96. 'account_name' => [
  97. 'name' => $account->accountName,
  98. 'id' => $account->accountId ?? null,
  99. 'start_date' => $account->startDate,
  100. 'end_date' => $account->endDate,
  101. ],
  102. 'net_movement' => $account->balance->netMovement ?? '',
  103. default => '',
  104. };
  105. }
  106. return $row;
  107. }, $type->accounts ?? []);
  108. // Subcategory (type) summary
  109. $typeSummary = [];
  110. foreach ($this->getColumns() as $column) {
  111. $typeSummary[$column->getName()] = match ($column->getName()) {
  112. 'account_name' => 'Total ' . $typeName,
  113. 'net_movement' => $type->summary->netMovement ?? '',
  114. default => '',
  115. };
  116. }
  117. // Add subcategory (type) to the list
  118. $types[$typeName] = new ReportTypeDTO(
  119. header: $typeHeader,
  120. data: $typeData,
  121. summary: $typeSummary,
  122. );
  123. }
  124. // Add the category to the final array with its direct accounts and subcategories (types)
  125. $categories[$accountCategoryName] = new ReportCategoryDTO(
  126. header: $header,
  127. data: $data, // Direct accounts under the category
  128. summary: $categorySummary,
  129. types: $types, // Subcategories (types) under the category
  130. );
  131. }
  132. return $categories;
  133. }
  134. public function getSummaryCategories(): array
  135. {
  136. $summaryCategories = [];
  137. $columns = $this->getSummaryColumns();
  138. foreach ($this->report->categories as $accountCategoryName => $accountCategory) {
  139. $categoryHeader = [];
  140. foreach ($columns as $column) {
  141. $categoryHeader[$column->getName()] = $column->getName() === 'account_name' ? $accountCategoryName : '';
  142. }
  143. $categorySummary = [];
  144. foreach ($columns as $column) {
  145. $categorySummary[$column->getName()] = match ($column->getName()) {
  146. 'account_name' => 'Total ' . $accountCategoryName,
  147. 'net_movement' => $accountCategory->summary->netMovement ?? '',
  148. default => '',
  149. };
  150. }
  151. $types = [];
  152. // Iterate through each account type and calculate type summaries
  153. foreach ($accountCategory->types as $typeName => $type) {
  154. $typeSummary = [];
  155. foreach ($columns as $column) {
  156. $typeSummary[$column->getName()] = match ($column->getName()) {
  157. 'account_name' => 'Total ' . $typeName,
  158. 'net_movement' => $type->summary->netMovement ?? '',
  159. default => '',
  160. };
  161. }
  162. $types[$typeName] = new ReportTypeDTO(
  163. header: [],
  164. data: [],
  165. summary: $typeSummary,
  166. );
  167. }
  168. // Add the category with its types and summary to the final array
  169. $summaryCategories[$accountCategoryName] = new ReportCategoryDTO(
  170. header: $categoryHeader,
  171. data: [],
  172. summary: $categorySummary,
  173. types: $types,
  174. );
  175. }
  176. return $summaryCategories;
  177. }
  178. public function getOverallTotals(): array
  179. {
  180. return [];
  181. }
  182. public function getSummaryOverallTotals(): array
  183. {
  184. return [];
  185. }
  186. public function getSummary(): array
  187. {
  188. return [
  189. [
  190. 'label' => 'Gross Cash Inflow',
  191. 'value' => $this->grossCashInflow,
  192. ],
  193. [
  194. 'label' => 'Gross Cash Outflow',
  195. 'value' => $this->grossCashOutflow,
  196. ],
  197. [
  198. 'label' => 'Net Cash Flow',
  199. 'value' => $this->report->overallTotal->netMovement ?? '',
  200. ],
  201. ];
  202. }
  203. }