Andrew Wallo 1 year ago
parent
commit
f511f7bd0e

+ 0
- 16
app/DTO/ReportDatesDTO.php View File

1
-<?php
2
-
3
-namespace App\DTO;
4
-
5
-use Illuminate\Support\Carbon;
6
-
7
-class ReportDatesDTO
8
-{
9
-    public function __construct(
10
-        public Carbon $fiscalYearStartDate,
11
-        public Carbon $fiscalYearEndDate,
12
-        public string $defaultDateRange,
13
-        public Carbon $defaultStartDate,
14
-        public Carbon $defaultEndDate,
15
-    ) {}
16
-}

+ 47
- 12
app/Factories/ReportDateFactory.php View File

2
 
2
 
3
 namespace App\Factories;
3
 namespace App\Factories;
4
 
4
 
5
-use App\DTO\ReportDatesDTO;
6
 use App\Models\Company;
5
 use App\Models\Company;
7
 use Illuminate\Support\Carbon;
6
 use Illuminate\Support\Carbon;
8
 
7
 
9
 class ReportDateFactory
8
 class ReportDateFactory
10
 {
9
 {
11
-    public static function create(Company $company): ReportDatesDTO
10
+    public Carbon $fiscalYearStartDate;
11
+
12
+    public Carbon $fiscalYearEndDate;
13
+
14
+    public string $defaultDateRange;
15
+
16
+    public Carbon $defaultStartDate;
17
+
18
+    public Carbon $defaultEndDate;
19
+
20
+    public Carbon $earliestTransactionDate;
21
+
22
+    protected Company $company;
23
+
24
+    public function __construct(Company $company)
25
+    {
26
+        $this->company = $company;
27
+        $this->buildReportDates();
28
+    }
29
+
30
+    protected function buildReportDates(): void
12
     {
31
     {
13
-        $fiscalYearStartDate = Carbon::parse($company->locale->fiscalYearStartDate())->startOfDay();
14
-        $fiscalYearEndDate = Carbon::parse($company->locale->fiscalYearEndDate())->endOfDay();
32
+        $fiscalYearStartDate = Carbon::parse($this->company->locale->fiscalYearStartDate())->startOfDay();
33
+        $fiscalYearEndDate = Carbon::parse($this->company->locale->fiscalYearEndDate())->endOfDay();
15
         $defaultDateRange = 'FY-' . now()->year;
34
         $defaultDateRange = 'FY-' . now()->year;
16
         $defaultStartDate = $fiscalYearStartDate->startOfDay();
35
         $defaultStartDate = $fiscalYearStartDate->startOfDay();
17
         $defaultEndDate = $fiscalYearEndDate->isFuture() ? now()->endOfDay() : $fiscalYearEndDate->endOfDay();
36
         $defaultEndDate = $fiscalYearEndDate->isFuture() ? now()->endOfDay() : $fiscalYearEndDate->endOfDay();
18
 
37
 
19
-        // Return a new DTO with the calculated values
20
-        return new ReportDatesDTO(
21
-            $fiscalYearStartDate,
22
-            $fiscalYearEndDate,
23
-            $defaultDateRange,
24
-            $defaultStartDate,
25
-            $defaultEndDate
26
-        );
38
+        // Calculate the earliest transaction date based on the company's transactions
39
+        $earliestTransactionDate = $this->company->transactions()->min('posted_at')
40
+            ? Carbon::parse($this->company->transactions()->min('posted_at'))->startOfDay()
41
+            : $defaultStartDate;
42
+
43
+        // Assign values to properties
44
+        $this->fiscalYearStartDate = $fiscalYearStartDate;
45
+        $this->fiscalYearEndDate = $fiscalYearEndDate;
46
+        $this->defaultDateRange = $defaultDateRange;
47
+        $this->defaultStartDate = $defaultStartDate;
48
+        $this->defaultEndDate = $defaultEndDate;
49
+        $this->earliestTransactionDate = $earliestTransactionDate;
50
+    }
51
+
52
+    public function refresh(): self
53
+    {
54
+        $this->buildReportDates();
55
+
56
+        return $this;
57
+    }
58
+
59
+    public static function create(Company $company): self
60
+    {
61
+        return new static($company);
27
     }
62
     }
28
 }
63
 }

+ 8
- 4
app/Repositories/Accounting/JournalEntryRepository.php View File

4
 
4
 
5
 use App\Models\Accounting\Account;
5
 use App\Models\Accounting\Account;
6
 use Illuminate\Database\Eloquent\Builder;
6
 use Illuminate\Database\Eloquent\Builder;
7
+use Illuminate\Support\Carbon;
7
 
8
 
8
 class JournalEntryRepository
9
 class JournalEntryRepository
9
 {
10
 {
11
     {
12
     {
12
         $query = $account->journalEntries()->where('type', $type);
13
         $query = $account->journalEntries()->where('type', $type);
13
 
14
 
15
+        $startDateCarbon = Carbon::parse($startDate)->startOfDay();
16
+        $endDateCarbon = Carbon::parse($endDate)->endOfDay();
17
+
14
         if ($startDate && $endDate) {
18
         if ($startDate && $endDate) {
15
-            $query->whereHas('transaction', static function (Builder $query) use ($startDate, $endDate) {
16
-                $query->whereBetween('posted_at', [$startDate, $endDate]);
19
+            $query->whereHas('transaction', static function (Builder $query) use ($startDateCarbon, $endDateCarbon) {
20
+                $query->whereBetween('posted_at', [$startDateCarbon, $endDateCarbon]);
17
             });
21
             });
18
         } elseif ($startDate) {
22
         } elseif ($startDate) {
19
-            $query->whereHas('transaction', static function (Builder $query) use ($startDate) {
20
-                $query->where('posted_at', '<=', $startDate);
23
+            $query->whereHas('transaction', static function (Builder $query) use ($startDateCarbon) {
24
+                $query->where('posted_at', '<=', $startDateCarbon);
21
             });
25
             });
22
         }
26
         }
23
 
27
 

+ 2
- 3
app/Services/AccountService.php View File

240
 
240
 
241
     public function getEarliestTransactionDate(): string
241
     public function getEarliestTransactionDate(): string
242
     {
242
     {
243
-        $earliestDate = Transaction::oldest('posted_at')
244
-            ->value('posted_at');
243
+        $earliestDate = Transaction::min('posted_at');
245
 
244
 
246
-        return $earliestDate ?? now()->toDateString();
245
+        return $earliestDate ?? now()->toDateTimeString();
247
     }
246
     }
248
 }
247
 }

+ 1
- 1
app/Services/ReportService.php View File

96
         return new ReportDTO($accountCategories, $formattedReportTotalBalances, $columns);
96
         return new ReportDTO($accountCategories, $formattedReportTotalBalances, $columns);
97
     }
97
     }
98
 
98
 
99
-    private function calculateAccountBalances(Account $account, AccountCategory $category): array
99
+    public function calculateAccountBalances(Account $account, AccountCategory $category): array
100
     {
100
     {
101
         $balances = [
101
         $balances = [
102
             'debit_balance' => $account->total_debit ?? 0,
102
             'debit_balance' => $account->total_debit ?? 0,

+ 33
- 33
composer.lock View File

8
     "packages": [
8
     "packages": [
9
         {
9
         {
10
             "name": "akaunting/laravel-money",
10
             "name": "akaunting/laravel-money",
11
-            "version": "5.2.1",
11
+            "version": "5.2.2",
12
             "source": {
12
             "source": {
13
                 "type": "git",
13
                 "type": "git",
14
                 "url": "https://github.com/akaunting/laravel-money.git",
14
                 "url": "https://github.com/akaunting/laravel-money.git",
15
-                "reference": "6cc8abb912286c671de5993ffbcd3225588aeace"
15
+                "reference": "d99a9e8e576cac40668d0a5afaf7ea153590aff9"
16
             },
16
             },
17
             "dist": {
17
             "dist": {
18
                 "type": "zip",
18
                 "type": "zip",
19
-                "url": "https://api.github.com/repos/akaunting/laravel-money/zipball/6cc8abb912286c671de5993ffbcd3225588aeace",
20
-                "reference": "6cc8abb912286c671de5993ffbcd3225588aeace",
19
+                "url": "https://api.github.com/repos/akaunting/laravel-money/zipball/d99a9e8e576cac40668d0a5afaf7ea153590aff9",
20
+                "reference": "d99a9e8e576cac40668d0a5afaf7ea153590aff9",
21
                 "shasum": ""
21
                 "shasum": ""
22
             },
22
             },
23
             "require": {
23
             "require": {
71
             ],
71
             ],
72
             "support": {
72
             "support": {
73
                 "issues": "https://github.com/akaunting/laravel-money/issues",
73
                 "issues": "https://github.com/akaunting/laravel-money/issues",
74
-                "source": "https://github.com/akaunting/laravel-money/tree/5.2.1"
74
+                "source": "https://github.com/akaunting/laravel-money/tree/5.2.2"
75
             },
75
             },
76
-            "time": "2024-07-23T15:01:26+00:00"
76
+            "time": "2024-09-25T10:06:11+00:00"
77
         },
77
         },
78
         {
78
         {
79
             "name": "andrewdwallo/filament-companies",
79
             "name": "andrewdwallo/filament-companies",
497
         },
497
         },
498
         {
498
         {
499
             "name": "aws/aws-sdk-php",
499
             "name": "aws/aws-sdk-php",
500
-            "version": "3.322.4",
500
+            "version": "3.322.5",
501
             "source": {
501
             "source": {
502
                 "type": "git",
502
                 "type": "git",
503
                 "url": "https://github.com/aws/aws-sdk-php.git",
503
                 "url": "https://github.com/aws/aws-sdk-php.git",
504
-                "reference": "f6d2c64cb87d9e70ad99aeaffcd879a412d2ccb5"
504
+                "reference": "968fe51da0854eac0e0aeac6ec8b86856c6bd83e"
505
             },
505
             },
506
             "dist": {
506
             "dist": {
507
                 "type": "zip",
507
                 "type": "zip",
508
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f6d2c64cb87d9e70ad99aeaffcd879a412d2ccb5",
509
-                "reference": "f6d2c64cb87d9e70ad99aeaffcd879a412d2ccb5",
508
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/968fe51da0854eac0e0aeac6ec8b86856c6bd83e",
509
+                "reference": "968fe51da0854eac0e0aeac6ec8b86856c6bd83e",
510
                 "shasum": ""
510
                 "shasum": ""
511
             },
511
             },
512
             "require": {
512
             "require": {
589
             "support": {
589
             "support": {
590
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
590
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
591
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
591
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
592
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.322.4"
592
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.322.5"
593
             },
593
             },
594
-            "time": "2024-09-24T18:10:10+00:00"
594
+            "time": "2024-09-25T18:14:27+00:00"
595
         },
595
         },
596
         {
596
         {
597
             "name": "aws/aws-sdk-php-laravel",
597
             "name": "aws/aws-sdk-php-laravel",
2981
         },
2981
         },
2982
         {
2982
         {
2983
             "name": "laravel/framework",
2983
             "name": "laravel/framework",
2984
-            "version": "v11.24.0",
2984
+            "version": "v11.24.1",
2985
             "source": {
2985
             "source": {
2986
                 "type": "git",
2986
                 "type": "git",
2987
                 "url": "https://github.com/laravel/framework.git",
2987
                 "url": "https://github.com/laravel/framework.git",
2988
-                "reference": "557da2b02e298acbd12b3fb7d04d16ea253c5f20"
2988
+                "reference": "e063fa80ac5818099f45a3a57dd803476c8f3a2a"
2989
             },
2989
             },
2990
             "dist": {
2990
             "dist": {
2991
                 "type": "zip",
2991
                 "type": "zip",
2992
-                "url": "https://api.github.com/repos/laravel/framework/zipball/557da2b02e298acbd12b3fb7d04d16ea253c5f20",
2993
-                "reference": "557da2b02e298acbd12b3fb7d04d16ea253c5f20",
2992
+                "url": "https://api.github.com/repos/laravel/framework/zipball/e063fa80ac5818099f45a3a57dd803476c8f3a2a",
2993
+                "reference": "e063fa80ac5818099f45a3a57dd803476c8f3a2a",
2994
                 "shasum": ""
2994
                 "shasum": ""
2995
             },
2995
             },
2996
             "require": {
2996
             "require": {
3186
                 "issues": "https://github.com/laravel/framework/issues",
3186
                 "issues": "https://github.com/laravel/framework/issues",
3187
                 "source": "https://github.com/laravel/framework"
3187
                 "source": "https://github.com/laravel/framework"
3188
             },
3188
             },
3189
-            "time": "2024-09-24T14:46:11+00:00"
3189
+            "time": "2024-09-25T07:21:24+00:00"
3190
         },
3190
         },
3191
         {
3191
         {
3192
             "name": "laravel/prompts",
3192
             "name": "laravel/prompts",
9450
         },
9450
         },
9451
         {
9451
         {
9452
             "name": "filp/whoops",
9452
             "name": "filp/whoops",
9453
-            "version": "2.15.4",
9453
+            "version": "2.16.0",
9454
             "source": {
9454
             "source": {
9455
                 "type": "git",
9455
                 "type": "git",
9456
                 "url": "https://github.com/filp/whoops.git",
9456
                 "url": "https://github.com/filp/whoops.git",
9457
-                "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546"
9457
+                "reference": "befcdc0e5dce67252aa6322d82424be928214fa2"
9458
             },
9458
             },
9459
             "dist": {
9459
             "dist": {
9460
                 "type": "zip",
9460
                 "type": "zip",
9461
-                "url": "https://api.github.com/repos/filp/whoops/zipball/a139776fa3f5985a50b509f2a02ff0f709d2a546",
9462
-                "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546",
9461
+                "url": "https://api.github.com/repos/filp/whoops/zipball/befcdc0e5dce67252aa6322d82424be928214fa2",
9462
+                "reference": "befcdc0e5dce67252aa6322d82424be928214fa2",
9463
                 "shasum": ""
9463
                 "shasum": ""
9464
             },
9464
             },
9465
             "require": {
9465
             "require": {
9466
-                "php": "^5.5.9 || ^7.0 || ^8.0",
9466
+                "php": "^7.1 || ^8.0",
9467
                 "psr/log": "^1.0.1 || ^2.0 || ^3.0"
9467
                 "psr/log": "^1.0.1 || ^2.0 || ^3.0"
9468
             },
9468
             },
9469
             "require-dev": {
9469
             "require-dev": {
9470
-                "mockery/mockery": "^0.9 || ^1.0",
9471
-                "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3",
9472
-                "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0"
9470
+                "mockery/mockery": "^1.0",
9471
+                "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3",
9472
+                "symfony/var-dumper": "^4.0 || ^5.0"
9473
             },
9473
             },
9474
             "suggest": {
9474
             "suggest": {
9475
                 "symfony/var-dumper": "Pretty print complex values better with var-dumper available",
9475
                 "symfony/var-dumper": "Pretty print complex values better with var-dumper available",
9509
             ],
9509
             ],
9510
             "support": {
9510
             "support": {
9511
                 "issues": "https://github.com/filp/whoops/issues",
9511
                 "issues": "https://github.com/filp/whoops/issues",
9512
-                "source": "https://github.com/filp/whoops/tree/2.15.4"
9512
+                "source": "https://github.com/filp/whoops/tree/2.16.0"
9513
             },
9513
             },
9514
             "funding": [
9514
             "funding": [
9515
                 {
9515
                 {
9517
                     "type": "github"
9517
                     "type": "github"
9518
                 }
9518
                 }
9519
             ],
9519
             ],
9520
-            "time": "2023-11-03T12:00:00+00:00"
9520
+            "time": "2024-09-25T12:00:00+00:00"
9521
         },
9521
         },
9522
         {
9522
         {
9523
             "name": "hamcrest/hamcrest-php",
9523
             "name": "hamcrest/hamcrest-php",
10000
         },
10000
         },
10001
         {
10001
         {
10002
             "name": "pestphp/pest",
10002
             "name": "pestphp/pest",
10003
-            "version": "v3.2.2",
10003
+            "version": "v3.2.3",
10004
             "source": {
10004
             "source": {
10005
                 "type": "git",
10005
                 "type": "git",
10006
                 "url": "https://github.com/pestphp/pest.git",
10006
                 "url": "https://github.com/pestphp/pest.git",
10007
-                "reference": "989e43d1a01e5a3b5333cffe5c8e633ac4d17da2"
10007
+                "reference": "4e2987d438a3c3b2f291d2c991049544ab2f52bb"
10008
             },
10008
             },
10009
             "dist": {
10009
             "dist": {
10010
                 "type": "zip",
10010
                 "type": "zip",
10011
-                "url": "https://api.github.com/repos/pestphp/pest/zipball/989e43d1a01e5a3b5333cffe5c8e633ac4d17da2",
10012
-                "reference": "989e43d1a01e5a3b5333cffe5c8e633ac4d17da2",
10011
+                "url": "https://api.github.com/repos/pestphp/pest/zipball/4e2987d438a3c3b2f291d2c991049544ab2f52bb",
10012
+                "reference": "4e2987d438a3c3b2f291d2c991049544ab2f52bb",
10013
                 "shasum": ""
10013
                 "shasum": ""
10014
             },
10014
             },
10015
             "require": {
10015
             "require": {
10095
             ],
10095
             ],
10096
             "support": {
10096
             "support": {
10097
                 "issues": "https://github.com/pestphp/pest/issues",
10097
                 "issues": "https://github.com/pestphp/pest/issues",
10098
-                "source": "https://github.com/pestphp/pest/tree/v3.2.2"
10098
+                "source": "https://github.com/pestphp/pest/tree/v3.2.3"
10099
             },
10099
             },
10100
             "funding": [
10100
             "funding": [
10101
                 {
10101
                 {
10107
                     "type": "github"
10107
                     "type": "github"
10108
                 }
10108
                 }
10109
             ],
10109
             ],
10110
-            "time": "2024-09-24T09:23:43+00:00"
10110
+            "time": "2024-09-25T15:19:39+00:00"
10111
         },
10111
         },
10112
         {
10112
         {
10113
             "name": "pestphp/pest-plugin",
10113
             "name": "pestphp/pest-plugin",

+ 14
- 14
package-lock.json View File

955
             }
955
             }
956
         },
956
         },
957
         "node_modules/browserslist": {
957
         "node_modules/browserslist": {
958
-            "version": "4.23.3",
959
-            "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz",
960
-            "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==",
958
+            "version": "4.24.0",
959
+            "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
960
+            "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==",
961
             "dev": true,
961
             "dev": true,
962
             "funding": [
962
             "funding": [
963
                 {
963
                 {
975
             ],
975
             ],
976
             "license": "MIT",
976
             "license": "MIT",
977
             "dependencies": {
977
             "dependencies": {
978
-                "caniuse-lite": "^1.0.30001646",
979
-                "electron-to-chromium": "^1.5.4",
978
+                "caniuse-lite": "^1.0.30001663",
979
+                "electron-to-chromium": "^1.5.28",
980
                 "node-releases": "^2.0.18",
980
                 "node-releases": "^2.0.18",
981
                 "update-browserslist-db": "^1.1.0"
981
                 "update-browserslist-db": "^1.1.0"
982
             },
982
             },
998
             }
998
             }
999
         },
999
         },
1000
         "node_modules/caniuse-lite": {
1000
         "node_modules/caniuse-lite": {
1001
-            "version": "1.0.30001663",
1002
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz",
1003
-            "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==",
1001
+            "version": "1.0.30001664",
1002
+            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz",
1003
+            "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==",
1004
             "dev": true,
1004
             "dev": true,
1005
             "funding": [
1005
             "funding": [
1006
                 {
1006
                 {
1159
             "license": "MIT"
1159
             "license": "MIT"
1160
         },
1160
         },
1161
         "node_modules/electron-to-chromium": {
1161
         "node_modules/electron-to-chromium": {
1162
-            "version": "1.5.28",
1163
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.28.tgz",
1164
-            "integrity": "sha512-VufdJl+rzaKZoYVUijN13QcXVF5dWPZANeFTLNy+OSpHdDL5ynXTF35+60RSBbaQYB1ae723lQXHCrf4pyLsMw==",
1162
+            "version": "1.5.29",
1163
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz",
1164
+            "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==",
1165
             "dev": true,
1165
             "dev": true,
1166
             "license": "ISC"
1166
             "license": "ISC"
1167
         },
1167
         },
2550
             "license": "MIT"
2550
             "license": "MIT"
2551
         },
2551
         },
2552
         "node_modules/vite": {
2552
         "node_modules/vite": {
2553
-            "version": "5.4.7",
2554
-            "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz",
2555
-            "integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==",
2553
+            "version": "5.4.8",
2554
+            "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
2555
+            "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==",
2556
             "dev": true,
2556
             "dev": true,
2557
             "license": "MIT",
2557
             "license": "MIT",
2558
             "dependencies": {
2558
             "dependencies": {

+ 59
- 12
tests/Feature/Reports/AccountBalancesReportTest.php View File

7
 
7
 
8
 use function Pest\Livewire\livewire;
8
 use function Pest\Livewire\livewire;
9
 
9
 
10
-it('correctly builds a account balances report', function () {
10
+it('correctly builds an account balances report for the current fiscal year', function () {
11
     $testCompany = $this->testCompany;
11
     $testCompany = $this->testCompany;
12
 
12
 
13
-    $reportDatesDTO = ReportDateFactory::create($testCompany);
14
-    $defaultDateRange = $reportDatesDTO->defaultDateRange;
15
-    $defaultStartDate = $reportDatesDTO->defaultStartDate->toImmutable();
16
-    $defaultEndDate = $reportDatesDTO->defaultEndDate->toImmutable();
13
+    $reportDates = ReportDateFactory::create($testCompany);
14
+    $defaultDateRange = $reportDates->defaultDateRange;
15
+    $defaultStartDate = $reportDates->defaultStartDate->toImmutable();
16
+    $defaultEndDate = $reportDates->defaultEndDate->toImmutable();
17
 
17
 
18
     $depositAmount = 1000;
18
     $depositAmount = 1000;
19
     $withdrawalAmount = 1000;
19
     $withdrawalAmount = 1000;
20
     $depositCount = 10;
20
     $depositCount = 10;
21
     $withdrawalCount = 10;
21
     $withdrawalCount = 10;
22
 
22
 
23
-    // Create transactions for the company
24
     Transaction::factory()
23
     Transaction::factory()
25
         ->forDefaultBankAccount()
24
         ->forDefaultBankAccount()
26
         ->forUncategorizedRevenue()
25
         ->forUncategorizedRevenue()
41
         ])
40
         ])
42
         ->create();
41
         ->create();
43
 
42
 
44
-    $defaultBankAccount = $testCompany->default->bankAccount->account;
43
+    $defaultBankAccountAccount = $testCompany->default->bankAccount->account;
45
 
44
 
46
-    $fields = $defaultBankAccount->category->getRelevantBalanceFields();
45
+    $fields = $defaultBankAccountAccount->category->getRelevantBalanceFields();
47
 
46
 
48
-    $expectedBalances = Accounting::getBalances($defaultBankAccount, $defaultStartDate->toDateString(), $defaultEndDate->toDateString(), $fields);
47
+    $expectedBalances = Accounting::getBalances(
48
+        $defaultBankAccountAccount,
49
+        $defaultStartDate->toDateString(),
50
+        $defaultEndDate->toDateString(),
51
+        $fields
52
+    );
49
 
53
 
50
     $formattedExpectedBalances = formatReportBalances($expectedBalances);
54
     $formattedExpectedBalances = formatReportBalances($expectedBalances);
51
 
55
 
62
         ])
66
         ])
63
         ->call('applyFilters')
67
         ->call('applyFilters')
64
         ->assertSeeTextInOrder([
68
         ->assertSeeTextInOrder([
65
-            'Cash on Hand',
69
+            $defaultBankAccountAccount->name,
66
             $formattedExpectedBalances->startingBalance,
70
             $formattedExpectedBalances->startingBalance,
67
             $formattedExpectedBalances->debitBalance,
71
             $formattedExpectedBalances->debitBalance,
68
             $formattedExpectedBalances->creditBalance,
72
             $formattedExpectedBalances->creditBalance,
70
             $formattedExpectedBalances->endingBalance,
74
             $formattedExpectedBalances->endingBalance,
71
         ])
75
         ])
72
         ->assertReportTableData();
76
         ->assertReportTableData();
77
+});
78
+
79
+it('correctly builds an account balances report for the previous fiscal year', function () {
80
+    $testCompany = $this->testCompany;
81
+
82
+    $reportDatesDTO = ReportDateFactory::create($testCompany);
83
+    $defaultDateRange = $reportDatesDTO->defaultDateRange;
84
+    $defaultStartDate = $reportDatesDTO->defaultStartDate->toImmutable();
85
+    $defaultEndDate = $reportDatesDTO->defaultEndDate->toImmutable();
86
+
87
+    $depositAmount = 1000;
88
+    $withdrawalAmount = 1000;
89
+    $depositCount = 10;
90
+    $withdrawalCount = 10;
91
+
92
+    Transaction::factory()
93
+        ->forDefaultBankAccount()
94
+        ->forUncategorizedRevenue()
95
+        ->asDeposit($depositAmount)
96
+        ->count($depositCount)
97
+        ->state([
98
+            'posted_at' => $defaultStartDate->subWeek(),
99
+        ])
100
+        ->create();
101
+
102
+    Transaction::factory()
103
+        ->forDefaultBankAccount()
104
+        ->forUncategorizedExpense()
105
+        ->asWithdrawal($withdrawalAmount)
106
+        ->count($withdrawalCount)
107
+        ->state([
108
+            'posted_at' => $defaultEndDate,
109
+        ])
110
+        ->create();
111
+
112
+    $defaultBankAccountAccount = $testCompany->default->bankAccount->account;
113
+
114
+    $fields = $defaultBankAccountAccount->category->getRelevantBalanceFields();
73
 
115
 
74
-    $expectedBalancesSubYear = Accounting::getBalances($defaultBankAccount, $defaultStartDate->subYear()->startOfYear()->toDateString(), $defaultEndDate->subYear()->endOfYear()->toDateString(), $fields);
116
+    $expectedBalancesSubYear = Accounting::getBalances(
117
+        $defaultBankAccountAccount,
118
+        $defaultStartDate->subYear()->startOfYear()->toDateString(),
119
+        $defaultEndDate->subYear()->endOfYear()->toDateString(),
120
+        $fields
121
+    );
75
 
122
 
76
     $formattedExpectedBalancesSubYear = formatReportBalances($expectedBalancesSubYear);
123
     $formattedExpectedBalancesSubYear = formatReportBalances($expectedBalancesSubYear);
77
 
124
 
92
         ])
139
         ])
93
         ->call('applyFilters')
140
         ->call('applyFilters')
94
         ->assertSeeTextInOrder([
141
         ->assertSeeTextInOrder([
95
-            'Cash on Hand',
142
+            $defaultBankAccountAccount->name,
96
             $formattedExpectedBalancesSubYear->startingBalance,
143
             $formattedExpectedBalancesSubYear->startingBalance,
97
             $formattedExpectedBalancesSubYear->debitBalance,
144
             $formattedExpectedBalancesSubYear->debitBalance,
98
             $formattedExpectedBalancesSubYear->creditBalance,
145
             $formattedExpectedBalancesSubYear->creditBalance,

+ 86
- 38
tests/Feature/Reports/TrialBalanceReportTest.php View File

1
 <?php
1
 <?php
2
 
2
 
3
+use App\Facades\Accounting;
3
 use App\Factories\ReportDateFactory;
4
 use App\Factories\ReportDateFactory;
4
 use App\Filament\Company\Pages\Reports\TrialBalance;
5
 use App\Filament\Company\Pages\Reports\TrialBalance;
5
 use App\Models\Accounting\Transaction;
6
 use App\Models\Accounting\Transaction;
6
-use App\Utilities\Currency\CurrencyAccessor;
7
+use App\Services\AccountService;
8
+use App\Services\ReportService;
7
 
9
 
8
 use function Pest\Livewire\livewire;
10
 use function Pest\Livewire\livewire;
9
 
11
 
10
 it('correctly builds a standard trial balance report', function () {
12
 it('correctly builds a standard trial balance report', function () {
11
     $testCompany = $this->testCompany;
13
     $testCompany = $this->testCompany;
12
 
14
 
13
-    $reportDatesDTO = ReportDateFactory::create($testCompany);
14
-    $defaultDateRange = $reportDatesDTO->defaultDateRange;
15
-    $defaultEndDate = $reportDatesDTO->defaultEndDate;
15
+    $reportDates = ReportDateFactory::create($testCompany);
16
+    $defaultDateRange = $reportDates->defaultDateRange;
17
+    $defaultStartDate = $reportDates->defaultStartDate->toImmutable();
18
+    $defaultEndDate = $reportDates->defaultEndDate->toImmutable();
16
 
19
 
17
     $defaultReportType = 'standard';
20
     $defaultReportType = 'standard';
18
 
21
 
19
-    // Create transactions for the company
22
+    $depositAmount = 1000;
23
+    $withdrawalAmount = 1000;
24
+    $depositCount = 10;
25
+    $withdrawalCount = 10;
26
+
20
     Transaction::factory()
27
     Transaction::factory()
21
         ->forDefaultBankAccount()
28
         ->forDefaultBankAccount()
22
         ->forUncategorizedRevenue()
29
         ->forUncategorizedRevenue()
23
-        ->asDeposit(1000)
24
-        ->count(10)
30
+        ->asDeposit($depositAmount)
31
+        ->count($depositCount)
32
+        ->state([
33
+            'posted_at' => $defaultStartDate->subWeek(),
34
+        ])
35
+        ->create();
36
+
37
+    Transaction::factory()
38
+        ->forDefaultBankAccount()
39
+        ->forUncategorizedExpense()
40
+        ->asWithdrawal($withdrawalAmount)
41
+        ->count($withdrawalCount)
42
+        ->state([
43
+            'posted_at' => now()->subWeek(),
44
+        ])
25
         ->create();
45
         ->create();
26
 
46
 
27
-    $expectedBankAccountDebit = 10000;
28
-    $expectedBankAccountCredit = 0;
47
+    $defaultBankAccountAccount = $testCompany->default->bankAccount->account;
48
+    $earliestTransactionDate = $reportDates->refresh()->earliestTransactionDate;
49
+
50
+    $fields = $defaultBankAccountAccount->category->getRelevantBalanceFields();
51
+
52
+    $expectedBalances = Accounting::getBalances(
53
+        $defaultBankAccountAccount,
54
+        $earliestTransactionDate->toDateString(),
55
+        $defaultEndDate->toDateString(),
56
+        $fields
57
+    );
58
+
59
+    $calculatedTrialBalances = calculateTrialBalances($defaultBankAccountAccount->category, $expectedBalances['ending_balance']);
29
 
60
 
30
-    $defaultCurrencyCode = CurrencyAccessor::getDefaultCurrency();
61
+    $formattedExpectedBalances = formatReportBalances($calculatedTrialBalances);
31
 
62
 
32
     livewire(TrialBalance::class)
63
     livewire(TrialBalance::class)
33
         ->assertFormSet([
64
         ->assertFormSet([
43
         ->call('applyFilters')
74
         ->call('applyFilters')
44
         ->assertDontSeeText('Retained Earnings')
75
         ->assertDontSeeText('Retained Earnings')
45
         ->assertSeeTextInOrder([
76
         ->assertSeeTextInOrder([
46
-            'Cash on Hand',
47
-            money($expectedBankAccountDebit, $defaultCurrencyCode, true),
48
-            money($expectedBankAccountCredit, $defaultCurrencyCode, true),
77
+            $defaultBankAccountAccount->name,
78
+            $formattedExpectedBalances->debitBalance,
79
+            $formattedExpectedBalances->creditBalance,
49
         ])
80
         ])
50
         ->assertReportTableData();
81
         ->assertReportTableData();
51
 });
82
 });
53
 it('correctly builds a post-closing trial balance report', function () {
84
 it('correctly builds a post-closing trial balance report', function () {
54
     $testCompany = $this->testCompany;
85
     $testCompany = $this->testCompany;
55
 
86
 
56
-    $reportDatesDTO = ReportDateFactory::create($testCompany);
57
-    $defaultDateRange = $reportDatesDTO->defaultDateRange;
58
-    $defaultEndDate = $reportDatesDTO->defaultEndDate;
87
+    $reportDates = ReportDateFactory::create($testCompany);
88
+    $defaultDateRange = $reportDates->defaultDateRange;
89
+    $defaultStartDate = $reportDates->defaultStartDate->toImmutable();
90
+    $defaultEndDate = $reportDates->defaultEndDate->toImmutable();
59
 
91
 
60
     $defaultReportType = 'postClosing';
92
     $defaultReportType = 'postClosing';
61
 
93
 
62
-    // Create transactions for the company
94
+    $depositAmount = 2000;
95
+    $withdrawalAmount = 1000;
96
+    $depositCount = 5;
97
+    $withdrawalCount = 5;
98
+
63
     Transaction::factory()
99
     Transaction::factory()
64
         ->forDefaultBankAccount()
100
         ->forDefaultBankAccount()
65
         ->forUncategorizedRevenue()
101
         ->forUncategorizedRevenue()
66
-        ->asDeposit(1000)
102
+        ->asDeposit($depositAmount)
103
+        ->count($depositCount)
104
+        ->state([
105
+            'posted_at' => $defaultStartDate->subWeek(),
106
+        ])
67
         ->create();
107
         ->create();
68
 
108
 
69
     Transaction::factory()
109
     Transaction::factory()
70
         ->forDefaultBankAccount()
110
         ->forDefaultBankAccount()
71
         ->forUncategorizedExpense()
111
         ->forUncategorizedExpense()
72
-        ->asWithdrawal(500)
112
+        ->asWithdrawal($withdrawalAmount)
113
+        ->count($withdrawalCount)
114
+        ->state([
115
+            'posted_at' => now()->subWeek(),
116
+        ])
73
         ->create();
117
         ->create();
74
 
118
 
75
-    $expectedRetainedEarningsDebit = 0;
76
-    $expectedRetainedEarningsCredit = 500;
119
+    $defaultBankAccountAccount = $testCompany->default->bankAccount->account;
120
+    $earliestTransactionDate = $reportDates->refresh()->earliestTransactionDate->toImmutable();
77
 
121
 
78
-    $defaultCurrencyCode = CurrencyAccessor::getDefaultCurrency();
122
+    $fields = $defaultBankAccountAccount->category->getRelevantBalanceFields();
79
 
123
 
124
+    $accountService = app(AccountService::class);
125
+
126
+    $balances = $accountService->getAccountBalances($earliestTransactionDate->toDateTimeString(), $defaultEndDate->toDateTimeString(), [$defaultBankAccountAccount->id]);
127
+
128
+    $account = $balances->find($defaultBankAccountAccount->id);
129
+
130
+    $reportService = app(ReportService::class);
131
+
132
+    $calculatedBalances = $reportService->calculateAccountBalances($account, $account->category);
133
+
134
+    $calculatedTrialBalances = calculateTrialBalances($defaultBankAccountAccount->category, $calculatedBalances['ending_balance']);
135
+
136
+    $formattedExpectedBalances = formatReportBalances($calculatedTrialBalances);
137
+
138
+    // Use Livewire to assert the report's filters and displayed data
80
     livewire(TrialBalance::class)
139
     livewire(TrialBalance::class)
81
         ->set('deferredFilters.reportType', $defaultReportType)
140
         ->set('deferredFilters.reportType', $defaultReportType)
82
-        ->call('applyFilters')
83
         ->assertFormSet([
141
         ->assertFormSet([
84
             'deferredFilters.reportType' => $defaultReportType,
142
             'deferredFilters.reportType' => $defaultReportType,
85
             'deferredFilters.dateRange' => $defaultDateRange,
143
             'deferredFilters.dateRange' => $defaultDateRange,
86
             'deferredFilters.asOfDate' => $defaultEndDate->toDateTimeString(),
144
             'deferredFilters.asOfDate' => $defaultEndDate->toDateTimeString(),
87
         ])
145
         ])
146
+        ->call('applyFilters')
88
         ->assertSet('filters', [
147
         ->assertSet('filters', [
89
             'reportType' => $defaultReportType,
148
             'reportType' => $defaultReportType,
90
             'dateRange' => $defaultDateRange,
149
             'dateRange' => $defaultDateRange,
91
             'asOfDate' => $defaultEndDate->toDateString(),
150
             'asOfDate' => $defaultEndDate->toDateString(),
92
         ])
151
         ])
93
-        ->call('applyFilters')
94
-        ->assertSeeTextInOrder([
95
-            'RE',
96
-            'Retained Earnings',
97
-            money($expectedRetainedEarningsDebit, $defaultCurrencyCode, true),
98
-            money($expectedRetainedEarningsCredit, $defaultCurrencyCode, true),
99
-        ])
100
-        ->assertSeeTextInOrder([
101
-            'Total Revenue',
102
-            money(0, $defaultCurrencyCode, true),
103
-            money(0, $defaultCurrencyCode, true),
104
-        ])
152
+        ->assertSeeText('Retained Earnings')
105
         ->assertSeeTextInOrder([
153
         ->assertSeeTextInOrder([
106
-            'Total Expenses',
107
-            money(0, $defaultCurrencyCode, true),
108
-            money(0, $defaultCurrencyCode, true),
154
+            $defaultBankAccountAccount->name,
155
+            $formattedExpectedBalances->debitBalance,
156
+            $formattedExpectedBalances->creditBalance,
109
         ])
157
         ])
110
         ->assertReportTableData();
158
         ->assertReportTableData();
111
 });
159
 });

+ 8
- 0
tests/Helpers/helpers.php View File

1
 <?php
1
 <?php
2
 
2
 
3
 use App\DTO\AccountBalanceDTO;
3
 use App\DTO\AccountBalanceDTO;
4
+use App\Enums\Accounting\AccountCategory;
4
 use App\Enums\Setting\EntityType;
5
 use App\Enums\Setting\EntityType;
5
 use App\Filament\Company\Pages\CreateCompany;
6
 use App\Filament\Company\Pages\CreateCompany;
6
 use App\Models\Company;
7
 use App\Models\Company;
45
 
46
 
46
     return $reportService->formatBalances($balances);
47
     return $reportService->formatBalances($balances);
47
 }
48
 }
49
+
50
+function calculateTrialBalances(AccountCategory $accountCategory, int $endingBalance): array
51
+{
52
+    $reportService = app(ReportService::class);
53
+
54
+    return $reportService->calculateTrialBalance($accountCategory, $endingBalance);
55
+}

Loading…
Cancel
Save