Refactor DocumentFactory
continuous-integration/drone/push Build is failing Details

This commit is contained in:
philipp lang 2022-12-07 00:40:53 +01:00
parent 3a93d1585f
commit 94b405bcf9
9 changed files with 74 additions and 132 deletions

View File

@ -4,6 +4,7 @@ namespace App\Letter\Actions;
use App\Letter\BillKind;
use App\Letter\DocumentFactory;
use App\Letter\Queries\BillKindQuery;
use App\Payment\PaymentMail;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
@ -32,8 +33,8 @@ class LetterSendAction
*/
public function handle(): int
{
foreach (app(DocumentFactory::class)->types as $type) {
$letters = app(DocumentFactory::class)->letterCollection($type, BillKind::EMAIL);
foreach (app(DocumentFactory::class)->getTypes() as $type) {
$letters = app(DocumentFactory::class)->letterCollection($type, new BillKindQuery(BillKind::EMAIL));
foreach ($letters as $letter) {
$letterPath = Storage::path(Tex::compile($letter)->storeIn('/tmp', 'local'));

View File

@ -22,24 +22,11 @@ class BillDocument extends Letter
return 'tex.bill';
}
public function sendAllLabel(): string
public static function sendAllLabel(): string
{
return 'Rechnungen versenden';
}
/**
* Get Descriptions for sendpayment page.
*
* @return array<int, string>
*/
public function getDescription(): array
{
return [
'Diese Funktion erstellt ein PDF mit allen noch nicht versendenden Rechnungen bei den Mitgliedern die Post als Versandweg haben.',
'Die Rechnungen werden automatisch auf "Rechnung gestellt" aktualisiert.',
];
}
public function afterSingle(Payment $payment): void
{
$payment->update(['status_id' => 2]);
@ -59,4 +46,17 @@ class BillDocument extends Letter
{
return $query->whereNeedsBill();
}
/**
* Get Descriptions for sendpayment page.
*
* @return array<int, string>
*/
public static function getDescription(): array
{
return [
'Diese Funktion erstellt ein PDF mit allen noch nicht versendenden Rechnungen bei den Mitgliedern die Post als Versandweg haben.',
'Die Rechnungen werden automatisch auf "Rechnung gestellt" aktualisiert.',
];
}
}

View File

@ -2,72 +2,39 @@
namespace App\Letter;
use App\Letter\Queries\BillKindQuery;
use App\Letter\Queries\SingleMemberQuery;
use App\Member\Member;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use App\Letter\Queries\LetterMemberQuery;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
class DocumentFactory
{
/**
* @var array<int, class-string<Letter>>
*/
public array $types = [
private array $types = [
BillDocument::class,
RememberDocument::class,
];
/**
* @return Collection<int, Letter>
* @return Collection<int, class-string<Letter>>
*/
public function getTypes(): Collection
{
/** @var array<int, Member> */
$emptyMembers = [];
return collect(array_map(fn ($classString) => new $classString(collect($emptyMembers)), $this->types));
return collect($this->types);
}
/**
* @param class-string<Letter> $type
*/
public function fromSingleRequest(string $type, Member $member): ?Letter
public function singleLetter(string $type, LetterMemberQuery $query): ?Letter
{
$members = $this->singleMemberPages($member, $type);
if ($members->isEmpty()) {
return null;
}
return tap(
$this->resolve($type, $members),
fn ($repo) => $repo->setFilename(Str::slug("{$repo->getSubject()} für {$members->first()->singleName}"))
);
}
/**
* @param class-string<Letter> $type
*/
public function forAll(string $type, BillKind $billKind): ?Letter
{
$pages = $this->allMemberPages($type, $billKind);
$pages = $query->getPages($type);
if ($pages->isEmpty()) {
return null;
}
return tap($this->resolve($type, $pages), fn ($repo) => $repo->setFilename('alle-rechnungen'));
}
/**
* @param class-string<Letter> $type
*/
public function afterAll(string $type, BillKind $billKind): void
{
$letter = $this->forAll($type, $billKind);
$this->afterSingle($letter);
return $this->resolve($type, $pages);
}
/**
@ -75,11 +42,11 @@ class DocumentFactory
*
* @return Collection<int, Letter>
*/
public function letterCollection(string $type, BillKind $billKind): Collection
public function letterCollection(string $type, LetterMemberQuery $query): Collection
{
$pages = $this->allMemberPages($type, $billKind);
return $pages->map(fn ($page) => $this->resolve($type, collect([$page])));
return $query
->getPages($type)
->map(fn ($page) => $this->resolve($type, collect([$page])));
}
public function afterSingle(Letter $letter): void
@ -89,26 +56,6 @@ class DocumentFactory
}
}
/**
* @param class-string<Letter> $type
*
* @return Collection<int, Page>
*/
private function singleMemberPages(Member $member, string $type): Collection
{
return (new SingleMemberQuery($member))->getPages($type);
}
/**
* @param class-string<Letter> $type
*
* @return Collection<int, Page>
*/
private function allMemberPages(string $type, BillKind $billKind): Collection
{
return (new BillKindQuery($billKind))->getPages($type);
}
/**
* @param class-string<Letter> $type
* @param Collection<int, Page> $pages
@ -117,18 +64,4 @@ class DocumentFactory
{
return new $type($pages);
}
/**
* @param EloquentCollection<Member> $members
*
* @return Collection<int, Page>
*/
private function toPages(EloquentCollection $members): Collection
{
return $members->groupBy(
fn ($member) => Str::slug(
"{$member->lastname}{$member->address}{$member->zip}{$member->location}",
),
)->map(fn ($page) => new Page($page));
}
}

View File

@ -21,7 +21,7 @@ abstract class Letter extends Document
abstract public function linkLabel(): string;
abstract public function sendAllLabel(): string;
abstract public static function sendAllLabel(): string;
/**
* @param HasMany<Payment> $query
@ -33,7 +33,7 @@ abstract class Letter extends Document
/**
* @return array<int, string>
*/
abstract public function getDescription(): array;
abstract public static function getDescription(): array;
abstract public function afterSingle(Payment $payment): void;

View File

@ -71,24 +71,6 @@ class RememberDocument extends Letter
return $page->first()->location;
}
public function sendAllLabel(): string
{
return 'Erinnerungen versenden';
}
/**
* Get Descriptions for sendpayment page.
*
* @return array<int, string>
*/
public function getDescription(): array
{
return [
'Diese Funktion erstellt Erinnerungs-PDFs mit allen versendeten aber noch nich bezahlten Rechnungen bei den Mitgliedern die Post als Versandweg haben.',
'Das zuletzt erinnerte Datum wird auf heute gesetzt.',
];
}
public function afterSingle(Payment $payment): void
{
$payment->update(['last_remembered_at' => now()]);
@ -108,4 +90,22 @@ class RememberDocument extends Letter
{
return $query->whereNeedsRemember();
}
/**
* Get Descriptions for sendpayment page.
*
* @return array<int, string>
*/
public static function getDescription(): array
{
return [
'Diese Funktion erstellt Erinnerungs-PDFs mit allen versendeten aber noch nich bezahlten Rechnungen bei den Mitgliedern die Post als Versandweg haben.',
'Das zuletzt erinnerte Datum wird auf heute gesetzt.',
];
}
public static function sendAllLabel(): string
{
return 'Erinnerungen versenden';
}
}

View File

@ -3,20 +3,19 @@
namespace App\Payment;
use App\Letter\DocumentFactory;
use App\Letter\Letter;
use Illuminate\Support\Collection;
class ActionFactory
{
public function allLinks(): Collection
{
return app(DocumentFactory::class)->getTypes()->map(function (Letter $repo) {
return app(DocumentFactory::class)->getTypes()->map(function ($repo) {
return [
'link' => [
'href' => route('sendpayment.pdf', ['type' => get_class($repo)]),
'label' => $repo->sendAllLabel(),
'href' => route('sendpayment.pdf', ['type' => $repo]),
'label' => $repo::sendAllLabel(),
],
'text' => $repo->getDescription(),
'text' => $repo::getDescription(),
];
});
}

View File

@ -5,6 +5,7 @@ namespace App\Payment;
use App\Http\Controllers\Controller;
use App\Letter\BillKind;
use App\Letter\DocumentFactory;
use App\Letter\Queries\BillKindQuery;
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
@ -29,14 +30,14 @@ class SendpaymentController extends Controller
*/
public function send(Request $request)
{
$repo = app(DocumentFactory::class)->forAll($request->type, BillKind::POST);
$letter = app(DocumentFactory::class)->singleLetter($request->type, new BillKindQuery(BillKind::POST));
if (is_null($repo)) {
if (is_null($letter)) {
return response()->noContent();
}
$pdfFile = Tex::compile($repo);
app(DocumentFactory::class)->afterAll($request->type, BillKind::POST);
$pdfFile = Tex::compile($letter);
app(DocumentFactory::class)->afterSingle($letter);
return $pdfFile;
}

View File

@ -4,6 +4,7 @@ namespace App\Pdf;
use App\Http\Controllers\Controller;
use App\Letter\DocumentFactory;
use App\Letter\Queries\SingleMemberQuery;
use App\Member\Member;
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Http\Request;
@ -17,10 +18,10 @@ class MemberPdfController extends Controller
*/
public function __invoke(Request $request, Member $member)
{
$document = app(DocumentFactory::class)->fromSingleRequest($request->type, $member);
$letter = app(DocumentFactory::class)->singleLetter($request->type, new SingleMemberQuery($member));
return null === $document
return null === $letter
? response()->noContent()
: Tex::compile($document);
: Tex::compile($letter);
}
}

View File

@ -5,6 +5,8 @@ namespace Tests\Feature\Letter;
use App\Letter\BillDocument;
use App\Letter\DocumentFactory;
use App\Letter\LetterSettings;
use App\Letter\Queries\LetterMemberQuery;
use App\Letter\Queries\SingleMemberQuery;
use App\Letter\RememberDocument;
use App\Member\Member;
use App\Payment\Payment;
@ -23,7 +25,7 @@ class DocumentFactoryTest extends TestCase
public function testItDoesntReturnARepositoryWhenMemberDoesntHavePayments(): void
{
$member = Member::factory()->defaults()->create();
$letter = app(DocumentFactory::class)->fromSingleRequest(BillDocument::class, $member);
$letter = app(DocumentFactory::class)->singleLetter(BillDocument::class, $this->query($member));
$this->assertNull($letter);
}
@ -41,7 +43,7 @@ class DocumentFactoryTest extends TestCase
->has(Payment::factory()->notPaid()->nr('1995')->subscription('::subName::', 1500))
->create();
$letter = app(DocumentFactory::class)->fromSingleRequest(BillDocument::class, $member);
$letter = app(DocumentFactory::class)->singleLetter(BillDocument::class, $this->query($member));
$letter->assertHasAllContent([
'Rechnung',
@ -60,7 +62,7 @@ class DocumentFactoryTest extends TestCase
->has(Payment::factory()->notPaid()->nr('1995')->subscription('::subName::', 1500))
->create();
$letter = app(DocumentFactory::class)->fromSingleRequest(BillDocument::class, $member);
$letter = app(DocumentFactory::class)->singleLetter(BillDocument::class, $this->query($member));
$this->assertEquals('rechnung-fur-lastname.pdf', $letter->compiledFilename());
}
@ -73,7 +75,7 @@ class DocumentFactoryTest extends TestCase
->has(Payment::factory()->notPaid())
->create();
$letter = app(DocumentFactory::class)->fromSingleRequest(RememberDocument::class, $member);
$letter = app(DocumentFactory::class)->singleLetter(RememberDocument::class, $this->query($member));
$this->assertEquals('zahlungserinnerung-fur-lastname.pdf', $letter->compiledFilename());
}
@ -91,7 +93,7 @@ class DocumentFactoryTest extends TestCase
->has(Payment::factory()->notPaid()->nr('nr2'))
->create();
$letter = app(DocumentFactory::class)->fromSingleRequest(BillDocument::class, $firstMember);
$letter = app(DocumentFactory::class)->singleLetter(BillDocument::class, $this->query($firstMember));
$letter->assertHasAllContent(['Max1', 'Max2', 'nr1', 'nr2']);
}
@ -119,7 +121,7 @@ class DocumentFactoryTest extends TestCase
->has(Payment::factory()->notPaid()->nr('nr2'))
->create();
$letter = app(DocumentFactory::class)->fromSingleRequest($type, $member);
$letter = app(DocumentFactory::class)->singleLetter($type, $this->query($member));
$letter->assertHasAllContent([
'langer Stammesname',
@ -152,4 +154,9 @@ class DocumentFactoryTest extends TestCase
$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): LetterMemberQuery
{
return new SingleMemberQuery($member);
}
}