您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

IncomeStatementReportTransformer.php 6.5KB

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