Skip to content

Commit

Permalink
Merge pull request laravel#534 from eurides-eu/implement-subscription…
Browse files Browse the repository at this point in the history
…-approval-page

Finished service approval UI + backend
  • Loading branch information
Lumiware authored Feb 25, 2019
2 parents 9757a28 + bcd586f commit cbc7522
Show file tree
Hide file tree
Showing 23 changed files with 592 additions and 214 deletions.
88 changes: 75 additions & 13 deletions app/Http/Controllers/ApproverPagesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,82 @@

namespace App\Http\Controllers;

use App\Models\Subscription;
use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class ApproverPagesController extends Controller
{
public function getServiceRequests()
public function getServiceRequests(Request $request)
{
if ($this->checkApprover()) {
return view('pages.approver.approve-service-requests');
// Get budgets for which the logged in user is the approver
$approver = Auth::user();
$selectedSubscription = null;

// Denotes whether a success alert should be shown, false by default
$success = '';
$previousSubscriptionName = '';

// First, check if the previous operation was successful
if ($request->query('operation')) {
$success = $request->query('operation');
$previousSubscriptionName = Subscription::findOrFailForOrganization($approver->organization->id, $request->query('previousSubscriptionId'))->internal_reference;
}

// Get budgets managed by user
$managedBudgetIds = $approver->approverBudgets()->get()->pluck('id');

// Get 10 oldest subscriptions across all managed budgets
$subscriptionsToRate = Subscription::query()
->whereIn('organization_budget_id', $managedBudgetIds)
->where('status', Subscription::TO_BE_APPROVED)
->orderBy('requested_on', 'ASC')
->take(10)
->get();

// Optional request parameter indicating the subscription that needs to be evaluated
$selectedSubscriptionId = $request->get('subscriptionId');

if ($selectedSubscriptionId) {
// Get info about selected subscription
$selectedSubscription = Subscription::findOrFailForOrganization($approver->organization->id, $selectedSubscriptionId);
// If the subscription is not included in the list, assign the first trip of the list as selected
if (!$subscriptionsToRate->contains('id', $selectedSubscriptionId)) {
$selectedSubscription = $subscriptionsToRate->first();
}
} else {
// No selected transaction, assign first transaction as selected, if available
// If the list of transactions is empty, selectedTrip gets null assigned to it
$selectedSubscription = $subscriptionsToRate->first();
}

// Get additional information for selected trip

// Budget of selected trip
$budget = null;
if ($selectedSubscription) {
$budget = $selectedSubscription->organizationBudget;
}

// Show all other active or approved subscriptions for the user
$otherSubscriptions = null;
if ($selectedSubscription) {
$otherSubscriptions = Subscription::whereUserId($selectedSubscription->user_id)
->whereIn('status', [Subscription::ACTIVE, Subscription::APPROVED])
->orderBy('end_on', 'ASC')
->get();
}

// Show 10 oldest subscriptions to be approved
return view('pages.approver.approve-service-requests')
->withSubscriptionsToRate($subscriptionsToRate)
->withSelectedSubscription($selectedSubscription)
->withBudget($budget)
->withOtherSubscriptions($otherSubscriptions)
->withSuccess($success)
->withPreviousSubscriptionName($previousSubscriptionName);
}

return $this->getUserView();
Expand All @@ -26,12 +92,12 @@ public function getTripRequests(Request $request)

// Denotes whether a success alert should be shown, false by default
$success = '';
$previousTransaction = '';
$previousTransactionName = '';

// First, check if the previous operation was successful
if ($request->query('operation')) {
$success = $request->query('operation');
$previousTransaction = $request->query('name');
$previousTransactionName = Transaction::findOrFailForOrganization($approver->organization->id, $request->query('previousTransactionId'))->description;
}

// Get budgets managed by user
Expand All @@ -50,13 +116,9 @@ public function getTripRequests(Request $request)

if ($selectedTripId) {
// Get info about selected transaction
$selectedTrip = Transaction::whereId($selectedTripId)->first();
// If the transaction is included in the list, assign the selected trip
if ($selectedTrip && $tripsToRate->contains('id', $selectedTripId)) {
$selectedTrip = Transaction::whereId($selectedTripId)->first();
}
// Otherwise, assign the first trip of the list as selected
else {
$selectedTrip = Transaction::findOrFailForOrganization($approver->organization->id, $selectedTripId);
// If the transaction is not included in the list, assign the first trip of the list as selected
if ($selectedTrip && !$tripsToRate->contains('id', $selectedTripId)) {
$selectedTrip = $tripsToRate->first();
}
} else {
Expand Down Expand Up @@ -84,14 +146,14 @@ public function getTripRequests(Request $request)
->get();
}

// Show 10 oldest transactions
// Show 10 oldest transactions to be approved
return view('pages.approver.approve-trip-requests')
->withTripsToRate($tripsToRate)
->withSelectedTrip($selectedTrip)
->withBudget($budget)
->withRecentTrips($recentTrips)
->withSuccess($success)
->withPreviousTransaction($previousTransaction);
->withPreviousTransactionName($previousTransactionName);
}

return $this->getUserView();
Expand Down
6 changes: 6 additions & 0 deletions app/Http/Controllers/ApproverSubscriptionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ public function updateSubscription(ApproverUpdateSubscriptionRequest $request, s
throw new AccessDeniedHttpException('Subscription cannot be approved by you.');
}
$subscription->status = $request->getStatus(); //request already checked if valid status.

// Set the approver for this transaction (approved or disapproved)
$subscription->approver()->associate($request->user());

$subscription->approver_motivation = $request->getApproverMotivation();

$subscription->save();

return $subscription;
Expand Down
17 changes: 12 additions & 5 deletions app/Http/Requests/Users/ApproverUpdateSubscriptionRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,23 @@
*/
class ApproverUpdateSubscriptionRequest extends FormRequest
{
/** status to set the transaction to. */
public function rules()
{
return [
'status' => ['required', 'string', Rule::in([Transaction::DISAPPROVED, Transaction::APPROVED])],
'approverMotivation' => ['nullable', 'string'],
];
}

/** status to set the subscription to. */
public function getStatus(): string
{
return $this->get('status');
}

public function rules()
/** Text shown to user why a subscription request was disapproved (or approved). */
public function getApproverMotivation()
{
return [
'status' => ['required', 'string', Rule::in([Transaction::DISAPPROVED, Transaction::APPROVED])],
];
return $this->getValidated('approverMotivation');
}
}
23 changes: 21 additions & 2 deletions app/Models/Subscription.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,24 @@
* @property string $service
* @property string $status
* @property string $organization_budget_id
* @property string $requested_on
* @property \Carbon\Carbon|null $requested_on
* @property string $user_id
* @property string|null $internal_reference
* @property \Carbon\Carbon|null $created_at
* @property \Carbon\Carbon|null $updated_at
* @property string|null $deleted_at
* @property \Carbon\Carbon|null $deleted_at
* @property \Carbon\Carbon|null $approved_at
* @property string|null $organization_id
* @property array $payload
* @property float|null $price
* @property string|null $document_id
* @property string|null $approver_id
* @property string|null $approver_motivation
* @property-read \App\Models\Organization|null $organization
* @property-read \App\Models\OrganizationBudget $organizationBudget
* @property-read \App\User $user
* @property-read \App\Models\Document|null $document
* @property-read \App\User|null $approver
*
* @method static bool|null forceDelete()
* @method static \Illuminate\Database\Query\Builder|\App\Models\Subscription onlyTrashed()
Expand Down Expand Up @@ -144,6 +148,11 @@ class Subscription extends Model implements HasDeletionPolicy
'payload' => 'array',
'start_on' => 'datetime',
'end_on' => 'datetime',
'requested_on' => 'datetime',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'approved_at' => 'datetime',
];

/**
Expand Down Expand Up @@ -189,6 +198,16 @@ public function document()
return $this->belongsTo(Document::class)->withTrashed();
}

/**
* Get the user who is the approver for this subscription.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function approver()
{
return $this->belongsTo(User::class)->withTrashed();
}

/**
* @param $organizationId
* @param $subscriptionId
Expand Down
8 changes: 5 additions & 3 deletions app/Models/Transaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
* @property \Carbon\Carbon|null $created_at
* @property \Carbon\Carbon|null $updated_at
* @property \Carbon\Carbon|null $approved_at
* @property string|null $deleted_at
* @property \Carbon\Carbon|null $deleted_at
* @property string|null $document_id
* @property string|null $approver_id
* @property string|null $approver_motivation
Expand Down Expand Up @@ -122,8 +122,10 @@ class Transaction extends Model implements HasDeletionPolicy
*/
protected $casts = [
'occurred_on' => 'datetime',
'created_on' => 'datetime',
'updated_on' => 'datetime',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'approved_at' => 'datetime',
];

/**
Expand Down
2 changes: 2 additions & 0 deletions app/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Subscriptions\Events\SubscriptionStatusChangedEvent;
use App\Subscriptions\Events\SubscriptionStatusChangedObserver;
use App\Transactions\EventHandlers\MailTransactionStatusOnChangedHandler;
use App\Transactions\Events\EnsureSubscriptionApprovedAtColumnSet;
use App\Transactions\Events\EnsureTransactionApprovedAtColumnSet;
use App\Transactions\Events\InstantAutoApproveTransactionObserver;
use App\Transactions\Events\TransactionStatusChangedEvent;
Expand Down Expand Up @@ -44,6 +45,7 @@ public function boot()
Transaction::observe(TransactionStatusChangedObserver::class);
Transaction::observe(EnsureTransactionApprovedAtColumnSet::class);
Subscription::observe(SubscriptionStatusChangedObserver::class);
Subscription::observe(EnsureSubscriptionApprovedAtColumnSet::class);
parent::boot();
}
}
26 changes: 26 additions & 0 deletions app/Subscriptions/Events/EnsureSubscriptionApprovedAtColumnSet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace App\Transactions\Events;

use App\Models\Subscription;
use Illuminate\Support\Carbon;

class EnsureSubscriptionApprovedAtColumnSet
{
public function creating(Subscription $model)
{
$this->check($model);
}

public function updating(Subscription $model)
{
$this->check($model);
}

private function check(Subscription $subscription)
{
if (Subscription::APPROVED === $subscription->status && null === $subscription->approved_at) {
$subscription->approved_at = Carbon::now();
}
}
}
4 changes: 4 additions & 0 deletions app/Subscriptions/Transformers/SubscriptionTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ public function transform(Subscription $subscription)
'payload' => $subscription->payload,
'userId' => $subscription->user_id,
'budgetId' => $subscription->organization_budget_id,
'documentId' => $subscription->document_id,
'approverMotivation' => $subscription->approver_motivation,
'approvedAt' => $subscription->approved_at,
'approverId' => $subscription->approver_id,
];
}

Expand Down
11 changes: 11 additions & 0 deletions app/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
* @property-read \App\Models\Organization|null $organization
* @property-read \App\Models\OrganizationRole|null $role
* @property-read \App\Models\Subscription[]|\Illuminate\Database\Eloquent\Collection $subscriptions
* @property-read \App\Models\Transaction[]|\Illuminate\Database\Eloquent\Collection $subscriptionsApprovedByMe
* @property-read \App\Models\Transaction[]|\Illuminate\Database\Eloquent\Collection $transactionsApprovedByMe
* @property-read \Illuminate\Database\Eloquent\Collection|\Laravel\Passport\Token[] $tokens
* @property-read \App\Models\OrganizationBudget[]|\Illuminate\Database\Eloquent\Collection $isApproverFor
Expand Down Expand Up @@ -166,6 +167,16 @@ public function subscriptions()
return $this->hasMany(Subscription::class);
}

/**
* Get subscriptions approved by user.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function subscriptionsApprovedByMe()
{
return $this->hasMany(Subscription::class, 'approver_id');
}

/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddApproverMotivationAndDateAndIdColumnToSubscriptionsTable extends Migration
{
/**
* Run the migrations.
*/
public function up()
{
Schema::table('subscriptions', function (Blueprint $table) {
$table->timestamp('approved_at')->nullable()->after('deleted_at');
$table->string('approver_id')->after('document_id')->nullable();
$table->string('approver_motivation')->nullable();
});
}

/**
* Reverse the migrations.
*/
public function down()
{
Schema::table('subscriptions', function (Blueprint $table) {
$table->dropColumn('approver_motivation');
$table->dropColumn('approver_id');
$table->dropColumn('approved_at');
});
}
}
Loading

0 comments on commit cbc7522

Please sign in to comment.