Skip to content

Commit

Permalink
[Slack][Equipment Authorization] Refactor batch authorization into qu…
Browse files Browse the repository at this point in the history
…euable action(s) (#48)

* Add AddUserMembership Action

* Add BatchAuthorizeEquipment Action

* Use BatchAuthorizeEquipment in `EquipmentAuthorization->handle`
  • Loading branch information
chungl authored Jan 18, 2024
1 parent 0c418b5 commit d518cb0
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 24 deletions.
33 changes: 33 additions & 0 deletions app/Actions/WordPress/AddUserMembership.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace App\Actions\WordPress;

use App\External\WooCommerce\Api\WooCommerceApi;
use Spatie\QueueableAction\QueueableAction;
use Illuminate\Support\Facades\Log;

class AddUserMembership
{
use QueueableAction;

/**
* Create a new action instance.
*
* @return void
*/
public function __construct(WooCommerceApi $wpApi)
{
$this->wpApi = $wpApi;
}

/**
* Execute the action.
*
* @return mixed
*/
public function execute($actorId, $memberId, $planId)
{
$this->wpApi->members->addMembership($memberId, $planId);
Log::info('AddUserMembership: Customer '.$actorId.' granted user plan id '.$planId.' to Customer '.$memberId);
}
}
66 changes: 66 additions & 0 deletions app/Actions/WordPress/BatchAuthorizeEquipment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace App\Actions\WordPress;

use App\Models\Customer;
use App\Actions\WordPress\AddUserMembershipo;
use Illuminate\Support\Facades\Log;

class BatchAuthorizeEquipment
{
/**
* Create a new action instance.
*
* @return void
*/
public function __construct(
AddUserMembership $addUserMembership
)
{
$this->authorizeAction = $addUserMembership;
}

/**
* Execute the action.
* @param Customer $trainer - The person who is submitting the authorization
* @param Collection<Customer> $members - The members to be authorized on the equipment
* @param Collection<TrainableEquipment> $equipment - The pieces of equipment for which the members will be authorized
* @param Boolean $makeTrainers - Default false. Whether the members should be authorized to trainers others on this equipment.
* @return mixed
*/
public function execute(Customer $trainer, $members, $equipment, $makeTrainers=false)
{
// Validate that trainer is an authorized trainer for all equipment
foreach($equipment as $e) {
if (!$trainer->hasMembership($e->trainer_plan_id)) {
Log::info('BatchAuthorizeEquipment: Customer attempted to submit authorization without trainer role. '.json_encode([
'trainer_id' => $trainer->id,
'equipment_id' => $e->id
]));

throw new \Exception('NotAuthorized');
}
}

Log::info('BatchAuthorizeEquipment: Submitting batch: '.json_encode([
'trainer_id' => $trainer->id,
'member_ids' => $members->map(fn($member) => $member->id),
'equipment_ids' => $equipment->map(fn($e) => $e->id),
'make_trainers' => $makeTrainers
]));

$planIds = $equipment->map(fn($e) => $e->user_plan_id);

if ($makeTrainers) {
$planIds = $planIds->concat($equipment->map(fn ($e) => $e->trainer_plan_id));
}

foreach($members->crossjoin($planIds) as [$member, $planId]){
if ($member->hasMembership($planId)) {
continue;
}
$this->authorizeAction->onQueue()->execute($trainer->id, $member->id, $planId);
}
return 'ok';
}
}
45 changes: 21 additions & 24 deletions app/External/Slack/Modals/EquipmentAuthorization.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use SlackPhp\BlockKit\Partials\Option;
use SlackPhp\BlockKit\Surfaces\Modal;
use Illuminate\Support\Collection;
use App\Actions\WordPress\BatchAuthorizeEquipment;

class EquipmentAuthorization implements ModalInterface
{
Expand Down Expand Up @@ -84,7 +85,6 @@ public static function handle(SlackRequest $request)
}

$state = self::getStateValues($request);
$makeUsers = true;
$makeTrainers = ! is_null($state[self::TRAINER_CHECK][self::TRAINER_CHECK] ?? null);

/** @var WooCommerceApi $api */
Expand All @@ -93,26 +93,19 @@ public static function handle(SlackRequest $request)
$selectedEquipment = self::equipmentFromState($state);
$selectedMembers = self::peopleFromState($state);

$actorId = $request->customer()->id;

foreach($selectedMembers->crossJoin($selectedEquipment)->all() as [$person, $equipment]) {
if (!$person->hasMembership($equipment->user_plan_id)) {
Log::info('EquipmentAuthorization: Customer '.$actorId.' authorized Customer '.$person->id.' to use equipment under plan id '.$equipment->user_plan_id);
$api->members->addMembership($person->id, $equipment->user_plan_id);
}

if ($makeTrainers && !$person->hasMembership($equipment->trainer_plan_id)) {
Log::info('EquipmentAuthorization: Customer '.$actorId.' authorized Customer '.$person->id.' to train on equipment with plan id '.$equipment->trainer_plan_id);
$api->members->addMembership($person->id, $equipment->trainer_plan_id);
$actor = $request->customer();

try {
app()->make(BatchAuthorizeEquipment::class)->execute($actor, $selectedMembers, $selectedEquipment, $makeTrainers);
} catch (\Exception $e) {
if ($e->getMessage() == 'NotAuthorized') {
return response()->json([
'response_action' => 'errors',
'errors' => [self::EQUIPMENT_DROPDOWN => "You don't have permission to authorize members for this equipment."]
]);
}
}


if (! $makeTrainers && ! $makeUsers) {
return (new FailureModal('Neither user nor trainer appear to have been selected. Try again?'))
->update();
}

// TODO actually check error before sending success
return (new SuccessModal())->update();
}
Expand All @@ -132,16 +125,20 @@ public static function getBlockActions(): array

public static function equipmentFromState($state): Collection
{
return collect($state[self::EQUIPMENT_DROPDOWN][self::EQUIPMENT_DROPDOWN] ?? [])
-> map(fn($formValue) => str_replace('equipment-', '', $formValue))
-> map(fn($equipmentId) => TrainableEquipment::find($equipmentId));
$equipmentIds = array_map(
fn($formValue) => str_replace('equipment-', '', $formValue),
$state[self::EQUIPMENT_DROPDOWN][self::EQUIPMENT_DROPDOWN] ?? []
);
return TrainableEquipment::whereIn('id', $equipmentIds)->get();
}

public static function peopleFromState($state): Collection
{
return collect($state[self::PERSON_DROPDOWN][self::PERSON_DROPDOWN] ?? [])
-> map(fn($formValue) => str_replace('customer-', '', $formValue))
-> map(fn($customerId) => Customer::find($customerId));
$customerIds = array_map(
fn($formValue) => str_replace('customer-', '', $formValue),
$state[self::PERSON_DROPDOWN][self::PERSON_DROPDOWN] ?? []
);
return Customer::with('memberships')->whereIn('id', $customerIds)->get();
}

public static function getOptions(SlackRequest $request)
Expand Down

0 comments on commit d518cb0

Please sign in to comment.