Add: Store Course
This commit is contained in:
parent
fbd4640396
commit
fb95c9a135
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Course\Controllers;
|
||||
|
||||
use App\Course\Requests\StoreRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Member\Member;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CourseController extends Controller
|
||||
{
|
||||
public function store(Member $member, StoreRequest $request): RedirectResponse
|
||||
{
|
||||
$request->persist($member);
|
||||
|
||||
return redirect()->route('member.index');
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
namespace App\Course\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
@ -10,5 +10,5 @@ class Course extends Model
|
|||
use HasFactory;
|
||||
|
||||
public $timestamps = false;
|
||||
public $guarded = [];
|
||||
public $fillable = ['name', 'nami_id'];
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace App\Course\Requests;
|
||||
|
||||
use App\Course\Models\Course;
|
||||
use App\Member\Member;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class StoreRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'organizer' => 'required|max:255',
|
||||
'event_name' => 'required|max:255',
|
||||
'completed_at' => 'required|date',
|
||||
'course_id' => 'required|exists:courses,id',
|
||||
];
|
||||
}
|
||||
|
||||
public function persist(Member $member): void
|
||||
{
|
||||
$course = Course::findOrFail($this->input('course_id'));
|
||||
$payload = array_merge(
|
||||
$this->only(['event_name', 'completed_at', 'course_id', 'organizer']),
|
||||
['course_id' => $course->nami_id],
|
||||
);
|
||||
$namiId = auth()->user()->api()->createCourse($member->nami_id, $payload);
|
||||
|
||||
$member->courses()->attach(
|
||||
$course,
|
||||
$this->safe()->collect()->put('nami_id', $namiId)->except(['course_id'])->toArray(),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace App\Course\Resources;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class CourseResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'organizer' => $this->pivot->organizer,
|
||||
'event_name' => $this->pivot->event_name,
|
||||
'completed_at_human' => Carbon::parse($this->pivot->completed_at)->format('d.m.Y'),
|
||||
'completed_at' => $this->pivot->completed_at,
|
||||
'course_name' => $this->name,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Http\Views;
|
||||
|
||||
use App\Activity;
|
||||
use App\Course\Models\Course;
|
||||
use App\Member\Member;
|
||||
use App\Member\MemberResource;
|
||||
use App\Payment\ActionFactory;
|
||||
|
@ -19,18 +20,19 @@ class MemberView {
|
|||
return [
|
||||
'data' => MemberResource::collection(Member::select('*')
|
||||
->filter($filter)->search($request->query('search', null))
|
||||
->with('billKind')->with('payments')->with('memberships')
|
||||
->with('billKind')->with('payments')->with('memberships')->with('courses')
|
||||
->withSubscriptionName()->withIsConfirmed()->withPendingPayment()->withAgeGroup()
|
||||
->orderByRaw('lastname, firstname')
|
||||
->paginate(15)
|
||||
),
|
||||
'filterActivities' => Activity::where('is_filterable', true)->get()->pluck('name', 'id'),
|
||||
'filterSubactivities' => Subactivity::where('is_filterable', true)->get()->pluck('name', 'id'),
|
||||
'filterActivities' => Activity::where('is_filterable', true)->pluck('name', 'id'),
|
||||
'filterSubactivities' => Subactivity::where('is_filterable', true)->pluck('name', 'id'),
|
||||
'toolbar' => [ ['href' => route('member.index'), 'label' => 'Zurück', 'color' => 'primary', 'icon' => 'plus'] ],
|
||||
'paymentDefaults' => ['nr' => date('Y')],
|
||||
'subscriptions' => Subscription::get()->pluck('name', 'id'),
|
||||
'statuses' => Status::get()->pluck('name', 'id'),
|
||||
'subscriptions' => Subscription::pluck('name', 'id'),
|
||||
'statuses' => Status::pluck('name', 'id'),
|
||||
'activities' => $activities->pluck('name', 'id'),
|
||||
'courses' => Course::pluck('name', 'id'),
|
||||
'subactivities' => $activities->map(function(Activity $activity) {
|
||||
return ['subactivities' => $activity->subactivities->pluck('name', 'id'), 'id' => $activity->id];
|
||||
})->pluck('subactivities', 'id'),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Initialize;
|
||||
|
||||
use App\Course;
|
||||
use App\Course\Models\Course;
|
||||
use Aweos\Agnoster\Progress\Progress;
|
||||
use Zoomyboy\LaravelNami\Api;
|
||||
use Zoomyboy\LaravelNami\NamiUser;
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace App\Initialize;
|
|||
use App\Activity;
|
||||
use App\Confession;
|
||||
use App\Country;
|
||||
use App\Course;
|
||||
use App\Course\Models\Course;
|
||||
use App\Fee;
|
||||
use App\Gender;
|
||||
use App\Group;
|
||||
|
|
|
@ -6,7 +6,7 @@ use App\Activity;
|
|||
use App\Bill\BillKind;
|
||||
use App\Confession;
|
||||
use App\Country;
|
||||
use App\Course;
|
||||
use App\Course\Models\Course;
|
||||
use App\Group;
|
||||
use App\Nationality;
|
||||
use App\Payment\Payment;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Member;
|
||||
|
||||
use App\Course\Resources\CourseResource;
|
||||
use App\Membership\MembershipResource;
|
||||
use App\Payment\PaymentResource;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
@ -55,6 +56,7 @@ class MemberResource extends JsonResource
|
|||
'first_activity_id' => $this->first_activity_id,
|
||||
'first_subactivity_id' => $this->first_subactivity_id,
|
||||
'age_group_icon' => $this->age_group_icon,
|
||||
'courses' => CourseResource::collection($this->whenLoaded('courses')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories\Course\Models;
|
||||
|
||||
use App\Course\Models\Course;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<Course>
|
||||
*/
|
||||
class CourseFactory extends Factory
|
||||
{
|
||||
|
||||
/**
|
||||
* The name of the factory's corresponding model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $model = Course::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'name' => $this->faker->words(5, true),
|
||||
];
|
||||
}
|
||||
|
||||
public function inNami(int $namiId): self
|
||||
{
|
||||
return $this->state(['nami_id' => $namiId]);
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class CourseFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
|
@ -17,12 +17,12 @@ class GroupFactory extends Factory
|
|||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'name' => $this->faker->randomElement(['Normaler Beitrag', 'Familienermäßigt']),
|
||||
'name' => $this->faker->words(5, true),
|
||||
'nami_id' => $this->faker->randomNumber(),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@ use App\Payment\Payment;
|
|||
use App\Payment\Subscription;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<Member>
|
||||
*/
|
||||
class MemberFactory extends Factory
|
||||
{
|
||||
/**
|
||||
|
@ -23,7 +26,7 @@ class MemberFactory extends Factory
|
|||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
|
@ -34,7 +37,7 @@ class MemberFactory extends Factory
|
|||
'joined_at' => $this->faker->dateTimeBetween('-30 years'),
|
||||
'send_newspaper' => $this->faker->boolean,
|
||||
'address' => $this->faker->streetAddress,
|
||||
'zip' => $this->faker->postCode,
|
||||
'zip' => $this->faker->postcode,
|
||||
'location' => $this->faker->city,
|
||||
];
|
||||
}
|
||||
|
@ -61,6 +64,14 @@ class MemberFactory extends Factory
|
|||
->for($subscription);
|
||||
}
|
||||
|
||||
public function inNami(int $namiId): self
|
||||
{
|
||||
return $this->state(['nami_id' => $namiId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, callable> $payments
|
||||
*/
|
||||
public function withPayments(array $payments): self
|
||||
{
|
||||
return $this->afterCreating(function (Member $model) use ($payments): void {
|
||||
|
|
|
@ -13,11 +13,11 @@ class CreateGeneralSettings extends SettingsMigration
|
|||
{
|
||||
$defaults = [
|
||||
'diözese' => [
|
||||
'modules' => [],
|
||||
'modules' => ['courses'],
|
||||
'single_view' => false,
|
||||
],
|
||||
'stamm' => [
|
||||
'modules' => ['bill'],
|
||||
'modules' => ['bill', 'courses'],
|
||||
'single_view' => true,
|
||||
]
|
||||
];
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<svg height="512" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m501.991 128.354-241-85.031a14.992 14.992 0 0 0-9.981 0l-241 85.031a15.001 15.001 0 0 0-.034 28.279l241 85.677a14.991 14.991 0 0 0 10.048 0l241-85.677a15 15 0 0 0-.033-28.279zM475.973 328.574v-130.84l-30 10.665v120.175c-9.036 5.201-15.125 14.946-15.125 26.121 0 11.174 6.089 20.92 15.125 26.121v73.716c0 8.284 6.716 15 15 15s15-6.716 15-15v-73.715c9.036-5.2 15.125-14.947 15.125-26.121 0-11.175-6.088-20.921-15.125-26.122z"/><path d="M256 273.177c-5.149 0-10.22-.875-15.073-2.6l-135.483-48.165v66.008c0 16.149 16.847 29.806 50.073 40.59 28.961 9.4 64.647 14.577 100.483 14.577s71.521-5.177 100.483-14.577c33.226-10.784 50.073-24.441 50.073-40.59v-66.008l-135.482 48.165a44.896 44.896 0 0 1-15.074 2.6z"/></svg>
|
After Width: | Height: | Size: 785 B |
|
@ -0,0 +1,95 @@
|
|||
<template>
|
||||
<div class="sidebar flex flex-col">
|
||||
<sidebar-header :links="indexLinks" @close="$emit('close')" @create="mode = 'create'; single = {}" title="Ausbildungen"></sidebar-header>
|
||||
|
||||
<form v-if="single" class="p-6 grid gap-4 justify-start" @submit.prevent="submit">
|
||||
<f-text id="nr" v-model="single.nr" label="Jahr" required></f-text>
|
||||
<f-select id="subscription_id" :options="subscriptions" v-model="single.subscription_id" label="Beitrag" required></f-select>
|
||||
<f-select id="status_id" :options="statuses" v-model="single.status_id" label="Status" required></f-select>
|
||||
<button type="submit" class="btn btn-primary">Absenden</button>
|
||||
</form>
|
||||
|
||||
<table v-else class="custom-table custom-table-light custom-table-sm text-sm flex-grow">
|
||||
<thead>
|
||||
<th>Baustein</th>
|
||||
<th>Veranstaltung</th>
|
||||
<th>Veranstalter</th>
|
||||
<th>Datum</th>
|
||||
<th></th>
|
||||
</thead>
|
||||
|
||||
<tr v-for="course, index in value.courses">
|
||||
<td v-text="course.course_name"></td>
|
||||
<td v-text="course.event_name"></td>
|
||||
<td v-text="course.organizer"></td>
|
||||
<td v-text="course.completed_at_human"></td>
|
||||
<td class="flex">
|
||||
<a href="#" @click.prevent="single = course; mode = 'edit'" class="inline-flex btn btn-warning btn-sm"><sprite src="pencil"></sprite></a>
|
||||
<inertia-link href="#" @click.prevent="remove(course)" class="inline-flex btn btn-danger btn-sm"><sprite src="trash"></sprite></inertia-link>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SidebarHeader from '../../components/SidebarHeader.vue';
|
||||
|
||||
export default {
|
||||
data: function() {
|
||||
return {
|
||||
mode: null,
|
||||
single: null,
|
||||
indexLinks: [
|
||||
{event: 'create', label: 'Neuer Kurs'}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
props: {
|
||||
value: {}
|
||||
},
|
||||
|
||||
components: { SidebarHeader },
|
||||
|
||||
methods: {
|
||||
remove(payment) {
|
||||
this.$inertia.delete(`/member/${this.value.id}/payment/${payment.id}`);
|
||||
},
|
||||
|
||||
accept(payment) {
|
||||
this.$inertia.patch(`/member/${this.value.id}/payment/${payment.id}`, { ...payment, status_id: 3 });
|
||||
},
|
||||
|
||||
openLink(link) {
|
||||
if (link.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.open(link.href);
|
||||
},
|
||||
|
||||
submit() {
|
||||
var _self = this;
|
||||
|
||||
this.mode === 'create'
|
||||
? this.$inertia.post(`/member/${this.value.id}/payment`, this.single, {
|
||||
onFinish() {
|
||||
_self.single = null;
|
||||
}
|
||||
})
|
||||
: this.$inertia.patch(`/member/${this.value.id}/payment/${this.single.id}`, this.single, {
|
||||
onFinish() {
|
||||
_self.single = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
props: {
|
||||
value: {},
|
||||
subscriptions: {},
|
||||
statuses: {},
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -53,6 +53,7 @@
|
|||
<td class="flex">
|
||||
<inertia-link :href="`/member/${member.id}/edit`" class="inline-flex btn btn-warning btn-sm"><sprite src="pencil"></sprite></inertia-link>
|
||||
<a href="#" v-show="hasModule('bill')" @click.prevent="openSidebar(index, 'payment.index')" class="inline-flex btn btn-info btn-sm"><sprite src="money"></sprite></a>
|
||||
<a href="#" v-show="hasModule('courses')" @click.prevent="openSidebar(index, 'courses.index')" class="inline-flex btn btn-info btn-sm"><sprite src="course"></sprite></a>
|
||||
<a href="#" @click.prevent="openSidebar(index, 'membership.index')" class="inline-flex btn btn-info btn-sm"><sprite src="user"></sprite></a>
|
||||
<inertia-link href="#" @click.prevent="remove(member)" class="inline-flex btn btn-danger btn-sm"><sprite src="trash"></sprite></inertia-link>
|
||||
</td>
|
||||
|
@ -67,6 +68,7 @@
|
|||
<transition name="sidebar">
|
||||
<payments v-if="single !== null && sidebar === 'payment.index'" @close="closeSidebar" :subscriptions="subscriptions" :statuses="statuses" v-model="data.data[single]"></payments>
|
||||
<memberships v-if="single !== null && sidebar === 'membership.index'" @close="closeSidebar" :activities="activities" :subactivities="subactivities" v-model="data.data[single]"></memberships>
|
||||
<courses v-if="single !== null && sidebar === 'courses.index'" @close="closeSidebar" :courses="courses" v-model="data.data[single]"></courses>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -75,6 +77,7 @@
|
|||
import App from '../../layouts/App';
|
||||
import Payments from './Payments.vue';
|
||||
import Memberships from './Memberships.vue';
|
||||
import Courses from './Courses.vue';
|
||||
import Filt from './Filt.vue';
|
||||
import mergesQueryString from '../../mixins/mergesQueryString.js';
|
||||
|
||||
|
@ -91,7 +94,7 @@ export default {
|
|||
|
||||
mixins: [mergesQueryString],
|
||||
|
||||
components: { Memberships, Payments, Filt },
|
||||
components: { Memberships, Payments, Filt, Courses },
|
||||
|
||||
methods: {
|
||||
remove(member) {
|
||||
|
@ -120,6 +123,7 @@ export default {
|
|||
subactivities: {},
|
||||
filterActivities: {},
|
||||
filterSubactivities: {},
|
||||
courses: {},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -40,7 +40,7 @@ return [
|
|||
'distinct' => ':attribute beinhaltet einen bereits vorhandenen Wert.',
|
||||
'email' => ':attribute muss eine gültige E-Mail-Adresse sein.',
|
||||
'ends_with' => ':attribute muss eine der folgenden Endungen aufweisen: :values',
|
||||
'exists' => 'Der gewählte Wert für :attribute ist ungültig.',
|
||||
'exists' => ':attribute ist nicht vorhanden.',
|
||||
'file' => ':attribute muss eine Datei sein.',
|
||||
'filled' => ':attribute muss ausgefüllt sein.',
|
||||
'gt' => [
|
||||
|
@ -95,7 +95,7 @@ return [
|
|||
'password' => 'Das Passwort ist falsch.',
|
||||
'present' => ':attribute muss vorhanden sein.',
|
||||
'regex' => ':attribute Format ist ungültig.',
|
||||
'required' => ':attribute muss ausgefüllt werden.',
|
||||
'required' => ':attribute ist erforderlich.',
|
||||
'required_if' => ':attribute muss ausgefüllt werden, wenn :other den Wert :value hat.',
|
||||
'required_unless' => ':attribute muss ausgefüllt werden, wenn :other nicht den Wert :values hat.',
|
||||
'required_with' => ':attribute muss ausgefüllt werden, wenn :values ausgefüllt wurde.',
|
||||
|
@ -188,5 +188,9 @@ return [
|
|||
'first_group_id' => 'Erste Untertätigkeit',
|
||||
'first_activity_id' => 'Erste Tätigkeit',
|
||||
'fee_id' => 'Beitragsart',
|
||||
'course_id' => 'Baustein',
|
||||
'completed_at' => 'Datum',
|
||||
'event_name' => 'Veranstaltung',
|
||||
'organizer' => 'Veranstalter',
|
||||
],
|
||||
];
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use App\Course\Controllers\CourseController;
|
||||
use App\Http\Controllers\HomeController;
|
||||
use App\Initialize\InitializeController;
|
||||
use App\Member\MemberConfirmController;
|
||||
|
@ -30,4 +31,5 @@ Route::group(['middleware' => 'auth:web'], function (): void {
|
|||
Route::get('/sendpayment/pdf', [SendpaymentController::class, 'send'])->name('sendpayment.pdf');
|
||||
Route::apiResource('member.membership', MembershipController::class);
|
||||
Route::resource('setting', SettingController::class);
|
||||
Route::resource('member.course', CourseController::class);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature\Course;
|
||||
|
||||
use App\Course\Models\Course;
|
||||
use App\Member\Member;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Foundation\Testing\WithFaker;
|
||||
use Tests\TestCase;
|
||||
use Zoomyboy\LaravelNami\Backend\FakeBackend;
|
||||
use Zoomyboy\LaravelNami\Fakes\CourseFake;
|
||||
|
||||
class StoreTest extends TestCase
|
||||
{
|
||||
|
||||
use RefreshDatabase;
|
||||
|
||||
/**
|
||||
* @return array<string, array{payload: array<string, mixed>, errors: array<string, mixed>}>
|
||||
*/
|
||||
public function validationDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'course_id_missing' => [
|
||||
'payload' => ['course_id' => null],
|
||||
'errors' => ['course_id' => 'Baustein ist erforderlich.'],
|
||||
],
|
||||
'course_id_invalid' => [
|
||||
'payload' => ['course_id' => 999],
|
||||
'errors' => ['course_id' => 'Baustein ist nicht vorhanden.'],
|
||||
],
|
||||
'completed_at_required' => [
|
||||
'payload' => ['completed_at' => ''],
|
||||
'errors' => ['completed_at' => 'Datum ist erforderlich.'],
|
||||
],
|
||||
'completed_at_not_date' => [
|
||||
'payload' => ['completed_at' => '123'],
|
||||
'errors' => ['completed_at' => 'Datum muss ein gültiges Datum sein.'],
|
||||
],
|
||||
'event_name_required' => [
|
||||
'payload' => ['event_name' => ''],
|
||||
'errors' => ['event_name' => 'Veranstaltung ist erforderlich.'],
|
||||
],
|
||||
'organizer' => [
|
||||
'payload' => ['organizer' => ''],
|
||||
'errors' => ['organizer' => 'Veranstalter ist erforderlich.'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $payload
|
||||
* @param array<string, string> $errors
|
||||
* @dataProvider validationDataProvider
|
||||
*/
|
||||
public function testItValidatesInput(array $payload, array $errors): void
|
||||
{
|
||||
$this->login()->init();
|
||||
$member = Member::factory()->defaults()->inNami(123)->createOne();
|
||||
$course = Course::factory()->inNami(456)->createOne();
|
||||
|
||||
$response = $this->post("/member/{$member->id}/course", array_merge([
|
||||
'course_id' => $course->id,
|
||||
'completed_at' => '2021-01-02',
|
||||
'event_name' => '::event::',
|
||||
'organizer' => '::org::',
|
||||
], $payload));
|
||||
|
||||
$response->assertSessionHasErrors($errors);
|
||||
}
|
||||
|
||||
public function testItCreatesACourse(): void
|
||||
{
|
||||
$this->withoutExceptionHandling();
|
||||
$this->login()->init();
|
||||
$member = Member::factory()->defaults()->inNami(123)->createOne();
|
||||
$course = Course::factory()->inNami(456)->createOne();
|
||||
app(CourseFake::class)->createsSuccessful(123, 999);
|
||||
|
||||
$response = $this->post("/member/{$member->id}/course", [
|
||||
'course_id' => $course->id,
|
||||
'completed_at' => '2021-01-02',
|
||||
'event_name' => '::event::',
|
||||
'organizer' => '::org::',
|
||||
]);
|
||||
|
||||
$response->assertRedirect("/member");
|
||||
$this->assertDatabaseHas('course_member', [
|
||||
'member_id' => $member->id,
|
||||
'course_id' => $course->id,
|
||||
'completed_at' => '2021-01-02',
|
||||
'event_name' => '::event::',
|
||||
'organizer' => '::org::',
|
||||
'nami_id' => 999,
|
||||
]);
|
||||
app(CourseFake::class)->assertCreated(123, [
|
||||
'bausteinId' => 456,
|
||||
'veranstalter' => '::org::',
|
||||
'vstgName' => '::event',
|
||||
'vstgTag' => '2021-01-02T00:00:00',
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
|
@ -4,7 +4,7 @@ namespace Tests\Feature\Initialize;
|
|||
|
||||
use App\Activity;
|
||||
use App\Country;
|
||||
use App\Course;
|
||||
use App\Course\Models\Course;
|
||||
use App\Gender;
|
||||
use App\Member\Member;
|
||||
use App\Nationality;
|
||||
|
|
Loading…
Reference in New Issue