Add frontend for subscription children
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
20b1309ccc
commit
49417981f1
|
@ -22,7 +22,6 @@ class InitializeFees
|
||||||
Fee::create(['nami_id' => $fee->id, 'name' => $fee->name])
|
Fee::create(['nami_id' => $fee->id, 'name' => $fee->name])
|
||||||
->subscriptions()->create([
|
->subscriptions()->create([
|
||||||
'name' => $fee->name,
|
'name' => $fee->name,
|
||||||
'amount' => 1000,
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ class Page
|
||||||
return $this->getPayments()->mapWithKeys(function (Payment $payment) {
|
return $this->getPayments()->mapWithKeys(function (Payment $payment) {
|
||||||
$key = "Beitrag {$payment->nr} für {$payment->member->firstname} {$payment->member->lastname} ({$payment->subscription->name})";
|
$key = "Beitrag {$payment->nr} für {$payment->member->firstname} {$payment->member->lastname} ({$payment->subscription->name})";
|
||||||
|
|
||||||
return [$key => $this->number($payment->subscription->amount)];
|
return [$key => $this->number($payment->subscription->getAmount())];
|
||||||
})->toArray();
|
})->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ namespace App\Letter;
|
||||||
|
|
||||||
use App\Payment\Payment;
|
use App\Payment\Payment;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
class RememberDocument extends Letter
|
class RememberDocument extends Letter
|
||||||
{
|
{
|
||||||
|
@ -18,57 +17,14 @@ class RememberDocument extends Letter
|
||||||
return 'Zahlungserinnerung';
|
return 'Zahlungserinnerung';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setFilename(string $filename): static
|
|
||||||
{
|
|
||||||
$this->filename = $filename;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFilename(): string
|
|
||||||
{
|
|
||||||
return $this->filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function view(): string
|
public function view(): string
|
||||||
{
|
{
|
||||||
return 'tex.remember';
|
return 'tex.remember';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static function sendAllLabel(): string
|
||||||
* @return array<string, string>
|
|
||||||
*/
|
|
||||||
public function getPositions(Collection $page): array
|
|
||||||
{
|
{
|
||||||
$memberIds = $page->pluck('id')->toArray();
|
return 'Erinnerungen versenden';
|
||||||
$payments = Payment::whereIn('member_id', $memberIds)
|
|
||||||
->orderByRaw('nr, member_id')->whereNeedsRemember()->get();
|
|
||||||
|
|
||||||
return $payments->mapWithKeys(function (Payment $payment) {
|
|
||||||
$key = "Beitrag {$payment->nr} für {$payment->member->firstname} {$payment->member->lastname} ({$payment->subscription->name})";
|
|
||||||
|
|
||||||
return [$key => $this->number($payment->subscription->amount)];
|
|
||||||
})->toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAddress(Collection $page): string
|
|
||||||
{
|
|
||||||
return $page->first()->address;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getZip(Collection $page): string
|
|
||||||
{
|
|
||||||
return $page->first()->zip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getEmail(Collection $page): string
|
|
||||||
{
|
|
||||||
return $page->first()->email_parents ?: $page->first()->email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLocation(Collection $page): string
|
|
||||||
{
|
|
||||||
return $page->first()->location;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function afterSingle(Payment $payment): void
|
public function afterSingle(Payment $payment): void
|
||||||
|
@ -103,9 +59,4 @@ class RememberDocument extends Letter
|
||||||
'Das zuletzt erinnerte Datum wird auf heute gesetzt.',
|
'Das zuletzt erinnerte Datum wird auf heute gesetzt.',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function sendAllLabel(): string
|
|
||||||
{
|
|
||||||
return 'Erinnerungen versenden';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ class MemberShowAction
|
||||||
return [
|
return [
|
||||||
'data' => new MemberResource($member
|
'data' => new MemberResource($member
|
||||||
->load('memberships')
|
->load('memberships')
|
||||||
->load('payments.subscription')
|
->load('payments.subscription.children')
|
||||||
->load('nationality')
|
->load('nationality')
|
||||||
->load('region')
|
->load('region')
|
||||||
->load('subscription')
|
->load('subscription')
|
||||||
|
|
|
@ -280,10 +280,11 @@ class Member extends Model
|
||||||
public function scopeWithPendingPayment(Builder $q): Builder
|
public function scopeWithPendingPayment(Builder $q): Builder
|
||||||
{
|
{
|
||||||
return $q->addSelect([
|
return $q->addSelect([
|
||||||
'pending_payment' => Payment::selectRaw('SUM(subscriptions.amount)')
|
'pending_payment' => Payment::selectRaw('SUM(subscription_children.amount)')
|
||||||
->whereColumn('payments.member_id', 'members.id')
|
->whereColumn('payments.member_id', 'members.id')
|
||||||
->whereNeedsPayment()
|
->whereNeedsPayment()
|
||||||
->join('subscriptions', 'subscriptions.id', 'payments.subscription_id'),
|
->join('subscriptions', 'subscriptions.id', 'payments.subscription_id')
|
||||||
|
->join('subscription_children', 'subscriptions.id', 'subscription_children.parent_id'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,11 @@ class MemberPaymentBlock extends Block
|
||||||
*/
|
*/
|
||||||
public function data(): array
|
public function data(): array
|
||||||
{
|
{
|
||||||
$amount = Payment::whereNeedsPayment()->selectRaw('sum(subscriptions.amount) AS nr')->join('subscriptions', 'subscriptions.id', 'payments.subscription_id')->first();
|
$amount = Payment::whereNeedsPayment()
|
||||||
|
->selectRaw('sum(subscription_children.amount) AS nr')
|
||||||
|
->join('subscriptions', 'subscriptions.id', 'payments.subscription_id')
|
||||||
|
->join('subscription_children', 'subscriptions.id', 'subscription_children.parent_id')
|
||||||
|
->first();
|
||||||
$members = Member::whereHasPendingPayment()->count();
|
$members = Member::whereHasPendingPayment()->count();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -6,6 +6,7 @@ use App\Fee;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
class Subscription extends Model
|
class Subscription extends Model
|
||||||
{
|
{
|
||||||
|
@ -13,8 +14,23 @@ class Subscription extends Model
|
||||||
|
|
||||||
public $fillable = ['name', 'amount', 'fee_id'];
|
public $fillable = ['name', 'amount', 'fee_id'];
|
||||||
|
|
||||||
|
public function getAmount(): int
|
||||||
|
{
|
||||||
|
return $this->children->sum('amount');
|
||||||
|
}
|
||||||
|
|
||||||
public function fee(): BelongsTo
|
public function fee(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Fee::class);
|
return $this->belongsTo(Fee::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function children(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(SubscriptionChild::class, 'parent_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function booted(): void
|
||||||
|
{
|
||||||
|
static::deleting(fn ($model) => $model->children()->delete());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Payment;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class SubscriptionChild extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use HasUuids;
|
||||||
|
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
public $fillable = ['name', 'amount', 'uuid', 'parent_id'];
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Payment;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mixin SubscriptionChild
|
||||||
|
*/
|
||||||
|
class SubscriptionChildResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
*
|
||||||
|
* @return array{amount: int, name: string}
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'amount' => $this->amount,
|
||||||
|
'name' => $this->name,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,20 +29,29 @@ class SubscriptionController extends Controller
|
||||||
return \Inertia::render('subscription/SubscriptionForm', [
|
return \Inertia::render('subscription/SubscriptionForm', [
|
||||||
'fees' => Fee::pluck('name', 'id'),
|
'fees' => Fee::pluck('name', 'id'),
|
||||||
'mode' => 'create',
|
'mode' => 'create',
|
||||||
'data' => (object) [],
|
'data' => [
|
||||||
|
'children' => [],
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(Request $request): RedirectResponse
|
public function store(Request $request): RedirectResponse
|
||||||
{
|
{
|
||||||
Subscription::create($request->validate([
|
$subscriptionParams = $request->validate([
|
||||||
'name' => 'required|max:255',
|
'name' => 'required|max:255',
|
||||||
'amount' => 'required|numeric',
|
|
||||||
'fee_id' => 'required|exists:fees,id',
|
'fee_id' => 'required|exists:fees,id',
|
||||||
], [], [
|
], [], [
|
||||||
'fee_id' => 'Nami-Beitrag',
|
'fee_id' => 'Nami-Beitrag',
|
||||||
'amount' => 'Interner Beitrag',
|
]);
|
||||||
]));
|
|
||||||
|
$children = $request->validate([
|
||||||
|
'children' => 'present|array',
|
||||||
|
'children.*.amount' => 'required|numeric',
|
||||||
|
'children.*.name' => 'required|max:255',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$subscription = Subscription::create($subscriptionParams);
|
||||||
|
$subscription->children()->createMany($children['children']);
|
||||||
|
|
||||||
return redirect()->route('subscription.index');
|
return redirect()->route('subscription.index');
|
||||||
}
|
}
|
||||||
|
@ -61,14 +70,27 @@ class SubscriptionController extends Controller
|
||||||
|
|
||||||
public function update(Subscription $subscription, Request $request): RedirectResponse
|
public function update(Subscription $subscription, Request $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$subscription->update($request->validate([
|
$subscriptionParams = $request->validate([
|
||||||
'name' => 'required|max:255',
|
'name' => 'required|max:255',
|
||||||
'amount' => 'required|numeric',
|
|
||||||
'fee_id' => 'required|exists:fees,id',
|
'fee_id' => 'required|exists:fees,id',
|
||||||
], [], [
|
], [], [
|
||||||
'fee_id' => 'Nami-Beitrag',
|
'fee_id' => 'Nami-Beitrag',
|
||||||
'amount' => 'Interner Beitrag',
|
]);
|
||||||
]));
|
$subscription->update($subscriptionParams);
|
||||||
|
$children = $request->validate([
|
||||||
|
'children' => 'present|array',
|
||||||
|
'children.*.amount' => 'required|numeric',
|
||||||
|
'children.*.name' => 'required|max:255',
|
||||||
|
]);
|
||||||
|
$subscription->children()->delete();
|
||||||
|
$subscription->children()->createMany($children['children']);
|
||||||
|
|
||||||
|
return redirect()->route('subscription.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Subscription $subscription): RedirectResponse
|
||||||
|
{
|
||||||
|
$subscription->delete();
|
||||||
|
|
||||||
return redirect()->route('subscription.index');
|
return redirect()->route('subscription.index');
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,9 @@ class SubscriptionResource extends JsonResource
|
||||||
'name' => $this->name,
|
'name' => $this->name,
|
||||||
'fee_id' => $this->fee_id,
|
'fee_id' => $this->fee_id,
|
||||||
'fee_name' => $this->fee->name,
|
'fee_name' => $this->fee->name,
|
||||||
'amount_human' => number_format($this->amount / 100, 2, ',', '.').' €',
|
'amount_human' => number_format($this->getAmount() / 100, 2, ',', '.').' €',
|
||||||
'amount' => $this->amount,
|
'amount' => $this->getAmount(),
|
||||||
|
'children' => SubscriptionChildResource::collection($this->whenLoaded('children')),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use App\Payment\Payment;
|
||||||
use App\Payment\Status;
|
use App\Payment\Status;
|
||||||
use App\Payment\Subscription;
|
use App\Payment\Subscription;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
|
|
||||||
class PaymentFactory extends Factory
|
class PaymentFactory extends Factory
|
||||||
{
|
{
|
||||||
|
@ -37,10 +38,13 @@ class PaymentFactory extends Factory
|
||||||
return $this->state(['nr' => $nr]);
|
return $this->state(['nr' => $nr]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function subscription(string $name, int $amount): self
|
/**
|
||||||
|
* @param array<int, Child> $children
|
||||||
|
*/
|
||||||
|
public function subscription(string $name, array $children): self
|
||||||
{
|
{
|
||||||
return $this->for(
|
return $this->for(
|
||||||
Subscription::factory()->state(['name' => $name, 'amount' => $amount])->for(Fee::factory())
|
Subscription::factory()->state(['name' => $name])->for(Fee::factory())->children($children)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories\Payment;
|
||||||
|
|
||||||
|
use App\Payment\SubscriptionChild;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<SubscriptionChild>
|
||||||
|
*/
|
||||||
|
class SubscriptionChildFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = SubscriptionChild::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'amount' => $this->faker->numberBetween(10, 3000),
|
||||||
|
'name' => $this->faker->words(5, true),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,9 @@ namespace Database\Factories\Payment;
|
||||||
|
|
||||||
use App\Fee;
|
use App\Fee;
|
||||||
use App\Payment\Subscription;
|
use App\Payment\Subscription;
|
||||||
|
use App\Payment\SubscriptionChild;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
|
|
||||||
class SubscriptionFactory extends Factory
|
class SubscriptionFactory extends Factory
|
||||||
{
|
{
|
||||||
|
@ -14,7 +16,6 @@ class SubscriptionFactory extends Factory
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => $this->faker->word,
|
'name' => $this->faker->word,
|
||||||
'amount' => $this->faker->numberBetween(1000, 50000),
|
|
||||||
'fee_id' => Fee::factory()->createOne()->id,
|
'fee_id' => Fee::factory()->createOne()->id,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -24,8 +25,17 @@ class SubscriptionFactory extends Factory
|
||||||
return $this->state(['name' => $name]);
|
return $this->state(['name' => $name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function amount(int $amount): self
|
/**
|
||||||
|
* @param array<int, Child> $children
|
||||||
|
*/
|
||||||
|
public function children(array $children): self
|
||||||
{
|
{
|
||||||
return $this->state(['amount' => $amount]);
|
$instance = $this;
|
||||||
|
|
||||||
|
foreach ($children as $child) {
|
||||||
|
$instance = $instance->has(SubscriptionChild::factory()->state($child->toArray()), 'children');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Payment\SubscriptionChild;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class() extends Migration {
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$subscriptions = DB::table('subscriptions')->get();
|
||||||
|
|
||||||
|
Schema::table('subscriptions', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('amount');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('subscription_children', function (Blueprint $table) {
|
||||||
|
$table->uuid('id');
|
||||||
|
$table->foreignId('parent_id')->constrained('subscriptions');
|
||||||
|
$table->string('name');
|
||||||
|
$table->unsignedInteger('amount');
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($subscriptions as $subscription) {
|
||||||
|
SubscriptionChild::create([
|
||||||
|
'parent_id' => $subscription->id,
|
||||||
|
'name' => 'name',
|
||||||
|
'amount' => $subscription->amount,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,16 +1,50 @@
|
||||||
<template>
|
<template>
|
||||||
<form id="subedit" class="p-6 grid gap-4 justify-start" @submit.prevent="submit">
|
<form id="subedit" class="p-3 grid gap-3" @submit.prevent="submit">
|
||||||
<save-button form="subedit"></save-button>
|
<save-button form="subedit"></save-button>
|
||||||
<f-text id="name" v-model="inner.name" label="Name" required></f-text>
|
<box heading="Beitrag">
|
||||||
|
<div class="grid gap-4 sm:grid-cols-2">
|
||||||
|
<f-text id="name" v-model="inner.name" label="Name" size="sm" required></f-text>
|
||||||
<f-select
|
<f-select
|
||||||
id="fee_id"
|
id="fee_id"
|
||||||
name="fee_id"
|
name="fee_id"
|
||||||
:options="fees"
|
:options="fees"
|
||||||
v-model="inner.fee_id"
|
v-model="inner.fee_id"
|
||||||
label="Nami-Beitrag"
|
label="Nami-Beitrag"
|
||||||
|
size="sm"
|
||||||
required
|
required
|
||||||
></f-select>
|
></f-select>
|
||||||
<f-text id="amount" v-model="inner.amount" label="Interner Beitrag" mode="area" required></f-text>
|
</div>
|
||||||
|
</box>
|
||||||
|
<box heading="Positionen">
|
||||||
|
<div class="flex flex-col space-y-4">
|
||||||
|
<div v-for="(pos, index) in inner.children" :key="index" class="flex space-x-2 items-end">
|
||||||
|
<f-text :id="`name-${index}`" v-model="pos.name" label="Name" size="sm" required></f-text>
|
||||||
|
<f-text
|
||||||
|
:id="`amount-${index}`"
|
||||||
|
v-model="pos.amount"
|
||||||
|
label="Beitrag"
|
||||||
|
size="sm"
|
||||||
|
mode="area"
|
||||||
|
required
|
||||||
|
></f-text>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
@click.prevent="inner.children.splice(index, 1)"
|
||||||
|
class="btn btn-sm btn-danger icon flex-none"
|
||||||
|
>
|
||||||
|
<svg-sprite src="trash" class="w-5 h-5"></svg-sprite>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
@click.prevent="inner.children.push({name: '', amount: 0})"
|
||||||
|
class="btn btn-sm flex btn-primary flex self-start mt-4"
|
||||||
|
>
|
||||||
|
<svg-sprite src="plus" class="w-5 h-5"></svg-sprite>
|
||||||
|
Position hinzufügen
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</box>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ use App\Letter\RememberDocument;
|
||||||
use App\Member\Member;
|
use App\Member\Member;
|
||||||
use App\Payment\Payment;
|
use App\Payment\Payment;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use Zoomyboy\Tex\Tex;
|
use Zoomyboy\Tex\Tex;
|
||||||
|
|
||||||
|
@ -40,7 +41,10 @@ class DocumentFactoryTest extends TestCase
|
||||||
'zip' => '::zip::',
|
'zip' => '::zip::',
|
||||||
'location' => '::location::',
|
'location' => '::location::',
|
||||||
])
|
])
|
||||||
->has(Payment::factory()->notPaid()->nr('1995')->subscription('::subName::', 1500))
|
->has(Payment::factory()->notPaid()->nr('1995')->subscription('::subName::', [
|
||||||
|
new Child('a', 1000),
|
||||||
|
new Child('a', 500),
|
||||||
|
]))
|
||||||
->create();
|
->create();
|
||||||
|
|
||||||
$letter = app(DocumentFactory::class)->singleLetter(BillDocument::class, $this->query($member));
|
$letter = app(DocumentFactory::class)->singleLetter(BillDocument::class, $this->query($member));
|
||||||
|
@ -59,7 +63,7 @@ class DocumentFactoryTest extends TestCase
|
||||||
$member = Member::factory()
|
$member = Member::factory()
|
||||||
->defaults()
|
->defaults()
|
||||||
->state(['lastname' => '::lastname::'])
|
->state(['lastname' => '::lastname::'])
|
||||||
->has(Payment::factory()->notPaid()->nr('1995')->subscription('::subName::', 1500))
|
->has(Payment::factory()->notPaid()->nr('1995'))
|
||||||
->create();
|
->create();
|
||||||
|
|
||||||
$letter = app(DocumentFactory::class)->singleLetter(BillDocument::class, $this->query($member));
|
$letter = app(DocumentFactory::class)->singleLetter(BillDocument::class, $this->query($member));
|
||||||
|
|
|
@ -11,6 +11,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Mail;
|
use Mail;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use Zoomyboy\Tex\Tex;
|
use Zoomyboy\Tex\Tex;
|
||||||
|
|
||||||
|
@ -29,7 +30,9 @@ class LetterSendActionTest extends TestCase
|
||||||
$this->login()->loginNami();
|
$this->login()->loginNami();
|
||||||
$this->member = Member::factory()
|
$this->member = Member::factory()
|
||||||
->defaults()
|
->defaults()
|
||||||
->has(Payment::factory()->notPaid()->nr('1997')->subscription('tollerbeitrag', 5400))
|
->has(Payment::factory()->notPaid()->nr('1997')->subscription('tollerbeitrag', [
|
||||||
|
new Child('a', 5400),
|
||||||
|
]))
|
||||||
->emailBillKind()
|
->emailBillKind()
|
||||||
->create(['firstname' => 'Lah', 'lastname' => 'Mom', 'email' => 'peter@example.com']);
|
->create(['firstname' => 'Lah', 'lastname' => 'Mom', 'email' => 'peter@example.com']);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ use App\Payment\Payment;
|
||||||
use App\Subactivity;
|
use App\Subactivity;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class IndexTest extends TestCase
|
class IndexTest extends TestCase
|
||||||
|
@ -108,7 +109,10 @@ class IndexTest extends TestCase
|
||||||
{
|
{
|
||||||
$this->withoutExceptionHandling()->login()->loginNami();
|
$this->withoutExceptionHandling()->login()->loginNami();
|
||||||
$member = Member::factory()
|
$member = Member::factory()
|
||||||
->has(Payment::factory()->notPaid()->nr('2019')->subscription('Free', 1050))
|
->has(Payment::factory()->notPaid()->nr('2019')->subscription('Free', [
|
||||||
|
new Child('a', 1000),
|
||||||
|
new Child('b', 50),
|
||||||
|
]))
|
||||||
->defaults()->create();
|
->defaults()->create();
|
||||||
|
|
||||||
$response = $this->get('/member');
|
$response = $this->get('/member');
|
||||||
|
|
|
@ -15,6 +15,7 @@ use App\Payment\Subscription;
|
||||||
use App\Region;
|
use App\Region;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class ShowTest extends TestCase
|
class ShowTest extends TestCase
|
||||||
|
@ -34,7 +35,10 @@ class ShowTest extends TestCase
|
||||||
$member = Member::factory()
|
$member = Member::factory()
|
||||||
->defaults()
|
->defaults()
|
||||||
->has(Membership::factory()->promise(now())->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))
|
->has(Payment::factory()->notPaid()->nr('2019')->subscription('Free', [
|
||||||
|
new Child('uu', 1000),
|
||||||
|
new Child('a', 50),
|
||||||
|
]))
|
||||||
->for(Gender::factory()->name('Männlich'))
|
->for(Gender::factory()->name('Männlich'))
|
||||||
->for(Region::factory()->name('NRW'))
|
->for(Region::factory()->name('NRW'))
|
||||||
->postBillKind()
|
->postBillKind()
|
||||||
|
|
|
@ -6,6 +6,7 @@ use App\Member\Member;
|
||||||
use App\Payment\MemberPaymentBlock;
|
use App\Payment\MemberPaymentBlock;
|
||||||
use App\Payment\Payment;
|
use App\Payment\Payment;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class MemberPaymentsBlockTest extends TestCase
|
class MemberPaymentsBlockTest extends TestCase
|
||||||
|
@ -18,7 +19,10 @@ class MemberPaymentsBlockTest extends TestCase
|
||||||
|
|
||||||
Member::factory()
|
Member::factory()
|
||||||
->defaults()
|
->defaults()
|
||||||
->has(Payment::factory()->notPaid()->subscription('example', 3400))
|
->has(Payment::factory()->notPaid()->subscription('example', [
|
||||||
|
new Child('gg', 3400),
|
||||||
|
new Child('gg', 100),
|
||||||
|
]))
|
||||||
->create();
|
->create();
|
||||||
Member::factory()
|
Member::factory()
|
||||||
->defaults()
|
->defaults()
|
||||||
|
@ -27,7 +31,7 @@ class MemberPaymentsBlockTest extends TestCase
|
||||||
$data = app(MemberPaymentBlock::class)->render()['data'];
|
$data = app(MemberPaymentBlock::class)->render()['data'];
|
||||||
|
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
'amount' => '34,00 €',
|
'amount' => '35,00 €',
|
||||||
'members' => 1,
|
'members' => 1,
|
||||||
'total_members' => 2,
|
'total_members' => 2,
|
||||||
], $data);
|
], $data);
|
||||||
|
|
|
@ -8,6 +8,7 @@ use App\Member\Member;
|
||||||
use App\Payment\Payment;
|
use App\Payment\Payment;
|
||||||
use App\Payment\Status;
|
use App\Payment\Status;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
use Tests\RequestFactories\LetterSettingsFake;
|
use Tests\RequestFactories\LetterSettingsFake;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use Zoomyboy\Tex\Tex;
|
use Zoomyboy\Tex\Tex;
|
||||||
|
@ -37,8 +38,8 @@ class SendpaymentTest extends TestCase
|
||||||
$this->login()->loginNami();
|
$this->login()->loginNami();
|
||||||
$member = Member::factory()
|
$member = Member::factory()
|
||||||
->defaults()
|
->defaults()
|
||||||
->has(Payment::factory()->notPaid()->nr('1997')->subscription('tollerbeitrag', 5400))
|
->has(Payment::factory()->notPaid()->nr('1997')->subscription('tollerbeitrag', [new Child('a', 5400)]))
|
||||||
->has(Payment::factory()->paid()->nr('1998')->subscription('bezahltdesc', 5800))
|
->has(Payment::factory()->paid()->nr('1998')->subscription('bezahltdesc', [new Child('b', 5800)]))
|
||||||
->postBillKind()
|
->postBillKind()
|
||||||
->create();
|
->create();
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ class SendpaymentTest extends TestCase
|
||||||
$this->login()->loginNami();
|
$this->login()->loginNami();
|
||||||
$member = Member::factory()
|
$member = Member::factory()
|
||||||
->defaults()
|
->defaults()
|
||||||
->has(Payment::factory()->notPaid()->nr('1997')->subscription('tollerbeitrag', 5400))
|
->has(Payment::factory()->notPaid()->nr('1997')->subscription('tollerbeitrag', [new Child('u', 5400)]))
|
||||||
->emailBillKind()
|
->emailBillKind()
|
||||||
->create();
|
->create();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Subscription;
|
||||||
|
|
||||||
|
use App\Fee;
|
||||||
|
use App\Payment\Subscription;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class DestroyTest extends TestCase
|
||||||
|
{
|
||||||
|
use DatabaseTransactions;
|
||||||
|
|
||||||
|
public function testItDeletesChildrenWithSubscription(): void
|
||||||
|
{
|
||||||
|
$this->withoutExceptionHandling()->login()->loginNami();
|
||||||
|
$subscription = Subscription::factory()->name('hi')->for(Fee::factory())->children([
|
||||||
|
new Child('a', 1400),
|
||||||
|
new Child('b', 1500),
|
||||||
|
])->create();
|
||||||
|
|
||||||
|
$response = $this->from('/subscription')->delete("/subscription/{$subscription->id}");
|
||||||
|
|
||||||
|
$response->assertRedirect('/subscription');
|
||||||
|
$this->assertDatabaseCount('subscription_children', 0);
|
||||||
|
$this->assertDatabaseCount('subscriptions', 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Subscription;
|
||||||
|
|
||||||
|
use App\Fee;
|
||||||
|
use App\Payment\Subscription;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class EditTest extends TestCase
|
||||||
|
{
|
||||||
|
use DatabaseTransactions;
|
||||||
|
|
||||||
|
public function testItReturnsChildren(): void
|
||||||
|
{
|
||||||
|
$this->withoutExceptionHandling()->login()->loginNami();
|
||||||
|
$subscription = Subscription::factory()->name('hi')->for(Fee::factory())->children([
|
||||||
|
new Child('a', 1400),
|
||||||
|
new Child('b', 1500),
|
||||||
|
])->create();
|
||||||
|
|
||||||
|
$response = $this->get("/subscription/{$subscription->id}/edit");
|
||||||
|
|
||||||
|
$this->assertInertiaHas([
|
||||||
|
'children' => [
|
||||||
|
['name' => 'a', 'amount' => 1400],
|
||||||
|
['name' => 'b', 'amount' => 1500],
|
||||||
|
],
|
||||||
|
'name' => 'hi',
|
||||||
|
'id' => $subscription->id,
|
||||||
|
], $response, 'data');
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,9 @@
|
||||||
namespace Tests\Feature\Subscription;
|
namespace Tests\Feature\Subscription;
|
||||||
|
|
||||||
use App\Fee;
|
use App\Fee;
|
||||||
|
use App\Payment\Subscription;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
use Tests\RequestFactories\SubscriptionRequestFactory;
|
use Tests\RequestFactories\SubscriptionRequestFactory;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
@ -18,14 +20,21 @@ class StoreTest extends TestCase
|
||||||
|
|
||||||
$response = $this->from('/subscription')->post(
|
$response = $this->from('/subscription')->post(
|
||||||
'/subscription',
|
'/subscription',
|
||||||
SubscriptionRequestFactory::new()->amount(2500)->fee($fee)->name('lorem')->create()
|
SubscriptionRequestFactory::new()->fee($fee)->name('lorem')->children([
|
||||||
|
new Child('ch', 2500),
|
||||||
|
])->create()
|
||||||
);
|
);
|
||||||
|
|
||||||
$response->assertRedirect('/subscription');
|
$response->assertRedirect('/subscription');
|
||||||
|
$subscription = Subscription::firstWhere('name', 'lorem');
|
||||||
$this->assertDatabaseHas('subscriptions', [
|
$this->assertDatabaseHas('subscriptions', [
|
||||||
'amount' => 2500,
|
|
||||||
'fee_id' => $fee->id,
|
'fee_id' => $fee->id,
|
||||||
'name' => 'Lorem',
|
'name' => 'lorem',
|
||||||
|
]);
|
||||||
|
$this->assertDatabaseHas('subscription_children', [
|
||||||
|
'name' => 'ch',
|
||||||
|
'amount' => 2500,
|
||||||
|
'parent_id' => $subscription->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +49,6 @@ class StoreTest extends TestCase
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertErrors([
|
$this->assertErrors([
|
||||||
'amount' => 'Interner Beitrag ist erforderlich.',
|
|
||||||
'fee_id' => 'Nami-Beitrag ist nicht vorhanden.',
|
'fee_id' => 'Nami-Beitrag ist nicht vorhanden.',
|
||||||
'name' => 'Name ist erforderlich.',
|
'name' => 'Name ist erforderlich.',
|
||||||
], $response);
|
], $response);
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace Tests\Feature\Subscription;
|
||||||
use App\Fee;
|
use App\Fee;
|
||||||
use App\Payment\Subscription;
|
use App\Payment\Subscription;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\RequestFactories\Child;
|
||||||
use Tests\RequestFactories\SubscriptionRequestFactory;
|
use Tests\RequestFactories\SubscriptionRequestFactory;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ class UpdateTest extends TestCase
|
||||||
public function testItUpdatesASubscription(): void
|
public function testItUpdatesASubscription(): void
|
||||||
{
|
{
|
||||||
$this->withoutExceptionHandling()->login()->loginNami();
|
$this->withoutExceptionHandling()->login()->loginNami();
|
||||||
$subscription = Subscription::factory()->amount(670)->name('hi')->for(Fee::factory())->create();
|
$subscription = Subscription::factory()->name('hi')->for(Fee::factory())->create();
|
||||||
$fee = Fee::factory()->create();
|
$fee = Fee::factory()->create();
|
||||||
|
|
||||||
$response = $this->from("/subscription/{$subscription->id}")->patch(
|
$response = $this->from("/subscription/{$subscription->id}")->patch(
|
||||||
|
@ -26,17 +27,39 @@ class UpdateTest extends TestCase
|
||||||
$response->assertRedirect('/subscription');
|
$response->assertRedirect('/subscription');
|
||||||
$this->assertDatabaseHas('subscriptions', [
|
$this->assertDatabaseHas('subscriptions', [
|
||||||
'id' => $subscription->id,
|
'id' => $subscription->id,
|
||||||
'amount' => 2500,
|
|
||||||
'fee_id' => $fee->id,
|
'fee_id' => $fee->id,
|
||||||
'name' => 'Lorem',
|
'name' => 'Lorem',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testItUpdatesChildren(): void
|
||||||
|
{
|
||||||
|
$this->withoutExceptionHandling()->login()->loginNami();
|
||||||
|
$subscription = Subscription::factory()->name('hi')->for(Fee::factory())->children([
|
||||||
|
new Child('a', 1400),
|
||||||
|
new Child('b', 1500),
|
||||||
|
])->create();
|
||||||
|
|
||||||
|
$response = $this->from("/subscription/{$subscription->id}")->patch(
|
||||||
|
"/subscription/{$subscription->id}",
|
||||||
|
SubscriptionRequestFactory::new()->children([
|
||||||
|
new Child('c', 1900),
|
||||||
|
])->create()
|
||||||
|
);
|
||||||
|
|
||||||
|
$response->assertRedirect('/subscription');
|
||||||
|
$this->assertDatabaseHas('subscription_children', [
|
||||||
|
'parent_id' => $subscription->id,
|
||||||
|
'name' => 'c',
|
||||||
|
'amount' => 1900,
|
||||||
|
]);
|
||||||
|
$this->assertDatabaseCount('subscription_children', 1);
|
||||||
|
}
|
||||||
|
|
||||||
public function testItValidatesRequest(): void
|
public function testItValidatesRequest(): void
|
||||||
{
|
{
|
||||||
$this->login()->loginNami();
|
$this->login()->loginNami();
|
||||||
$subscription = Subscription::factory()->amount(670)->name('hi')->for(Fee::factory())->create();
|
$subscription = Subscription::factory()->name('hi')->for(Fee::factory())->create();
|
||||||
$fee = Fee::factory()->create();
|
|
||||||
|
|
||||||
$response = $this->from("/subscription/{$subscription->id}")->patch(
|
$response = $this->from("/subscription/{$subscription->id}")->patch(
|
||||||
"/subscription/{$subscription->id}",
|
"/subscription/{$subscription->id}",
|
||||||
|
@ -44,7 +67,6 @@ class UpdateTest extends TestCase
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertErrors([
|
$this->assertErrors([
|
||||||
'amount' => 'Interner Beitrag ist erforderlich.',
|
|
||||||
'fee_id' => 'Nami-Beitrag ist nicht vorhanden.',
|
'fee_id' => 'Nami-Beitrag ist nicht vorhanden.',
|
||||||
'name' => 'Name ist erforderlich.',
|
'name' => 'Name ist erforderlich.',
|
||||||
], $response);
|
], $response);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\RequestFactories;
|
||||||
|
|
||||||
|
class Child
|
||||||
|
{
|
||||||
|
public function __construct(private string $name, private int $amount)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{name: string, amount: int}
|
||||||
|
*/
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'amount' => $this->amount,
|
||||||
|
'name' => $this->name,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,12 +7,15 @@ use Worksome\RequestFactories\RequestFactory;
|
||||||
|
|
||||||
class SubscriptionRequestFactory extends RequestFactory
|
class SubscriptionRequestFactory extends RequestFactory
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, int|string|array<int, array{amount: int, name: string}>>
|
||||||
|
*/
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'amount' => $this->faker->numberBetween(100, 2000),
|
|
||||||
'fee_id' => Fee::factory()->create()->id,
|
'fee_id' => Fee::factory()->create()->id,
|
||||||
'name' => $this->faker->words(5, true),
|
'name' => $this->faker->words(5, true),
|
||||||
|
'children' => [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,9 +37,16 @@ class SubscriptionRequestFactory extends RequestFactory
|
||||||
public function invalid(): self
|
public function invalid(): self
|
||||||
{
|
{
|
||||||
return $this->state([
|
return $this->state([
|
||||||
'amount' => '',
|
|
||||||
'fee_id' => 9999,
|
'fee_id' => 9999,
|
||||||
'name' => '',
|
'name' => '',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, Child> $children
|
||||||
|
*/
|
||||||
|
public function children(array $children): self
|
||||||
|
{
|
||||||
|
return $this->state(['children' => array_map(fn ($child) => $child->toArray(), $children)]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue