diff --git a/app/Member/Membership.php b/app/Member/Membership.php index 2010b938..0bb0d86d 100644 --- a/app/Member/Membership.php +++ b/app/Member/Membership.php @@ -16,7 +16,7 @@ class Membership extends Model { use HasFactory; - public $fillable = ['subactivity_id', 'activity_id', 'group_id', 'member_id', 'nami_id', 'from']; + public $fillable = ['subactivity_id', 'activity_id', 'group_id', 'member_id', 'nami_id', 'from', 'promised_at']; public function activity(): BelongsTo { diff --git a/app/Membership/Actions/MembershipStoreAction.php b/app/Membership/Actions/MembershipStoreAction.php index f48b5273..6919c98f 100644 --- a/app/Membership/Actions/MembershipStoreAction.php +++ b/app/Membership/Actions/MembershipStoreAction.php @@ -7,6 +7,7 @@ use App\Member\Member; use App\Member\Membership; use App\Setting\NamiSettings; use App\Subactivity; +use Carbon\Carbon; use Illuminate\Http\RedirectResponse; use Illuminate\Validation\Rule; use Illuminate\Validation\Rules\In; @@ -20,7 +21,7 @@ class MembershipStoreAction { use AsAction; - public function handle(Member $member, Activity $activity, ?Subactivity $subactivity, NamiSettings $settings): Membership + public function handle(Member $member, Activity $activity, ?Subactivity $subactivity, ?Carbon $promisedAt, NamiSettings $settings): Membership { $from = now()->startOfDay(); @@ -38,6 +39,7 @@ class MembershipStoreAction $membership = $member->memberships()->create([ 'activity_id' => $activity->id, 'subactivity_id' => $subactivity ? $subactivity->id : null, + 'promised_at' => $promisedAt, ...['nami_id' => $namiId, 'group_id' => $member->group->id, 'from' => $from], ]); @@ -56,6 +58,7 @@ class MembershipStoreAction return [ 'activity_id' => ['bail', 'required', 'exists:activities,id'], 'subactivity_id' => $subactivityRule, + 'promised_at' => ['nullable', 'date'], ]; } @@ -76,6 +79,7 @@ class MembershipStoreAction $member, Activity::find($request->activity_id), $request->subactivity_id ? Subactivity::find($request->subactivity_id) : null, + $request->promised_at ? Carbon::parse($request->promised_at) : null, $settings, ); diff --git a/app/Membership/Actions/MembershipUpdateAction.php b/app/Membership/Actions/MembershipUpdateAction.php new file mode 100644 index 00000000..72c3ced6 --- /dev/null +++ b/app/Membership/Actions/MembershipUpdateAction.php @@ -0,0 +1,69 @@ +startOfDay(); + + $membership->update([ + 'activity_id' => $activity->id, + 'subactivity_id' => $subactivity ? $subactivity->id : null, + 'promised_at' => $promisedAt, + ]); + + return $membership; + } + + /** + * @return array> + */ + public function rules(): array + { + $subactivityRule = request()->activity_id ? ['nullable', Rule::exists('activity_subactivity', 'subactivity_id')->where('activity_id', request()->activity_id)] : ['nullable']; + + return [ + 'activity_id' => ['bail', 'required', 'exists:activities,id'], + 'subactivity_id' => $subactivityRule, + 'promised_at' => ['nullable', 'date'], + ]; + } + + /** + * @return array + */ + public function getValidationAttributes(): array + { + return [ + 'activity_id' => 'Tätigkeit', + 'subactivity_id' => 'Untertätigkeit', + ]; + } + + public function asController(Member $member, Membership $membership, ActionRequest $request): RedirectResponse + { + $this->handle( + $membership, + Activity::find($request->activity_id), + $request->subactivity_id ? Subactivity::find($request->subactivity_id) : null, + $request->promised_at ? Carbon::parse($request->promised_at) : null, + ); + + return redirect()->back(); + } +} diff --git a/app/Membership/MembershipResource.php b/app/Membership/MembershipResource.php index 2e060900..b0faf1a8 100644 --- a/app/Membership/MembershipResource.php +++ b/app/Membership/MembershipResource.php @@ -25,6 +25,7 @@ class MembershipResource extends JsonResource 'subactivity_id' => $this->subactivity_id, 'subactivity_name' => $this->subactivity?->name, 'human_date' => $this->created_at->format('d.m.Y'), + 'promised_at' => $this->promised_at, ]; } } diff --git a/database/factories/Member/MembershipFactory.php b/database/factories/Member/MembershipFactory.php index e2c213eb..bb419d38 100644 --- a/database/factories/Member/MembershipFactory.php +++ b/database/factories/Member/MembershipFactory.php @@ -6,6 +6,7 @@ use App\Activity; use App\Group; use App\Member\Membership; use App\Subactivity; +use Carbon\Carbon; use Illuminate\Database\Eloquent\Factories\Factory; /** @@ -25,6 +26,7 @@ class MembershipFactory extends Factory return [ 'group_id' => Group::factory()->createOne()->id, 'from' => now()->subMonths(3), + 'promised_at' => null, ]; } @@ -43,4 +45,11 @@ class MembershipFactory extends Factory return $instance; } + + public function promise(Carbon $value): self + { + return $this->state([ + 'promised_at' => $value->format('Y-m-d'), + ]); + } } diff --git a/database/migrations/2022_12_11_192600_create_memberships_has_promise_column.php b/database/migrations/2022_12_11_192600_create_memberships_has_promise_column.php new file mode 100644 index 00000000..d473d80a --- /dev/null +++ b/database/migrations/2022_12_11_192600_create_memberships_has_promise_column.php @@ -0,0 +1,28 @@ +date('promised_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + } +}; diff --git a/resources/js/views/member/MemberMemberships.vue b/resources/js/views/member/MemberMemberships.vue index c246b332..9a3adbdc 100644 --- a/resources/js/views/member/MemberMemberships.vue +++ b/resources/js/views/member/MemberMemberships.vue @@ -17,6 +17,7 @@ :options="activities" v-model="single.activity_id" label="Tätigkeit" + size="sm" required > + + diff --git a/routes/web.php b/routes/web.php index 41a67b8b..0d9ef488 100644 --- a/routes/web.php +++ b/routes/web.php @@ -12,6 +12,7 @@ use App\Member\Controllers\MemberResyncController; use App\Member\MemberController; use App\Membership\Actions\MembershipDestroyAction; use App\Membership\Actions\MembershipStoreAction; +use App\Membership\Actions\MembershipUpdateAction; use App\Payment\AllpaymentController; use App\Payment\PaymentController; use App\Payment\SendpaymentController; @@ -36,6 +37,7 @@ Route::group(['middleware' => 'auth:web'], function (): void { Route::get('/sendpayment', [SendpaymentController::class, 'create'])->name('sendpayment.create'); Route::get('/sendpayment/pdf', [SendpaymentController::class, 'send'])->name('sendpayment.pdf'); Route::post('/member/{member}/membership', MembershipStoreAction::class)->name('membership.store'); + Route::patch('/member/{member}/membership/{membership}', MembershipUpdateAction::class)->name('membership.store'); Route::delete('/member/{member}/membership/{membership}', MembershipDestroyAction::class)->name('membership.destroy'); Route::resource('member.course', CourseController::class); Route::get('/member/{member}/efz', ShowEfzDocumentAction::class)->name('efz'); diff --git a/tests/Feature/Member/ShowTest.php b/tests/Feature/Member/ShowTest.php index b8309fa7..b702f6d6 100644 --- a/tests/Feature/Member/ShowTest.php +++ b/tests/Feature/Member/ShowTest.php @@ -33,7 +33,7 @@ class ShowTest extends TestCase $this->withoutExceptionHandling()->login()->loginNami(); $member = Member::factory() ->defaults() - ->has(Membership::factory()->in('€ LeiterIn', 5, 'Jungpfadfinder', 88)->state(['created_at' => '2022-11-19 05:00:00'])) + ->has(Membership::factory()->promise(now())->in('€ LeiterIn', 5, 'Jungpfadfinder', 88)->state(['created_at' => '2022-11-19 05:00:00'])) ->has(Payment::factory()->notPaid()->nr('2019')->subscription('Free', 1050)) ->for(Gender::factory()->name('Männlich')) ->for(Region::factory()->name('NRW')) @@ -108,6 +108,7 @@ class ShowTest extends TestCase 'subactivity_name' => 'Jungpfadfinder', 'id' => $member->memberships->first()->id, 'human_date' => '19.11.2022', + 'promised_at' => now()->format('Y-m-d'), ], $response, 'data.memberships.0'); $this->assertInertiaHas([ 'organizer' => 'DPSG', diff --git a/tests/Feature/Membership/StoreTest.php b/tests/Feature/Membership/StoreTest.php index 1b07ce9e..a4fa79de 100644 --- a/tests/Feature/Membership/StoreTest.php +++ b/tests/Feature/Membership/StoreTest.php @@ -42,7 +42,7 @@ class StoreTest extends TestCase $response = $this->from('/member')->post( "/member/{$member->id}/membership", - MembershipRequestFactory::new()->in($activity, $activity->subactivities->first())->create() + MembershipRequestFactory::new()->promise(now())->in($activity, $activity->subactivities->first())->create() ); $response->assertRedirect('/member'); @@ -52,6 +52,7 @@ class StoreTest extends TestCase 'activity_id' => $activity->id, 'subactivity_id' => $activity->subactivities->first()->id, 'nami_id' => 133, + 'promised_at' => now()->format('Y-m-d'), ]); app(MembershipFake::class)->assertCreated(6, [ 'untergliederungId' => 4, diff --git a/tests/Feature/Membership/UpdateTest.php b/tests/Feature/Membership/UpdateTest.php new file mode 100644 index 00000000..3ad327e5 --- /dev/null +++ b/tests/Feature/Membership/UpdateTest.php @@ -0,0 +1,52 @@ +login()->loginNami(); + } + + public function testItCreatesAMembership(): void + { + $this->withoutExceptionHandling(); + $activity = Activity::factory()->hasAttached(Subactivity::factory())->create(); + $member = Member::factory() + ->defaults() + ->has(Membership::factory()->for($activity)->for($activity->subactivities->first())) + ->for(Group::factory()->inNami(1400)) + ->inNami(6) + ->create(); + $membership = $member->memberships->first(); + + $response = $this->from('/member')->patch( + "/member/{$member->id}/membership/{$membership->id}", + MembershipRequestFactory::new()->promise(now())->in($membership->activity, $membership->subactivity)->create() + ); + + $response->assertRedirect('/member'); + $this->assertDatabaseHas('memberships', [ + 'member_id' => $member->id, + 'activity_id' => $activity->id, + 'subactivity_id' => $activity->subactivities->first()->id, + 'promised_at' => now()->format('Y-m-d'), + ]); + } +} diff --git a/tests/RequestFactories/MembershipRequestFactory.php b/tests/RequestFactories/MembershipRequestFactory.php index 6a8051cb..d6183046 100644 --- a/tests/RequestFactories/MembershipRequestFactory.php +++ b/tests/RequestFactories/MembershipRequestFactory.php @@ -4,13 +4,16 @@ namespace Tests\RequestFactories; use App\Activity; use App\Subactivity; +use Carbon\Carbon; use Worksome\RequestFactories\RequestFactory; class MembershipRequestFactory extends RequestFactory { public function definition(): array { - return []; + return [ + 'has_promise' => null, + ]; } public function in(Activity $activity, ?Subactivity $subactivity = null): self @@ -44,4 +47,11 @@ class MembershipRequestFactory extends RequestFactory 'subactivity_id' => Subactivity::factory()->create()->id, ]); } + + public function promise(Carbon $value): self + { + return $this->state([ + 'promised_at' => $value->format('Y-m-d'), + ]); + } }