Add Backend for displaying memberships
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
878de3f566
commit
66b6a549c3
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Lib\Data;
|
||||||
|
|
||||||
|
use Spatie\LaravelData\Normalizers\Normalizer;
|
||||||
|
use App\Lib\Normalizers\DateNormalizer;
|
||||||
|
use Spatie\LaravelData\Data;
|
||||||
|
use Spatie\LaravelData\Attributes\WithTransformer;
|
||||||
|
use App\Lib\Transformers\DateTransformer;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class DateData extends Data
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
#[WithTransformer(DateTransformer::class)]
|
||||||
|
public Carbon $raw,
|
||||||
|
public string $human,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, class-string<Normalizer>>
|
||||||
|
*/
|
||||||
|
public static function normalizers(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
DateNormalizer::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Lib\Data;
|
||||||
|
|
||||||
|
use Spatie\LaravelData\Data;
|
||||||
|
|
||||||
|
class RecordData extends Data {
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public int $id,
|
||||||
|
public string $name,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Lib\Normalizers;
|
||||||
|
|
||||||
|
use Spatie\LaravelData\Normalizers\Normalizer;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class DateNormalizer implements Normalizer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function normalize(mixed $value): ?array
|
||||||
|
{
|
||||||
|
if (!$value instanceof Carbon) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'raw' => $value,
|
||||||
|
'human' => $value->format('d.m.Y'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Lib\Transformers;
|
||||||
|
|
||||||
|
use Spatie\LaravelData\Transformers\Transformer;
|
||||||
|
use Spatie\LaravelData\Support\DataProperty;
|
||||||
|
use Spatie\LaravelData\Support\Transformation\TransformationContext;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class DateTransformer implements Transformer
|
||||||
|
{
|
||||||
|
public function transform(DataProperty $property, mixed $value, TransformationContext $context): string
|
||||||
|
{
|
||||||
|
return Carbon::parse($value)->format('Y-m-d');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Member\Data;
|
||||||
|
|
||||||
|
use Spatie\LaravelData\Data;
|
||||||
|
use App\Lib\Data\DateData;
|
||||||
|
use App\Lib\Data\RecordData;
|
||||||
|
use App\Member\Membership;
|
||||||
|
|
||||||
|
class MembershipData extends Data
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public int $id,
|
||||||
|
public RecordData $activity,
|
||||||
|
public ?RecordData $subactivity,
|
||||||
|
public RecordData $group,
|
||||||
|
public ?DateData $promisedAt,
|
||||||
|
public DateData $from,
|
||||||
|
public bool $isActive,
|
||||||
|
public array $links,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public static function fromModel(Membership $membership): static
|
||||||
|
{
|
||||||
|
return static::factory()->withoutMagicalCreation()->from([
|
||||||
|
'id' => $membership->id,
|
||||||
|
'activity' => $membership->activity,
|
||||||
|
'subactivity' => $membership->subactivity,
|
||||||
|
'isActive' => $membership->isActive(),
|
||||||
|
'from' => $membership->from,
|
||||||
|
'group' => $membership->group,
|
||||||
|
'promisedAt' => $membership->promised_at,
|
||||||
|
'links' => [
|
||||||
|
'update' => route('membership.update', $membership),
|
||||||
|
'destroy' => route('membership.destroy', $membership),
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||||
use Lorisleiva\Actions\Concerns\AsAction;
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
|
|
||||||
class IndexAction
|
class MemberIndexAction
|
||||||
{
|
{
|
||||||
use AsAction;
|
use AsAction;
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Membership\Actions;
|
||||||
|
|
||||||
|
use App\Member\Data\MembershipData;
|
||||||
|
use App\Member\Membership;
|
||||||
|
use Inertia\Inertia;
|
||||||
|
use Inertia\Response;
|
||||||
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
|
use Spatie\LaravelData\PaginatedDataCollection;
|
||||||
|
|
||||||
|
class MembershipIndexAction
|
||||||
|
{
|
||||||
|
use AsAction;
|
||||||
|
|
||||||
|
public function asController(): Response
|
||||||
|
{
|
||||||
|
return Inertia::render(
|
||||||
|
'membership/Index',
|
||||||
|
MembershipData::collect(Membership::orderByRaw('member_id, activity_id, subactivity_id')->paginate(20), PaginatedDataCollection::class)->wrap('data')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,7 +73,9 @@ use App\Membership\Actions\IndexAction as MembershipIndexAction;
|
||||||
use App\Membership\Actions\ListForGroupAction;
|
use App\Membership\Actions\ListForGroupAction;
|
||||||
use App\Membership\Actions\MassListAction;
|
use App\Membership\Actions\MassListAction;
|
||||||
use App\Membership\Actions\MassStoreAction;
|
use App\Membership\Actions\MassStoreAction;
|
||||||
|
use App\Membership\Actions\MemberIndexAction;
|
||||||
use App\Membership\Actions\MembershipDestroyAction;
|
use App\Membership\Actions\MembershipDestroyAction;
|
||||||
|
use App\Membership\Actions\MembershipIndexAction as ActionsMembershipIndexAction;
|
||||||
use App\Membership\Actions\MembershipStoreAction;
|
use App\Membership\Actions\MembershipStoreAction;
|
||||||
use App\Membership\Actions\MembershipUpdateAction;
|
use App\Membership\Actions\MembershipUpdateAction;
|
||||||
use App\Payment\SubscriptionController;
|
use App\Payment\SubscriptionController;
|
||||||
|
@ -140,13 +142,14 @@ Route::group(['middleware' => 'auth:web'], function (): void {
|
||||||
Route::get('/member/{member}/invoice-position', PaymentPositionIndexAction::class)->name('member.invoice-position.index');
|
Route::get('/member/{member}/invoice-position', PaymentPositionIndexAction::class)->name('member.invoice-position.index');
|
||||||
|
|
||||||
// --------------------------------- membership --------------------------------
|
// --------------------------------- membership --------------------------------
|
||||||
Route::get('/member/{member}/membership', MembershipIndexAction::class)->name('member.membership.index');
|
Route::get('/member/{member}/membership', MemberIndexAction::class)->name('member.membership.index');
|
||||||
Route::post('/member/{member}/membership', MembershipStoreAction::class)->name('member.membership.store');
|
Route::post('/member/{member}/membership', MembershipStoreAction::class)->name('member.membership.store');
|
||||||
Route::patch('/membership/{membership}', MembershipUpdateAction::class)->name('membership.update');
|
Route::patch('/membership/{membership}', MembershipUpdateAction::class)->name('membership.update');
|
||||||
Route::delete('/membership/{membership}', MembershipDestroyAction::class)->name('membership.destroy');
|
Route::delete('/membership/{membership}', MembershipDestroyAction::class)->name('membership.destroy');
|
||||||
Route::post('/api/membership/member-list', ListForGroupAction::class)->name('membership.member-list');
|
Route::post('/api/membership/member-list', ListForGroupAction::class)->name('membership.member-list');
|
||||||
Route::post('/api/membership/masslist', MassStoreAction::class)->name('membership.masslist.store');
|
Route::post('/api/membership/masslist', MassStoreAction::class)->name('membership.masslist.store');
|
||||||
Route::get('/membership/masslist', MassListAction::class)->name('membership.masslist.index');
|
Route::get('/membership/masslist', MassListAction::class)->name('membership.masslist.index');
|
||||||
|
Route::get('/membership', ActionsMembershipIndexAction::class)->name('membership.index');
|
||||||
|
|
||||||
// ----------------------------------- group ----------------------------------
|
// ----------------------------------- group ----------------------------------
|
||||||
Route::get('/group', GroupIndexAction::class)->name('group.index');
|
Route::get('/group', GroupIndexAction::class)->name('group.index');
|
||||||
|
|
|
@ -63,7 +63,7 @@ it('cannot create membership when activity and subactivity doesnt belong togethe
|
||||||
])->assertJsonValidationErrors(['activity_id' => 'Tätigkeit ist nicht vorhanden.']);
|
])->assertJsonValidationErrors(['activity_id' => 'Tätigkeit ist nicht vorhanden.']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('testItDeletesAMembership', function() {
|
it('deletes a membership', function() {
|
||||||
MembershipDestroyAction::partialMock()->shouldReceive('handle')->once();
|
MembershipDestroyAction::partialMock()->shouldReceive('handle')->once();
|
||||||
MembershipStoreAction::partialMock()->shouldReceive('handle')->never();
|
MembershipStoreAction::partialMock()->shouldReceive('handle')->never();
|
||||||
ResyncAction::partialMock()->shouldReceive('handle')->once();
|
ResyncAction::partialMock()->shouldReceive('handle')->once();
|
||||||
|
@ -73,7 +73,7 @@ it('testItDeletesAMembership', function() {
|
||||||
MassStoreAction::run($member->memberships->first()->group, $member->memberships->first()->activity, $member->memberships->first()->subactivity, []);
|
MassStoreAction::run($member->memberships->first()->group, $member->memberships->first()->activity, $member->memberships->first()->subactivity, []);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('testItRollsbackWhenDeletionFails', function() {
|
it('rolls back when deletion fails', function() {
|
||||||
app(MembershipFake::class)
|
app(MembershipFake::class)
|
||||||
->shows(3, ['id' => 55])
|
->shows(3, ['id' => 55])
|
||||||
->shows(3, ['id' => 56])
|
->shows(3, ['id' => 56])
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Membership;
|
||||||
|
|
||||||
|
use App\Activity;
|
||||||
|
use App\Group;
|
||||||
|
use App\Member\Data\MembershipData;
|
||||||
|
use App\Member\Member;
|
||||||
|
use App\Member\Membership;
|
||||||
|
use App\Subactivity;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Inertia\Testing\AssertableInertia as Assert;
|
||||||
|
|
||||||
|
uses(DatabaseTransactions::class);
|
||||||
|
|
||||||
|
mutates(MembershipData::class);
|
||||||
|
|
||||||
|
it('lists memberships of users', function () {
|
||||||
|
$this->login()->loginNami()->withoutExceptionHandling();
|
||||||
|
$activity = Activity::factory()
|
||||||
|
->hasAttached(Subactivity::factory()->name('SubAct'))
|
||||||
|
->name('Act')
|
||||||
|
->create();
|
||||||
|
$group = Group::factory()->name('GG')->create();
|
||||||
|
$member = Member::factory()->defaults()
|
||||||
|
->for($group)
|
||||||
|
->has(Membership::factory()->for($activity)->for($activity->subactivities->first())->for($group))
|
||||||
|
->male()
|
||||||
|
->name('Max Muster')
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$activity->subactivities()->first();
|
||||||
|
$this->callFilter('membership.index', [])
|
||||||
|
->assertInertia(fn(Assert $page) => $page
|
||||||
|
->has('data.0', fn(Assert $page) => $page
|
||||||
|
->where('activity.name', 'Act')
|
||||||
|
->where('subactivity.name', 'SubAct')
|
||||||
|
->where('group.name', 'GG')
|
||||||
|
->where('promisedAt', null)
|
||||||
|
->where('links.update', route('membership.update', $member->memberships->first()))
|
||||||
|
->where('links.destroy', route('membership.destroy', $member->memberships->first()))
|
||||||
|
->etc()
|
||||||
|
)->has('meta', fn (Assert $page) => $page
|
||||||
|
->where('current_page', 1)
|
||||||
|
->etc()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue