Add payment_data for payments
This commit is contained in:
parent
fc1b647b54
commit
566ed704a6
|
@ -5,6 +5,7 @@ namespace App\Invoice\Actions;
|
|||
use App\Invoice\BillKind;
|
||||
use App\Invoice\DocumentFactory;
|
||||
use App\Invoice\Queries\BillKindQuery;
|
||||
use App\Payment\Payment;
|
||||
use App\Payment\PaymentMail;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
@ -33,13 +34,13 @@ class InvoiceSendAction
|
|||
public function handle(): int
|
||||
{
|
||||
foreach (app(DocumentFactory::class)->getTypes() as $type) {
|
||||
$invoices = app(DocumentFactory::class)->invoiceCollection($type, new BillKindQuery(BillKind::EMAIL));
|
||||
$memberCollection = (new BillKindQuery(BillKind::EMAIL))->type($type)->getMembers();
|
||||
|
||||
foreach ($invoices as $invoice) {
|
||||
foreach ($memberCollection as $members) {
|
||||
$invoice = $type::fromMembers($members);
|
||||
$invoicePath = Storage::disk('temp')->path(Tex::compile($invoice)->storeIn('', 'temp'));
|
||||
Mail::to($invoice->getRecipient())
|
||||
->send(new PaymentMail($invoice, $invoicePath));
|
||||
app(DocumentFactory::class)->afterSingle($invoice);
|
||||
Mail::to($invoice->getRecipient())->send(new PaymentMail($invoice, $invoicePath));
|
||||
app(DocumentFactory::class)->afterSingle($invoice, $members);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,10 @@ class BillDocument extends Invoice
|
|||
|
||||
public function afterSingle(Payment $payment): void
|
||||
{
|
||||
$payment->update(['status_id' => 2]);
|
||||
$payment->update([
|
||||
'invoice_data' => $this->toArray(),
|
||||
'status_id' => 2,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getMailSubject(): string
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Invoice;
|
||||
|
||||
use App\Invoice\Queries\InvoiceMemberQuery;
|
||||
use App\Member\Member;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class DocumentFactory
|
||||
|
@ -24,44 +24,14 @@ class DocumentFactory
|
|||
}
|
||||
|
||||
/**
|
||||
* @param class-string<Invoice> $type
|
||||
* @param Collection<(int|string), Member> $members
|
||||
*/
|
||||
public function singleInvoice(string $type, InvoiceMemberQuery $query): ?Invoice
|
||||
public function afterSingle(Invoice $invoice, Collection $members): void
|
||||
{
|
||||
$pages = $query->getPages($type);
|
||||
|
||||
if ($pages->isEmpty()) {
|
||||
return null;
|
||||
foreach ($members as $member) {
|
||||
foreach ($member->payments as $payment) {
|
||||
$invoice->afterSingle($payment);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->resolve($type, $pages);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string<Invoice> $type
|
||||
*
|
||||
* @return Collection<int, Invoice>
|
||||
*/
|
||||
public function invoiceCollection(string $type, InvoiceMemberQuery $query): Collection
|
||||
{
|
||||
return $query
|
||||
->getPages($type)
|
||||
->map(fn ($page) => $this->resolve($type, collect([$page])));
|
||||
}
|
||||
|
||||
public function afterSingle(Invoice $invoice): void
|
||||
{
|
||||
foreach ($invoice->allPayments() as $payment) {
|
||||
$invoice->afterSingle($payment);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string<Invoice> $type
|
||||
* @param Collection<int, Page> $pages
|
||||
*/
|
||||
private function resolve(string $type, Collection $pages): Invoice
|
||||
{
|
||||
return new $type($pages);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
|
||||
namespace App\Invoice;
|
||||
|
||||
use App\Member\Member;
|
||||
use App\Payment\Payment;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Generator;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
|
@ -16,11 +15,9 @@ use Zoomyboy\Tex\Template;
|
|||
abstract class Invoice extends Document
|
||||
{
|
||||
abstract public function getSubject(): string;
|
||||
|
||||
abstract public function view(): string;
|
||||
|
||||
abstract public function afterSingle(Payment $payment): void;
|
||||
abstract public function linkLabel(): string;
|
||||
|
||||
abstract public static function sendAllLabel(): string;
|
||||
|
||||
/**
|
||||
|
@ -35,37 +32,46 @@ abstract class Invoice extends Document
|
|||
*/
|
||||
abstract public static function getDescription(): array;
|
||||
|
||||
abstract public function afterSingle(Payment $payment): void;
|
||||
|
||||
/**
|
||||
* @var Collection<int, Page>
|
||||
*/
|
||||
public Collection $pages;
|
||||
public string $subject;
|
||||
protected string $filename;
|
||||
public string $until;
|
||||
public InvoiceSettings $settings;
|
||||
public string $filename;
|
||||
|
||||
/**
|
||||
* @param Collection<int, Page> $pages
|
||||
* @param array<string, string> $positions
|
||||
*/
|
||||
public function __construct(Collection $pages)
|
||||
{
|
||||
$this->pages = $pages;
|
||||
$this->subject = $this->getSubject();
|
||||
public function __construct(
|
||||
public string $familyName,
|
||||
public string $singleName,
|
||||
public string $address,
|
||||
public string $zip,
|
||||
public string $location,
|
||||
public array $positions,
|
||||
public string $usage,
|
||||
public ?string $email,
|
||||
) {
|
||||
$this->until = now()->addWeeks(2)->format('d.m.Y');
|
||||
$this->setFilename(Str::slug("{$this->getSubject()} für {$pages->first()?->familyName}"));
|
||||
$this->settings = app(InvoiceSettings::class);
|
||||
$this->filename = Str::slug("{$this->getSubject()} für {$familyName}");
|
||||
}
|
||||
|
||||
public function number(int $number): string
|
||||
/**
|
||||
* @param Collection<(int|string), Member> $members
|
||||
*/
|
||||
public static function fromMembers(Collection $members): self
|
||||
{
|
||||
return number_format($number / 100, 2, '.', '');
|
||||
return static::withoutMagicalCreationFrom([
|
||||
'familyName' => $members->first()->lastname,
|
||||
'singleName' => $members->first()->lastname,
|
||||
'address' => $members->first()->address,
|
||||
'zip' => $members->first()->zip,
|
||||
'location' => $members->first()->location,
|
||||
'email' => $members->first()->email_parents ?: $members->first()->email,
|
||||
'positions' => static::renderPositions($members),
|
||||
'usage' => "Mitgliedsbeitrag für {$members->first()->lastname}",
|
||||
]);
|
||||
}
|
||||
|
||||
public function getUntil(): Carbon
|
||||
public function settings(): InvoiceSettings
|
||||
{
|
||||
return now()->addWeeks(2);
|
||||
return app(InvoiceSettings::class);
|
||||
}
|
||||
|
||||
public function getEngine(): Engine
|
||||
|
@ -92,20 +98,9 @@ abstract class Invoice extends Document
|
|||
|
||||
public function getRecipient(): MailRecipient
|
||||
{
|
||||
if (!$this->pages->first()?->email) {
|
||||
throw new Exception('Cannot get Recipient. Mail not set.');
|
||||
}
|
||||
throw_unless($this->email, Exception::class, 'Cannot get Recipient. Mail not set.');
|
||||
|
||||
return new MailRecipient($this->pages->first()->email, $this->pages->first()->familyName);
|
||||
}
|
||||
|
||||
public function allPayments(): Generator
|
||||
{
|
||||
foreach ($this->pages as $page) {
|
||||
foreach ($page->getPayments() as $payment) {
|
||||
yield $payment;
|
||||
}
|
||||
}
|
||||
return new MailRecipient($this->email, $this->familyName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,12 +108,38 @@ abstract class Invoice extends Document
|
|||
*/
|
||||
public function mailView(): string
|
||||
{
|
||||
$view = 'mail.payment.'.Str::snake(class_basename($this));
|
||||
$view = 'mail.payment.' . Str::snake(class_basename($this));
|
||||
|
||||
if (!view()->exists($view)) {
|
||||
throw new Exception('Mail view '.$view.' existiert nicht.');
|
||||
}
|
||||
throw_unless(view()->exists($view), Exception::class, 'Mail view ' . $view . ' existiert nicht.');
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int|string, Member> $members
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public static function renderPositions(Collection $members): array
|
||||
{
|
||||
/** @var array<string, string> */
|
||||
$result = [];
|
||||
|
||||
foreach ($members->pluck('payments')->flatten(1) as $payment) {
|
||||
if ($payment->subscription->split) {
|
||||
foreach ($payment->subscription->children as $child) {
|
||||
$result["{$payment->subscription->name} ({$child->name}) {$payment->nr} für {$payment->member->firstname} {$payment->member->lastname}"] = static::number($child->amount);
|
||||
}
|
||||
} else {
|
||||
$result["{$payment->subscription->name} {$payment->nr} für {$payment->member->firstname} {$payment->member->lastname}"] = static::number($payment->subscription->getAmount());
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function number(int $number): string
|
||||
{
|
||||
return number_format($number / 100, 2, '.', '');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Invoice;
|
||||
|
||||
use App\Member\Member;
|
||||
use App\Payment\Payment;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class Page
|
||||
{
|
||||
/**
|
||||
* @var Collection<int, Member>
|
||||
*/
|
||||
private Collection $members;
|
||||
public string $familyName;
|
||||
public string $singleName;
|
||||
public string $address;
|
||||
public string $zip;
|
||||
public string $location;
|
||||
public string $usage;
|
||||
public ?string $email;
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public array $positions;
|
||||
|
||||
/**
|
||||
* @param Collection<int, Member> $members
|
||||
*/
|
||||
public function __construct(Collection $members)
|
||||
{
|
||||
$this->members = $members;
|
||||
$this->familyName = $this->members->first()->lastname;
|
||||
$this->singleName = $members->first()->lastname;
|
||||
$this->address = $members->first()->address;
|
||||
$this->zip = $members->first()->zip;
|
||||
$this->location = $members->first()->location;
|
||||
$this->email = $members->first()->email_parents ?: $members->first()->email;
|
||||
$this->positions = $this->getPositions();
|
||||
$this->usage = "Mitgliedsbeitrag für {$this->familyName}";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getPositions(): array
|
||||
{
|
||||
/** @var array<string, string> */
|
||||
$result = [];
|
||||
|
||||
foreach ($this->getPayments() as $payment) {
|
||||
if ($payment->subscription->split) {
|
||||
foreach ($payment->subscription->children as $child) {
|
||||
$result["{$payment->subscription->name} ({$child->name}) {$payment->nr} für {$payment->member->firstname} {$payment->member->lastname}"] = $this->number($child->amount);
|
||||
}
|
||||
} else {
|
||||
$result["{$payment->subscription->name} {$payment->nr} für {$payment->member->firstname} {$payment->member->lastname}"] = $this->number($payment->subscription->getAmount());
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Payment>
|
||||
*/
|
||||
public function getPayments(): Collection
|
||||
{
|
||||
return $this->members->pluck('payments')->flatten(1);
|
||||
}
|
||||
|
||||
public function number(int $number): string
|
||||
{
|
||||
return number_format($number / 100, 2, '.', '');
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Invoice\Queries;
|
||||
|
||||
use App\Invoice\Invoice;
|
||||
use App\Invoice\Page;
|
||||
use App\Member\Member;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
|
||||
|
@ -12,35 +11,46 @@ use Illuminate\Support\Str;
|
|||
|
||||
abstract class InvoiceMemberQuery
|
||||
{
|
||||
/**
|
||||
* @param class-string<Invoice> $type
|
||||
*/
|
||||
public string $type;
|
||||
|
||||
/**
|
||||
* @return Builder<Member>
|
||||
*/
|
||||
abstract protected function getQuery(): Builder;
|
||||
|
||||
/**
|
||||
* @param class-string<Invoice> $type
|
||||
*
|
||||
* @return Collection<int, Page>
|
||||
* @return Collection<(int|string), EloquentCollection<(int|string), Member>>
|
||||
*/
|
||||
public function getPages(string $type): Collection
|
||||
public function getMembers(): Collection
|
||||
{
|
||||
return $this->get($type)->groupBy(
|
||||
return $this->get()->groupBy(
|
||||
fn ($member) => Str::slug(
|
||||
"{$member->lastname}{$member->address}{$member->zip}{$member->location}",
|
||||
),
|
||||
)->map(fn ($page) => new Page($page));
|
||||
)->toBase();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string<Invoice> $type
|
||||
*
|
||||
*/
|
||||
public function type(string $type): self
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EloquentCollection<int, Member>
|
||||
*/
|
||||
private function get(string $type): EloquentCollection
|
||||
private function get(): EloquentCollection
|
||||
{
|
||||
return $this->getQuery()
|
||||
->with([
|
||||
'payments' => fn ($query) => $type::paymentsQuery($query)
|
||||
'payments' => fn ($query) => $this->type::paymentsQuery($query)
|
||||
->orderByRaw('nr, member_id'),
|
||||
])
|
||||
->get()
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Invoice\Queries;
|
||||
|
||||
use App\Member\Member;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class SingleMemberQuery extends InvoiceMemberQuery
|
||||
{
|
||||
public function __construct(
|
||||
private Member $member
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<Member>
|
||||
*/
|
||||
protected function getQuery(): Builder
|
||||
{
|
||||
return Member::where($this->member->only(['lastname', 'address', 'zip', 'location']));
|
||||
}
|
||||
}
|
|
@ -12,7 +12,18 @@ class Payment extends Model
|
|||
{
|
||||
use HasFactory;
|
||||
|
||||
public $fillable = ['member_id', 'subscription_id', 'nr', 'status_id', 'last_remembered_at'];
|
||||
/**
|
||||
* @var array<int, string>
|
||||
*/
|
||||
public $fillable = ['member_id', 'invoice_data', 'subscription_id', 'nr', 'status_id', 'last_remembered_at'];
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public $casts = [
|
||||
'invoice_data' => 'json',
|
||||
'last_remembered_at' => 'date',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Member, self>
|
||||
|
|
|
@ -25,7 +25,7 @@ class PaymentMail extends Mailable
|
|||
{
|
||||
$this->invoice = $invoice;
|
||||
$this->filename = $filename;
|
||||
$this->salutation = 'Liebe Familie ' . $invoice->pages->first()->familyName;
|
||||
$this->salutation = 'Liebe Familie ' . $invoice->familyName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Payment;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Invoice\BillDocument;
|
||||
use App\Invoice\BillKind;
|
||||
use App\Invoice\DocumentFactory;
|
||||
use App\Invoice\Queries\BillKindQuery;
|
||||
|
@ -30,15 +31,19 @@ class SendpaymentController extends Controller
|
|||
*/
|
||||
public function send(Request $request)
|
||||
{
|
||||
$invoice = app(DocumentFactory::class)->singleInvoice($request->type, new BillKindQuery(BillKind::POST));
|
||||
$memberCollection = (new BillKindQuery(BillKind::POST))->type($request->type)->getMembers();
|
||||
|
||||
if (is_null($invoice)) {
|
||||
if ($memberCollection->isEmpty()) {
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
$pdfFile = Tex::compile($invoice);
|
||||
app(DocumentFactory::class)->afterSingle($invoice);
|
||||
$documents = $memberCollection->map(function ($members) use ($request) {
|
||||
$document = $request->type::fromMembers($members);
|
||||
app(DocumentFactory::class)->afterSingle($document, $members);
|
||||
return $document;
|
||||
});
|
||||
|
||||
return $pdfFile;
|
||||
|
||||
return Tex::merge($documents->all());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Pdf;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Invoice\DocumentFactory;
|
||||
use App\Invoice\Queries\SingleMemberQuery;
|
||||
use App\Member\Member;
|
||||
use Illuminate\Contracts\Support\Responsable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Zoomyboy\Tex\Tex;
|
||||
|
||||
class MemberPdfController extends Controller
|
||||
{
|
||||
/**
|
||||
* @return Response|Responsable
|
||||
*/
|
||||
public function __invoke(Request $request, Member $member)
|
||||
{
|
||||
$invoice = app(DocumentFactory::class)->singleInvoice($request->type, new SingleMemberQuery($member));
|
||||
|
||||
return null === $invoice
|
||||
? response()->noContent()
|
||||
: Tex::compile($invoice);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -7,6 +7,7 @@ use App\Payment\Payment;
|
|||
use App\Payment\Status;
|
||||
use App\Payment\Subscription;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Tests\RequestFactories\Child;
|
||||
|
||||
/**
|
||||
|
@ -22,7 +23,7 @@ class PaymentFactory extends Factory
|
|||
'nr' => $this->faker->year,
|
||||
'subscription_id' => Subscription::factory()->create()->id,
|
||||
'status_id' => Status::factory()->create()->id,
|
||||
'last_remembered_at' => $this->faker->dateTime,
|
||||
'last_remembered_at' => now(),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -31,6 +32,11 @@ class PaymentFactory extends Factory
|
|||
return $this->for(Status::whereName('Nicht bezahlt')->first());
|
||||
}
|
||||
|
||||
public function pending(): self
|
||||
{
|
||||
return $this->for(Status::whereName('Rechnung gestellt')->first())->state(['last_remembered_at' => now()->subYears(2)]);;
|
||||
}
|
||||
|
||||
public function paid(): self
|
||||
{
|
||||
return $this->for(Status::whereName('Rechnung beglichen')->first());
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
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()
|
||||
{
|
||||
Schema::table('payments', function (Blueprint $table) {
|
||||
$table->json('invoice_data')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('payments', function (Blueprint $table) {
|
||||
$table->dropColumn('invoice_data');
|
||||
});
|
||||
}
|
||||
};
|
|
@ -1 +1 @@
|
|||
Subproject commit c5ea29af1bb1591238bb037da93739f5bd874334
|
||||
Subproject commit af626f5d3a14a365e97dc6437025a0b1da6b42bc
|
|
@ -1 +1 @@
|
|||
Subproject commit 6f162102ef7ceca41822d18c3e694abd926f550b
|
||||
Subproject commit bbab104f7e00c059ffffa115f6b769e2333e137a
|
85
phpstan.neon
85
phpstan.neon
|
@ -304,91 +304,6 @@ parameters:
|
|||
count: 1
|
||||
path: packages/laravel-nami/src/Gender.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:__construct\\(\\) has parameter \\$options with no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:__construct\\(\\) has parameter \\$response with no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:__construct\\(\\) has parameter \\$title with no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:__construct\\(\\) has parameter \\$url with no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:fromHttp\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:http\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:http\\(\\) has parameter \\$options with no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:http\\(\\) has parameter \\$response with no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:http\\(\\) has parameter \\$title with no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:http\\(\\) has parameter \\$url with no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:level\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Property Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:\\$errors has no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Property Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:\\$options has no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Property Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:\\$response has no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Property Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:\\$title has no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Property Zoomyboy\\\\LaravelNami\\\\Logger\\:\\:\\$url has no type specified\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Unsafe usage of new static\\(\\)\\.$#"
|
||||
count: 1
|
||||
path: packages/laravel-nami/src/Logger.php
|
||||
|
||||
-
|
||||
message: "#^Method Zoomyboy\\\\LaravelNami\\\\LoginException\\:\\:setReason\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
\documentclass[silvaletter,12pt]{scrlttr2}
|
||||
|
||||
\setkomavar{subject}{<<< $subject >>>}
|
||||
\setkomavar{subject}{<<< $getSubject >>>}
|
||||
\setkomavar{fromname}[<<<$settings->from>>>]{<<<$settings->from_long>>>}
|
||||
\setkomavar{frommobilephone}[Mobiltelefon: ]{<<<$settings->mobile>>>}
|
||||
\setkomavar{fromemail}[E-Mail: ]{<<<$settings->email>>>}
|
||||
|
@ -11,17 +11,16 @@
|
|||
\setkomavar{fromlogo}{\includegraphics[width=2cm]{logo.png}} % stammeslogo
|
||||
|
||||
\begin{document}
|
||||
@foreach($pages as $page)
|
||||
\begin{letter}{Familie <<< $page->familyName >>>\\<<< $page->address >>>\\<<< $page->zip >>> <<< $page->location >>>}
|
||||
\begin{letter}{Familie <<< $familyName >>>\\<<< $address >>>\\<<< $zip >>> <<< $location >>>}
|
||||
\sffamily
|
||||
\gdef\TotalHT{0}
|
||||
\opening{Liebe Familie <<< $page->familyName >>>,}
|
||||
\opening{Liebe Familie <<< $familyName >>>,}
|
||||
|
||||
Hiermit stellen wir Ihnen den aktuellen Mitgliedsbeitrag für den \usekomavar*{fromname} und die DPSG in Rechnung. Dieser setzt sich wie folgt zusammen:
|
||||
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{0.8\textwidth}|r}
|
||||
@foreach($page->positions as $desc => $price)
|
||||
@foreach($positions as $desc => $price)
|
||||
\product{<<< $desc >>>}{<<< $price >>>}
|
||||
@endforeach
|
||||
\hline
|
||||
|
@ -35,15 +34,14 @@
|
|||
Kontoinhaber: & <<<$settings->from_long>>> \\
|
||||
IBAN: & <<<$settings->iban>>> \\
|
||||
Bic: & <<<$settings->bic>>> \\
|
||||
Verwendungszweck: & <<<$page->usage>>>
|
||||
Verwendungszweck: & <<<$usage>>>
|
||||
\end{tabular}
|
||||
|
||||
Bitte nehmen Sie zur Kenntnis, dass der für jedes Mitglied obligatorische Versicherungsschutz über die DPSG nur dann für Ihr Kind / Ihre Kinder gilt, wenn der Mitgliedsbeitrag bezahlt wurde. Wenn dies nicht geschieht, müssen wir Ihr Kind / Ihre Kinder von allen Pfadfinderaktionen ausschließen. Dazu gehören sowohl die Gruppenstunden sowie Tagesaktionen als auch mehrtägige Lager.
|
||||
|
||||
|
||||
Bei Fragen zur Rechnung können Sie mich auch persönlich erreichen.
|
||||
|
||||
\closing{Viele Grüße \\ Der Stammesvorstand}
|
||||
\end{letter}
|
||||
@endforeach
|
||||
\end{document}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
\documentclass[silvaletter,12pt]{scrlttr2}
|
||||
|
||||
\setkomavar{subject}{<<< $subject >>>}
|
||||
\setkomavar{subject}{<<< $getSubject >>>}
|
||||
\setkomavar{fromname}[<<<$settings->from>>>]{<<<$settings->from_long>>>}
|
||||
\setkomavar{frommobilephone}[Mobiltelefon: ]{<<<$settings->mobile>>>}
|
||||
\setkomavar{fromemail}[E-Mail: ]{<<<$settings->email>>>}
|
||||
|
@ -11,17 +11,16 @@
|
|||
\setkomavar{fromlogo}{\includegraphics[width=2cm]{logo.png}} % stammeslogo
|
||||
|
||||
\begin{document}
|
||||
@foreach($pages as $page)
|
||||
\begin{letter}{Familie <<< $page->familyName >>>\\<<< $page->address >>>\\<<< $page->zip >>> <<< $page->location >>>}
|
||||
\begin{letter}{Familie <<< $familyName >>>\\<<< $address >>>\\<<< $zip >>> <<< $location >>>}
|
||||
\sffamily
|
||||
\gdef\TotalHT{0}
|
||||
\opening{Liebe Familie <<< $page->familyName >>>,}
|
||||
\opening{Liebe Familie <<< $familyName >>>,}
|
||||
|
||||
Ihr Mitgliedbeitrag ist noch ausstehend. Dieser setzt sich wie folgt zusammen:
|
||||
|
||||
\begin{center}
|
||||
\begin{tabular}{@{}p{0.8\textwidth}|r}
|
||||
@foreach($page->positions as $desc => $price)
|
||||
@foreach($positions as $desc => $price)
|
||||
\product{<<< $desc >>>}{<<< $price >>>}
|
||||
@endforeach
|
||||
\hline
|
||||
|
@ -35,15 +34,14 @@
|
|||
Kontoinhaber: & <<<$settings->from_long>>> \\
|
||||
IBAN: & <<<$settings->iban>>> \\
|
||||
Bic: & <<<$settings->bic>>> \\
|
||||
Verwendungszweck: & <<<$page->usage>>>
|
||||
Verwendungszweck: & <<<$usage>>>
|
||||
\end{tabular}
|
||||
|
||||
Bitte nehmen Sie zur Kenntnis, dass der für jedes Mitglied obligatorische Versicherungsschutz über die DPSG nur dann für Ihr Kind / Ihre Kinder gilt, wenn der Mitgliedsbeitrag bezahlt wurde. Wenn dies nicht geschieht, müssen wir Ihr Kind / Ihre Kinder von allen Pfadfinderaktionen ausschließen. Dazu gehören sowohl die Gruppenstunden sowie Tagesaktionen als auch mehrtägige Lager.
|
||||
|
||||
|
||||
Bei Fragen zur Rechnung können Sie mich auch persönlich erreichen.
|
||||
|
||||
\closing{Viele Grüße \\ Der Stammesvorstand}
|
||||
\end{letter}
|
||||
@endforeach
|
||||
\end{document}
|
||||
|
||||
|
|
|
@ -52,7 +52,6 @@ use App\Payment\Actions\PaymentStoreAction;
|
|||
use App\Payment\Actions\PaymentUpdateAction;
|
||||
use App\Payment\SendpaymentController;
|
||||
use App\Payment\SubscriptionController;
|
||||
use App\Pdf\MemberPdfController;
|
||||
|
||||
Route::group(['namespace' => 'App\\Http\\Controllers'], function (): void {
|
||||
Auth::routes(['register' => false]);
|
||||
|
@ -71,8 +70,6 @@ Route::group(['middleware' => 'auth:web'], function (): void {
|
|||
Route::get('allpayment', AllpaymentPageAction::class)->name('allpayment.page');
|
||||
Route::post('allpayment', AllpaymentStoreAction::class)->name('allpayment.store');
|
||||
Route::resource('subscription', SubscriptionController::class);
|
||||
Route::get('/member/{member}/pdf', MemberPdfController::class)
|
||||
->name('member.singlepdf');
|
||||
Route::get('/sendpayment', [SendpaymentController::class, 'create'])->name('sendpayment.create');
|
||||
Route::get('/sendpayment/pdf', [SendpaymentController::class, 'send'])->name('sendpayment.pdf');
|
||||
Route::get('/member/{member}/efz', ShowEfzDocumentAction::class)->name('efz');
|
||||
|
|
|
@ -3,8 +3,11 @@
|
|||
namespace Tests\Feature\Invoice;
|
||||
|
||||
use App\Invoice\BillDocument;
|
||||
use App\Invoice\BillKind;
|
||||
use App\Invoice\DocumentFactory;
|
||||
use App\Invoice\Invoice;
|
||||
use App\Invoice\InvoiceSettings;
|
||||
use App\Invoice\Queries\BillKindQuery;
|
||||
use App\Invoice\Queries\InvoiceMemberQuery;
|
||||
use App\Invoice\Queries\SingleMemberQuery;
|
||||
use App\Invoice\RememberDocument;
|
||||
|
@ -15,7 +18,7 @@ use Tests\RequestFactories\Child;
|
|||
use Tests\TestCase;
|
||||
use Zoomyboy\Tex\Tex;
|
||||
|
||||
class DocumentFactoryTest extends TestCase
|
||||
class BillRememberDocumentTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
|
@ -30,13 +33,14 @@ class DocumentFactoryTest extends TestCase
|
|||
'zip' => '::zip::',
|
||||
'location' => '::location::',
|
||||
])
|
||||
->postBillKind()
|
||||
->has(Payment::factory()->notPaid()->nr('1995')->subscription('::subName::', [
|
||||
new Child('a', 1000),
|
||||
new Child('a', 500),
|
||||
]))
|
||||
->create();
|
||||
|
||||
$invoice = app(DocumentFactory::class)->singleInvoice(BillDocument::class, $this->query($member));
|
||||
$invoice = BillDocument::fromMembers($this->query(BillDocument::class)->getMembers()->first());
|
||||
|
||||
$invoice->assertHasAllContent([
|
||||
'Rechnung',
|
||||
|
@ -51,6 +55,7 @@ class DocumentFactoryTest extends TestCase
|
|||
{
|
||||
$member = Member::factory()
|
||||
->defaults()
|
||||
->postBillKind()
|
||||
->state([
|
||||
'firstname' => '::firstname::',
|
||||
'lastname' => '::lastname::',
|
||||
|
@ -61,7 +66,7 @@ class DocumentFactoryTest extends TestCase
|
|||
], ['split' => true]))
|
||||
->create();
|
||||
|
||||
$invoice = app(DocumentFactory::class)->singleInvoice(BillDocument::class, $this->query($member));
|
||||
$invoice = BillDocument::fromMembers($this->query(BillDocument::class)->getMembers()->first());
|
||||
|
||||
$invoice->assertHasAllContent([
|
||||
'Rechnung',
|
||||
|
@ -75,46 +80,48 @@ class DocumentFactoryTest extends TestCase
|
|||
|
||||
public function testBillSetsFilename(): void
|
||||
{
|
||||
$member = Member::factory()
|
||||
Member::factory()
|
||||
->defaults()
|
||||
->postBillKind()
|
||||
->state(['lastname' => '::lastname::'])
|
||||
->has(Payment::factory()->notPaid()->nr('1995'))
|
||||
->create();
|
||||
|
||||
$invoice = app(DocumentFactory::class)->singleInvoice(BillDocument::class, $this->query($member));
|
||||
$invoice = BillDocument::fromMembers($this->query(BillDocument::class)->getMembers()->first());
|
||||
|
||||
$this->assertEquals('rechnung-fur-lastname.pdf', $invoice->compiledFilename());
|
||||
}
|
||||
|
||||
public function testRememberSetsFilename(): void
|
||||
{
|
||||
$member = Member::factory()
|
||||
Member::factory()
|
||||
->postBillKind()
|
||||
->defaults()
|
||||
->state(['lastname' => '::lastname::'])
|
||||
->has(Payment::factory()->notPaid()->state(['last_remembered_at' => now()->subMonths(6)]))
|
||||
->create();
|
||||
|
||||
$invoice = app(DocumentFactory::class)->singleInvoice(RememberDocument::class, $this->query($member));
|
||||
$invoice = RememberDocument::fromMembers($this->query(RememberDocument::class)->getMembers()->first());
|
||||
|
||||
$this->assertEquals('zahlungserinnerung-fur-lastname.pdf', $invoice->compiledFilename());
|
||||
}
|
||||
|
||||
public function testItCreatesOneFileForFamilyMembers(): void
|
||||
{
|
||||
$firstMember = Member::factory()
|
||||
Member::factory()
|
||||
->defaults()
|
||||
->postBillKind()
|
||||
->state(['firstname' => 'Max1', 'lastname' => '::lastname::', 'address' => '::address::', 'zip' => '12345', 'location' => '::location::'])
|
||||
->has(Payment::factory()->notPaid()->nr('nr1'))
|
||||
->create();
|
||||
Member::factory()
|
||||
->defaults()
|
||||
->postBillKind()
|
||||
->state(['firstname' => 'Max2', 'lastname' => '::lastname::', 'address' => '::address::', 'zip' => '12345', 'location' => '::location::'])
|
||||
->has(Payment::factory()->notPaid()->nr('nr2'))
|
||||
->create();
|
||||
|
||||
$invoice = app(DocumentFactory::class)->singleInvoice(BillDocument::class, $this->query($firstMember));
|
||||
|
||||
$invoice->assertHasAllContent(['Max1', 'Max2', 'nr1', 'nr2']);
|
||||
$this->assertCount(2, $this->query(BillDocument::class)->getMembers()->first());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,12 +142,13 @@ class DocumentFactoryTest extends TestCase
|
|||
'iban' => 'DE444',
|
||||
'bic' => 'SOLSSSSS',
|
||||
]);
|
||||
$member = Member::factory()
|
||||
Member::factory()
|
||||
->defaults()
|
||||
->has(Payment::factory()->notPaid()->nr('nr2'))
|
||||
->postBillKind()
|
||||
->has(Payment::factory()->notPaid()->nr('nr2')->state(['last_remembered_at' => now()->subYear()]))
|
||||
->create();
|
||||
|
||||
$invoice = app(DocumentFactory::class)->singleInvoice($type, $this->query($member));
|
||||
$invoice = BillDocument::fromMembers($this->query(BillDocument::class)->getMembers()->first());
|
||||
|
||||
$invoice->assertHasAllContent([
|
||||
'langer Stammesname',
|
||||
|
@ -156,26 +164,11 @@ class DocumentFactoryTest extends TestCase
|
|||
]);
|
||||
}
|
||||
|
||||
public function testItGeneratesAPdf(): void
|
||||
/**
|
||||
* @param class-string<Invoice> $type
|
||||
*/
|
||||
private function query(string $type): InvoiceMemberQuery
|
||||
{
|
||||
Tex::fake();
|
||||
$member = Member::factory()
|
||||
->defaults()
|
||||
->has(Payment::factory()->notPaid())
|
||||
->create(['lastname' => 'lastname']);
|
||||
$this->withoutExceptionHandling();
|
||||
$this->login()->init()->loginNami();
|
||||
|
||||
$response = $this->call('GET', "/member/{$member->id}/pdf", [
|
||||
'type' => BillDocument::class,
|
||||
]);
|
||||
|
||||
$this->assertEquals('application/pdf', $response->headers->get('content-type'));
|
||||
$this->assertEquals('inline; filename="rechnung-fur-lastname.pdf"', $response->headers->get('content-disposition'));
|
||||
}
|
||||
|
||||
private function query(Member $member): InvoiceMemberQuery
|
||||
{
|
||||
return new SingleMemberQuery($member);
|
||||
return (new BillKindQuery(BillKind::POST))->type($type);
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ use App\Member\Member;
|
|||
use App\Payment\Payment;
|
||||
use App\Payment\PaymentMail;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Tests\RequestFactories\Child;
|
||||
|
@ -19,42 +18,29 @@ class InvoiceSendActionTest extends TestCase
|
|||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
public Member $member;
|
||||
|
||||
public function setUp(): void
|
||||
public function testItCanCreatePdfPayments(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Mail::fake();
|
||||
Tex::spy();
|
||||
Storage::fake('temp');
|
||||
$this->withoutExceptionHandling();
|
||||
$this->login()->loginNami();
|
||||
$this->member = Member::factory()
|
||||
$member = Member::factory()
|
||||
->defaults()
|
||||
->has(Payment::factory()->notPaid()->nr('1997')->subscription('tollerbeitrag', [
|
||||
new Child('a', 5400),
|
||||
]))
|
||||
->emailBillKind()
|
||||
->create(['firstname' => 'Lah', 'lastname' => 'Mom', 'email' => 'peter@example.com']);
|
||||
}
|
||||
|
||||
public function testItCanCreatePdfPayments(): void
|
||||
{
|
||||
Mail::fake();
|
||||
|
||||
Artisan::call('invoice:send');
|
||||
|
||||
Mail::assertSent(PaymentMail::class, fn ($mail) => Storage::disk('temp')->path('rechnung-fur-mom.pdf') === $mail->filename && Storage::disk('temp')->exists('rechnung-fur-mom.pdf'));
|
||||
}
|
||||
|
||||
public function testItCanCompileAttachment(): void
|
||||
{
|
||||
Mail::fake();
|
||||
Tex::spy();
|
||||
|
||||
InvoiceSendAction::run();
|
||||
|
||||
Tex::assertCompiled(BillDocument::class, fn ($document) => 'Mom' === $document->pages->first()->familyName
|
||||
&& $document->pages->first()->getPositions() === ['tollerbeitrag 1997 für Lah Mom' => '54.00']
|
||||
Mail::assertSent(PaymentMail::class, fn ($mail) => Storage::disk('temp')->path('rechnung-fur-mom.pdf') === $mail->filename && Storage::disk('temp')->exists('rechnung-fur-mom.pdf'));
|
||||
Tex::assertCompiled(
|
||||
BillDocument::class,
|
||||
fn ($document) => 'Mom' === $document->familyName
|
||||
&& $document->positions === ['tollerbeitrag 1997 für Lah Mom' => '54.00']
|
||||
);
|
||||
Tex::assertCompiledContent(BillDocument::class, BillDocument::from($member->payments->first()->invoice_data)->renderBody());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
namespace Tests\Feature\Sendpayment;
|
||||
|
||||
use App\Invoice\BillDocument;
|
||||
use App\Invoice\BillKind;
|
||||
use App\Invoice\DocumentFactory;
|
||||
use App\Invoice\InvoiceSettings;
|
||||
use App\Invoice\Queries\BillKindQuery;
|
||||
use App\Invoice\Queries\SingleMemberQuery;
|
||||
use App\Invoice\RememberDocument;
|
||||
use App\Member\Member;
|
||||
use App\Payment\Payment;
|
||||
use App\Payment\Status;
|
||||
|
@ -30,27 +35,81 @@ class SendpaymentTest extends TestCase
|
|||
$this->assertStringContainsString('BillDocument', $href);
|
||||
}
|
||||
|
||||
public function testItDownloadsPdfOfAllMembersForBill(): void
|
||||
{
|
||||
InvoiceSettings::fake(InvoiceSettingsFake::new()->create());
|
||||
$this->withoutExceptionHandling()->login()->loginNami();
|
||||
Member::factory()->defaults()->postBillKind()->count(3)
|
||||
->has(Payment::factory()->notPaid()->subscription('tollerbeitrag', [new Child('a', 5400)]))
|
||||
->create();
|
||||
|
||||
$response = $this->call('GET', route('sendpayment.pdf'), ['type' => 'App\\Invoice\\BillDocument']);
|
||||
$response->assertOk();
|
||||
$this->assertPdfPageCount(3, $response->getFile());
|
||||
}
|
||||
|
||||
public function testItDownloadsPdfOfAllMembersForRemember(): void
|
||||
{
|
||||
InvoiceSettings::fake(InvoiceSettingsFake::new()->create());
|
||||
$this->withoutExceptionHandling()->login()->loginNami();
|
||||
Member::factory()->defaults()->postBillKind()->count(3)
|
||||
->has(Payment::factory()->pending()->subscription('tollerbeitrag', [new Child('a', 5400)]))
|
||||
->create();
|
||||
|
||||
$response = $this->call('GET', route('sendpayment.pdf'), ['type' => 'App\\Invoice\\RememberDocument']);
|
||||
$response->assertOk();
|
||||
$this->assertPdfPageCount(3, $response->getFile());
|
||||
}
|
||||
|
||||
public function testItCanCreatePdfPayments(): void
|
||||
{
|
||||
InvoiceSettings::fake(InvoiceSettingsFake::new()->create());
|
||||
Tex::spy();
|
||||
$this->withoutExceptionHandling();
|
||||
$this->login()->loginNami();
|
||||
$member = Member::factory()
|
||||
$this->withoutExceptionHandling()->login()->loginNami();
|
||||
$members = Member::factory()
|
||||
->defaults()
|
||||
->has(Payment::factory()->notPaid()->nr('1997')->subscription('tollerbeitrag', [new Child('a', 5400)]))
|
||||
->has(Payment::factory()->paid()->nr('1998')->subscription('bezahltdesc', [new Child('b', 5800)]))
|
||||
->postBillKind()
|
||||
->count(3)
|
||||
->create();
|
||||
$member = $members->first();
|
||||
|
||||
$response = $this->call('GET', route('sendpayment.pdf'), ['type' => 'App\\Invoice\\BillDocument']);
|
||||
|
||||
$response->assertOk();
|
||||
$this->call('GET', route('sendpayment.pdf'), ['type' => 'App\\Invoice\\BillDocument']);
|
||||
$this->assertEquals(Status::firstWhere('name', 'Rechnung gestellt')->id, $member->payments->firstWhere('nr', '1997')->status_id);
|
||||
$this->assertEquals(Status::firstWhere('name', 'Rechnung beglichen')->id, $member->payments->firstWhere('nr', '1998')->status_id);
|
||||
Tex::assertCompiled(BillDocument::class, fn ($document) => $document->hasAllContent(['1997', 'tollerbeitrag', '54.00'])
|
||||
&& $document->missesAllContent(['1998', 'bezahltdesc', '58.00'])
|
||||
Tex::assertCompiled(
|
||||
BillDocument::class,
|
||||
fn ($document) => $document->hasAllContent(['1997', 'tollerbeitrag', '54.00'])
|
||||
&& $document->missesAllContent(['1998', 'bezahltdesc', '58.00'])
|
||||
);
|
||||
|
||||
$member->payments->firstWhere('nr', '1997')->update(['status_id' => Status::firstWhere('name', 'Nicht bezahlt')->id]);
|
||||
$invoice = BillDocument::fromMembers((new BillKindQuery(BillKind::POST))->type(BillDocument::class)->getMembers()->first());
|
||||
$this->assertEquals(
|
||||
BillDocument::from($member->payments->firstWhere('nr', '1997')->invoice_data)->renderBody(),
|
||||
$invoice->renderBody()
|
||||
);
|
||||
}
|
||||
|
||||
public function testItCanCreatePdfPaymentsForRemember(): void
|
||||
{
|
||||
InvoiceSettings::fake(InvoiceSettingsFake::new()->create());
|
||||
Tex::spy();
|
||||
$this->withoutExceptionHandling()->login()->loginNami();
|
||||
$member = Member::factory()
|
||||
->defaults()
|
||||
->has(Payment::factory()->pending()->nr('1997')->subscription('tollerbeitrag', [new Child('a', 5400)]))
|
||||
->postBillKind()
|
||||
->create();
|
||||
|
||||
$this->call('GET', route('sendpayment.pdf'), ['type' => 'App\\Invoice\\RememberDocument']);
|
||||
Tex::assertCompiled(
|
||||
RememberDocument::class,
|
||||
fn ($document) => $document->hasAllContent(['1997', 'tollerbeitrag', '54.00'])
|
||||
);
|
||||
$this->assertNull($member->payments()->first()->invoice_data);
|
||||
$this->assertEquals(now()->format('Y-m-d'), $member->payments->first()->last_remembered_at->format('Y-m-d'));
|
||||
}
|
||||
|
||||
public function testItDoesntCreatePdfsWhenUserHasEmail(): void
|
||||
|
@ -58,7 +117,7 @@ class SendpaymentTest extends TestCase
|
|||
Tex::spy();
|
||||
$this->withoutExceptionHandling();
|
||||
$this->login()->loginNami();
|
||||
$member = Member::factory()
|
||||
Member::factory()
|
||||
->defaults()
|
||||
->has(Payment::factory()->notPaid()->nr('1997')->subscription('tollerbeitrag', [new Child('u', 5400)]))
|
||||
->emailBillKind()
|
||||
|
|
|
@ -11,6 +11,7 @@ use Illuminate\Http\RedirectResponse;
|
|||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Testing\TestResponse;
|
||||
use Phake;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
use Tests\Lib\MakesHttpCalls;
|
||||
use Tests\Lib\TestsInertia;
|
||||
use Zoomyboy\LaravelNami\Authentication\Auth;
|
||||
|
@ -81,8 +82,8 @@ abstract class TestCase extends BaseTestCase
|
|||
$sessionErrors = $response->getSession()->get('errors')->getBag('default');
|
||||
|
||||
foreach ($errors as $key => $value) {
|
||||
$this->assertTrue($sessionErrors->has($key), "Cannot find key {$key} in errors '".print_r($sessionErrors, true));
|
||||
$this->assertEquals($value, $sessionErrors->get($key)[0], "Failed to validate value for session error key {$key}. Actual value: ".print_r($sessionErrors, true));
|
||||
$this->assertTrue($sessionErrors->has($key), "Cannot find key {$key} in errors '" . print_r($sessionErrors, true));
|
||||
$this->assertEquals($value, $sessionErrors->get($key)[0], "Failed to validate value for session error key {$key}. Actual value: " . print_r($sessionErrors, true));
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
@ -106,4 +107,14 @@ abstract class TestCase extends BaseTestCase
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function assertPdfPageCount(int $pageCount, File $file): void
|
||||
{
|
||||
$this->assertTrue(file_exists($file->getPathname()));
|
||||
exec('pdfinfo ' . escapeshellarg($file->getPathname()) . ' | grep ^Pages | sed "s/Pages:\s*//"', $output, $returnVar);
|
||||
|
||||
$this->assertSame(0, $returnVar, 'Failed to get Pages of PDF File ' . $file->getPathname());
|
||||
$this->assertCount(1, $output, 'Failed to parse output format of pdfinfo');
|
||||
$this->assertEquals($pageCount, $output[0]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue