Skip to content

Commit 3cc6cbb

Browse files
Merge pull request laravel#73 from eurides-eu/feature/add-transaction-endpoints
Transaction endpoints
2 parents e419a6e + 2f8008a commit 3cc6cbb

26 files changed

+1061
-13
lines changed

app/Http/Controllers/SubscriptionsController.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public function __construct(
5656
* @param string $organizationId
5757
* @param SubscriptionRequest $request
5858
*/
59-
public function create(string $organizationId, SubscriptionRequest $request)
59+
public function create(string $organizationId, Organization $organization, SubscriptionRequest $request)
6060
{
6161
$user = $this->userReadRepository->find($request->get('subscriberId'));
6262
$budget = $this->budgetReadRepository->find($request->get('budgetId'));
@@ -69,7 +69,8 @@ public function create(string $organizationId, SubscriptionRequest $request)
6969
Carbon::createFromFormat("Y-m-d\TH:i:sP", $request->get('startOn')),
7070
Carbon::createFromFormat("Y-m-d\TH:i:sP", $request->get('endOn')),
7171
Carbon::createFromFormat("Y-m-d\TH:i:sP", $request->get('requestedOn')),
72-
$request->get('internalReference')
72+
$request->get('internalReference'),
73+
$organization
7374
));
7475

7576
return $this->responseCreated($subscription);
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use App\Http\Requests\Transactions\TransactionRequest;
6+
use App\Models\Organization;
7+
use App\Organizations\Budgets\Repositories\ReadRepository as BudgetReadRepository;
8+
use App\Subscriptions\Repositories\ReadRepository as SubscriptionReadRepository;
9+
use App\Transactions\Commands\CreateTransaction;
10+
use App\Transactions\Commands\DeleteTransaction;
11+
use App\Transactions\Commands\UpdateTransaction;
12+
use App\Transactions\Queries\TransactionsQuery;
13+
use App\Transactions\Repositories\ReadRepository;
14+
use App\Transactions\Transformers\TransactionTransformer;
15+
use Carbon\Carbon;
16+
use Illuminate\Http\Request;
17+
18+
class TransactionsController extends ApiController
19+
{
20+
/**
21+
* @var BudgetReadRepository
22+
*/
23+
protected $budgetReadRepository;
24+
25+
/**
26+
* @var SubscriptionReadRepository
27+
*/
28+
protected $subscriptionReadRepository;
29+
30+
/**
31+
* @var ReadRepository
32+
*/
33+
protected $readRepository;
34+
35+
/**
36+
* TransactionsController constructor.
37+
*
38+
* @param BudgetReadRepository $budgetReadRepository
39+
* @param SubscriptionReadRepository $subscriptionReadRepository
40+
* @param ReadRepository $readRepository
41+
* @param TransactionTransformer $transactionTransformer
42+
*/
43+
public function __construct(
44+
BudgetReadRepository $budgetReadRepository,
45+
SubscriptionReadRepository $subscriptionReadRepository,
46+
ReadRepository $readRepository,
47+
TransactionTransformer $transactionTransformer
48+
) {
49+
$this->setTransformer($transactionTransformer);
50+
$this->budgetReadRepository = $budgetReadRepository;
51+
$this->subscriptionReadRepository = $subscriptionReadRepository;
52+
$this->readRepository = $readRepository;
53+
}
54+
55+
/**
56+
* @param string $organizationId
57+
* @param TransactionRequest $request
58+
*/
59+
public function create(string $organizationId, Organization $organization, TransactionRequest $request)
60+
{
61+
$budget = $this->budgetReadRepository->find($request->get('budgetId'));
62+
$subscription = $this->subscriptionReadRepository->find($request->get('subscriptionId'));
63+
64+
$transaction = $this->dispatch(new CreateTransaction(
65+
$request->get('description'),
66+
$request->get('amount'),
67+
$request->get('status'),
68+
Carbon::createFromFormat("Y-m-d\TH:i:sP", $request->get('occurredOn')),
69+
$request->get('externalReference'),
70+
$budget,
71+
$organization,
72+
$subscription
73+
));
74+
75+
return $this->responseCreated($transaction);
76+
}
77+
78+
/**
79+
* @param string $organizationId
80+
* @param string $transactionId
81+
*/
82+
public function delete(string $organizationId, string $transactionId)
83+
{
84+
$transaction = $this->readRepository->findForOrganization($transactionId, $organizationId);
85+
86+
$this->dispatch(new DeleteTransaction($transaction));
87+
88+
return $this->responseNoContent();
89+
}
90+
91+
/**
92+
* @param string $organizationId
93+
* @param string $transactionId
94+
* @param TransactionRequest $request
95+
*/
96+
public function update(string $organizationId, string $transactionId, TransactionRequest $request)
97+
{
98+
$budget = $this->budgetReadRepository->find($request->get('budgetId'));
99+
$subscription = $this->subscriptionReadRepository->find($request->get('subscriptionId'));
100+
$transaction = $this->readRepository->findForOrganization($transactionId, $organizationId);
101+
102+
$transaction = $this->dispatch(new UpdateTransaction(
103+
$request->get('description'),
104+
$request->get('amount'),
105+
$request->get('status'),
106+
Carbon::createFromFormat("Y-m-d\TH:i:sP", $request->get('occurredOn')),
107+
$request->get('externalReference'),
108+
$budget,
109+
$subscription,
110+
$transaction
111+
));
112+
113+
return $this->responseItem($transaction);
114+
}
115+
116+
/**
117+
* @param string $organizationId
118+
* @param Organization $organization
119+
* @param TransactionsQuery $query
120+
* @param Request $request
121+
*
122+
* @return \Psr\Http\Message\ResponseInterface
123+
*/
124+
public function all(
125+
string $organizationId,
126+
Organization $organization,
127+
TransactionsQuery $query,
128+
Request $request)
129+
{
130+
if ($userId = $request->get('userId')) {
131+
$query->filterByUserId($userId);
132+
}
133+
134+
if ($budgetId = $request->get('budgetId')) {
135+
$query->filterByBudgetId($budgetId);
136+
}
137+
138+
if ($service = $request->get('service')) {
139+
$query->filterByService($service);
140+
}
141+
142+
if ($status = $request->get('status')) {
143+
$query->filterByStatus($status);
144+
}
145+
146+
if ($subscriptionId = $request->get('subscriptionId')) {
147+
$query->filterBySubscriptionId($subscriptionId);
148+
}
149+
150+
$transactions = $query->find($organization);
151+
152+
return $this->responsePaginator($transactions);
153+
}
154+
}

app/Http/Requests/Subscriptions/SubscriptionRequest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
namespace App\Http\Requests\Subscriptions;
44

55
use App\Http\Requests\FormRequest;
6+
use App\Models\Subscription;
67
use App\Organizations\Budgets\Rules\ValidOrganizationBudget;
8+
use App\Organizations\Rules\ValidOrganizationService;
79
use App\Users\Rules\ValidOrganizationUser;
810
use Illuminate\Validation\Rule;
911

@@ -29,8 +31,8 @@ public function rules()
2931
$organizationId = $this->route('organizationId');
3032

3133
return [
32-
'service' => ['string', 'required', Rule::in(config('eurides.services'))],
33-
'status' => ['string', 'required', Rule::in(config('eurides.subscription_statuses'))],
34+
'service' => ['string', 'required', new ValidOrganizationService($organizationId)],
35+
'status' => ['string', 'required', Rule::in(Subscription::$validStatuses)],
3436
'startOn' => 'date_format:Y-m-d\TH:i:sP|required|before:endOn',
3537
'endOn' => 'date_format:Y-m-d\TH:i:sP|required|after:startOn',
3638
'requestedOn' => 'date_format:Y-m-d\TH:i:sP|required',
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace App\Http\Requests\Transactions;
4+
5+
use App\Http\Requests\FormRequest;
6+
use App\Models\Transaction;
7+
use App\Organizations\Budgets\Rules\ValidOrganizationBudget;
8+
use App\Subscriptions\Rules\ValidSubscription;
9+
use Illuminate\Validation\Rule;
10+
11+
class TransactionRequest extends FormRequest
12+
{
13+
/**
14+
* Determine if the user is authorized to make this request.
15+
*
16+
* @return bool
17+
*/
18+
public function authorize()
19+
{
20+
return true;
21+
}
22+
23+
/**
24+
* Get the validation rules that apply to the request.
25+
*
26+
* @return array
27+
*/
28+
public function rules()
29+
{
30+
$organizationId = $this->route('organizationId');
31+
32+
return [
33+
'description' => 'string|required',
34+
'amount' => 'numeric|required',
35+
'status' => ['string', 'required', Rule::in(Transaction::$validStatuses)],
36+
'occurredOn' => 'date_format:Y-m-d\TH:i:sP|required',
37+
'subscriptionId' => ['string', 'required', new ValidSubscription($organizationId)],
38+
'budgetId' => ['string', 'required', new ValidOrganizationBudget($organizationId)],
39+
'externalReference' => 'nullable|string',
40+
];
41+
}
42+
}

app/Models/Organization.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,19 @@ public function roles()
7474
return $this->hasMany(OrganizationRole::class);
7575
}
7676

77+
/*
78+
* Get the transactions of the organization.
79+
*/
80+
public function transactions()
81+
{
82+
return $this->hasMany(Transaction::class);
83+
}
84+
7785
/**
7886
* Get all of the subscriptions for the organization.
7987
*/
8088
public function subscriptions()
8189
{
82-
return $this->hasManyThrough(Subscription::class, OrganizationBudget::class);
90+
return $this->hasMany(Subscription::class);
8391
}
8492
}

app/Models/Subscription.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,12 @@ public function user()
6161
{
6262
return $this->belongsTo(User::class);
6363
}
64+
65+
/**
66+
* Get the organization this subscription belongs to.
67+
*/
68+
public function organization()
69+
{
70+
return $this->belongsTo(Organization::class);
71+
}
6472
}

app/Models/Transaction.php

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use App\Traits\UuidModel;
6+
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Database\Eloquent\SoftDeletes;
8+
9+
class Transaction extends Model
10+
{
11+
use SoftDeletes;
12+
13+
use UuidModel;
14+
15+
/**
16+
* @var string
17+
*/
18+
const OPEN = 'open';
19+
20+
/**
21+
* @var string
22+
*/
23+
const INVISIBLE = 'invisible';
24+
25+
/**
26+
* @var string
27+
*/
28+
const APPROVED = 'approved';
29+
30+
/**
31+
* @var string
32+
*/
33+
const REJECTED = 'rejected';
34+
35+
/**
36+
* @var array
37+
*/
38+
public static $validStatuses = [self::OPEN, self::APPROVED, self::INVISIBLE, self::REJECTED];
39+
40+
/**
41+
* The attributes that are mass assignable.
42+
*
43+
* @var array
44+
*/
45+
protected $fillable = [
46+
'status', 'description', 'occurred_on', 'amount', 'external_reference',
47+
];
48+
49+
/**
50+
* Validation rules.
51+
*
52+
* @var array
53+
*/
54+
public static $rules = [
55+
'status' => 'string|required',
56+
'description' => 'string|required',
57+
'requested_on' => 'datetime|required',
58+
'occurred_on' => 'datetime|required',
59+
'amount' => 'numeric|required',
60+
'external_reference' => 'nullable|string',
61+
];
62+
63+
/**
64+
* Get the budget this subscription belongs to.
65+
*/
66+
public function organizationBudget()
67+
{
68+
return $this->belongsTo(OrganizationBudget::class);
69+
}
70+
71+
/**
72+
* Get the budget this subscription belongs to.
73+
*/
74+
public function organization()
75+
{
76+
return $this->belongsTo(Organization::class);
77+
}
78+
79+
/**
80+
* Get the budget this subscription belongs to.
81+
*/
82+
public function subscription()
83+
{
84+
return $this->belongsTo(Subscription::class);
85+
}
86+
}

app/Organizations/Budgets/Rules/ValidOrganizationBudget.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function passes($attribute, $value)
3434
{
3535
$budget = OrganizationBudget::find($value);
3636

37-
return $budget->organization_id === $this->organizationId;
37+
return empty($budget) ? false : ($budget->organization_id === $this->organizationId);
3838
}
3939

4040
/**

app/Organizations/Rules/ValidOrganizationService.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,23 @@ public function __construct(string $organizationId)
2424
* Determine if the validation rule passes.
2525
*
2626
* @param string $attribute
27-
* @param mixed $value
27+
* @param string $value
2828
*
2929
* @return bool
3030
*/
3131
public function passes($attribute, $value)
3232
{
33-
$count = OrganizationService::where('organization_id', $this->organizationId)
33+
if (is_array($value)) {
34+
$count = OrganizationService::where('organization_id', $this->organizationId)
3435
->whereIn('service', $value)
3536
->count();
3637

37-
return $count === count($value);
38+
return $count === count($value);
39+
}
40+
41+
return !empty(OrganizationService::where('organization_id', $this->organizationId)
42+
->where('service', $value)
43+
->get());
3844
}
3945

4046
/**

0 commit comments

Comments
 (0)