diff --git a/app/Invoice/Actions/MemberNewInvoiceAction.php b/app/Invoice/Actions/MemberNewInvoiceAction.php new file mode 100644 index 00000000..a5be9345 --- /dev/null +++ b/app/Invoice/Actions/MemberNewInvoiceAction.php @@ -0,0 +1,46 @@ + + */ + public function rules(): array + { + return [ + 'year' => 'required|integer|gte:0', + 'subscription_id' => 'required|exists:subscriptions,id', + ]; + } + + /** + * @return array + */ + public function handle(Member $member, Subscription $subscription, int $year): array + { + $invoice = Invoice::createForMember($member, Member::where('id', $member->id)->get(), $year, $subscription); + + return [ + ...$invoice->getAttributes(), + 'to' => $invoice->to, + 'positions' => $invoice->getRelationValue('positions')->toArray(), + ]; + } + + public function asController(ActionRequest $request, Member $member): JsonResponse + { + $payload = $this->handle($member, Subscription::find($request->input('subscription_id')), $request->input('year')); + return response()->json($payload); + } +} diff --git a/app/Invoice/Models/Invoice.php b/app/Invoice/Models/Invoice.php index 2890c11b..34166282 100644 --- a/app/Invoice/Models/Invoice.php +++ b/app/Invoice/Models/Invoice.php @@ -8,6 +8,7 @@ use App\Invoice\Enums\InvoiceStatus; use App\Invoice\InvoiceDocument; use App\Invoice\RememberDocument; use App\Member\Member; +use App\Payment\Subscription; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -44,8 +45,9 @@ class Invoice extends Model /** * @param Collection $members */ - public static function createForMember(Member $member, Collection $members, int $year): self + public static function createForMember(Member $member, Collection $members, int $year, Subscription $subscription = null): self { + $subscription = $subscription ?: $member->subscription; $invoice = new self([ 'to' => [ 'name' => 'Familie ' . $member->lastname, @@ -62,7 +64,7 @@ class Invoice extends Model $positions = collect([]); foreach ($members as $member) { - foreach ($member->subscription->children as $child) { + foreach ($subscription->children as $child) { $positions->push([ 'description' => str($child->name)->replace('{name}', $member->firstname . ' ' . $member->lastname)->replace('{year}', (string) $year), 'price' => $child->amount, diff --git a/routes/web.php b/routes/web.php index 95bd5a56..cf53f02e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -34,6 +34,7 @@ use App\Invoice\Actions\InvoiceIndexAction; use App\Invoice\Actions\InvoiceUpdateAction; use App\Invoice\Actions\MassPostPdfAction; use App\Invoice\Actions\MassStoreAction as InvoiceMassStoreAction; +use App\Invoice\Actions\MemberNewInvoiceAction; use App\Invoice\Actions\PaymentPositionIndexAction; use App\Maildispatcher\Actions\CreateAction; use App\Maildispatcher\Actions\DestroyAction; @@ -114,6 +115,7 @@ Route::group(['middleware' => 'auth:web'], function (): void { Route::get('/invoice/{invoice}/pdf', DisplayPdfAction::class)->name('invoice.pdf'); Route::get('/invoice/{invoice}/rememberpdf', DisplayRememberpdfAction::class)->name('invoice.rememberpdf'); Route::get('/invoice/masspdf', MassPostPdfAction::class)->name('invoice.masspdf'); + Route::post('/member/{member}/new-invoice', MemberNewInvoiceAction::class)->name('member.new-invoice'); // ----------------------------- invoice-position ------------------------------ diff --git a/tests/Feature/Invoice/MemberNewInvoiceActionTest.php b/tests/Feature/Invoice/MemberNewInvoiceActionTest.php new file mode 100644 index 00000000..576fb5ab --- /dev/null +++ b/tests/Feature/Invoice/MemberNewInvoiceActionTest.php @@ -0,0 +1,54 @@ +login()->loginNami()->withoutExceptionHandling(); + } + + public function testItReturnsNewInvoiceOfMember(): void + { + $subscription = Subscription::factory()->children([ + new Child('beitrag {name}', 4466), + new Child('beitrag2 für {name} für {year}', 2290), + ])->create(); + $member = Member::factory() + ->defaults() + ->emailBillKind() + ->create(['firstname' => 'Max', 'lastname' => 'Muster', 'address' => 'Maxstr 4', 'zip' => '33445', 'location' => 'Solingen', 'email' => 'lala@b.de']); + + $this->post(route('member.new-invoice', ['member' => $member]), ['year' => 2019, 'subscription_id' => $subscription->id]) + ->assertOk() + ->assertJsonPath('greeting', 'Liebe Familie Muster') + ->assertJsonPath('to.address', 'Maxstr 4') + ->assertJsonPath('to.location', 'Solingen') + ->assertJsonPath('to.zip', '33445') + ->assertJsonPath('to.name', 'Familie Muster') + ->assertJsonPath('usage', 'Mitgliedsbeitrag für Muster') + ->assertJsonPath('via', 'E-Mail') + ->assertJsonPath('mail_email', 'lala@b.de') + ->assertJsonPath('status', 'Neu') + ->assertJsonPath('positions.0.description', 'beitrag Max Muster') + ->assertJsonPath('positions.0.member_id', $member->id) + ->assertJsonPath('positions.0.price', 4466) + ->assertJsonPath('positions.1.description', 'beitrag2 für Max Muster für 2019') + ->assertJsonPath('positions.1.member_id', $member->id) + ->assertJsonPath('positions.1.price', 2290); + + $this->assertDatabaseCount('invoices', 0); + $this->assertDatabaseCount('invoice_positions', 0); + } +}