Compare commits

...

1 Commits

Author SHA1 Message Date
philipp lang 8f3e2e8aca --wip-- [skip ci] 2025-06-20 01:45:17 +02:00
6 changed files with 214 additions and 1 deletions

View File

@ -63,10 +63,12 @@ class ContributionFactory
}
public function validateType(HasContributionData $request) {
// @todo remove payload from hasContributionData and move the entire validation logic to the action
Validator::make(['type' => $request->type()], $this->typeRule())->validate();
}
public function validatePayload(HasContributionData $request) {
// @todo remove payload from hasContributionData and move the entire validation logic to the action
Validator::make($request->payload(), $this->rules($request->type()))->validate();
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace App\Form\Actions;
use App\Contribution\Contracts\HasContributionData;
use App\Contribution\ContributionFactory;
use App\Form\Models\Form;
use App\Rules\JsonBase64Rule;
use Illuminate\Http\JsonResponse;
use Lorisleiva\Actions\Concerns\AsAction;
use Zoomyboy\Tex\BaseCompiler;
use Zoomyboy\Tex\Tex;
class GenerateContributionAction
{
use AsAction;
public function handle(HasContributionData $request): BaseCompiler
{
return Tex::compile($request->type()::fromPayload($request));
}
public function asController(Form $form): BaseCompiler|JsonResponse
{
app(ContributionFactory::class)->validateType($form);
app(ContributionFactory::class)->validatePayload($form);
dd('I');
return $request->input('validate')
? response()->json([])
: $this->handle($request);
}
/**
* @return array<string, mixed>
*/
public function rules(): array
{
return [
'payload' => [new JsonBase64Rule()],
];
}
}

View File

@ -2,6 +2,8 @@
namespace App\Form\Models;
use App\Contribution\Contracts\HasContributionData;
use App\Country;
use App\Form\Actions\UpdateParticipantSearchIndexAction;
use App\Form\Data\ExportData;
use App\Form\Data\FieldCollection;
@ -9,11 +11,14 @@ use App\Form\Data\FormConfigData;
use App\Lib\Editor\Condition;
use App\Lib\Editor\EditorData;
use App\Lib\Sorting;
use App\Member\Data\MemberData;
use Carbon\Carbon;
use Cviebrock\EloquentSluggable\Sluggable;
use Database\Factories\Form\Models\FormFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Collection;
use Laravel\Scout\Searchable;
use Spatie\Image\Enums\Fit;
use Spatie\MediaLibrary\HasMedia;
@ -22,7 +27,7 @@ use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Zoomyboy\MedialibraryHelper\DefersUploads;
/** @todo replace editor content with EditorData cast */
class Form extends Model implements HasMedia
class Form extends Model implements HasMedia, HasContributionData
{
/** @use HasFactory<FormFactory> */
use HasFactory;
@ -201,4 +206,45 @@ class Form extends Model implements HasMedia
return true;
}
public function payload(): array
{
return [
'dateFrom' => $this->dateFrom()->format('Y-m-d'),
'eventName' => $this->name,
'members' => [],
];
}
/**
* @return class-string<ContributionDocument>
*/
public function type(): string
{
return request()->input('type');
}
public function dateFrom(): Carbon {
return now();
}
public function dateUntil(): Carbon {
return now();
}
public function zipLocation(): string {
return '';
}
public function eventName(): string {
return $this->name;
}
public function members(): Collection {
return MemberData::fromApi([]);
}
public function country(): ?Country {
return Country::first();
}
}

View File

@ -92,6 +92,8 @@ services:
socketi:
image: quay.io/soketi/soketi:89604f268623cf799573178a7ba56b7491416bde-16-debian
ports:
- "6001:6001"
environment:
SOKETI_DEFAULT_APP_ID: adremaid
SOKETI_DEFAULT_APP_KEY: adremakey
@ -104,6 +106,8 @@ services:
meilisearch:
image: getmeili/meilisearch:v1.6
ports:
- "7700:7700"
volumes:
- ./data/meilisearch:/meili_data
env_file:

View File

@ -34,6 +34,7 @@ use App\Form\Actions\FormtemplateStoreAction;
use App\Form\Actions\FormtemplateUpdateAction;
use App\Form\Actions\FormUpdateAction;
use App\Form\Actions\FormUpdateMetaAction;
use App\Form\Actions\GenerateContributionAction;
use App\Form\Actions\IsDirtyAction;
use App\Form\Actions\ParticipantAssignAction;
use App\Form\Actions\ParticipantDestroyAction;
@ -178,6 +179,7 @@ Route::group(['middleware' => 'auth:web'], function (): void {
Route::patch('/participant/{participant}', ParticipantUpdateAction::class)->name('participant.update');
Route::post('/form/{form}/participant', ParticipantStoreAction::class)->name('form.participant.store');
Route::post('/form/{form}/copy', FormCopyAction::class)->name('form.copy');
Route::get('/form/{form}/contribution', GenerateContributionAction::class)->name('form.contribution');
// ------------------------------------ fileshare -----------------------------------
Route::post('/fileshare', FileshareStoreAction::class)->name('fileshare.store');

View File

@ -0,0 +1,116 @@
<?php
namespace Tests\Feature\Form;
use App\Contribution\Documents\CitySolingenDocument;
use App\Form\Models\Form;
use App\Form\Models\Participant;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Zoomyboy\Tex\Tex;
uses(DatabaseTransactions::class);
it('doesnt create document when no firstname field given', function () {
Tex::spy();
$this->login()->loginNami();
$form = Form::factory()
->fields([])
->has(Participant::factory())
->create();
$this->json('GET', route('form.contribution', [
'type' => CitySolingenDocument::class,
'form' => $form,
'validate' => '1',
]))->assertJsonValidationErrors(['firstname' => 'Kein Feld für Vorname vorhanden']);
});
// it('compiles documents via base64 param', function (string $type, array $bodyChecks) {
// $this->withoutExceptionHandling();
// Tex::spy();
// $this->login()->loginNami();
// $member1 = Member::factory()->defaults()->male()->create(['address' => 'Maxstr 44', 'zip' => '42719', 'firstname' => 'Max', 'lastname' => 'Muster']);
// $member2 = Member::factory()->defaults()->female()->create(['address' => 'Maxstr 44', 'zip' => '42719', 'firstname' => 'Jane', 'lastname' => 'Muster']);
//
// $response = $this->call('GET', '/contribution-generate', [
// 'payload' => ContributionRequestFactory::new()->type($type)->state([
// 'dateFrom' => '1991-06-15',
// 'dateUntil' => '1991-06-16',
// 'eventName' => 'Super tolles Lager',
// 'members' => [$member1->id, $member2->id],
// 'type' => $type,
// 'zipLocation' => '42777 SG',
// ])->toBase64(),
// ]);
//
// $response->assertSessionDoesntHaveErrors();
// $response->assertOk();
// Tex::assertCompiled($type, fn ($document) => $document->hasAllContent($bodyChecks));
// })->with('contribution-assertions');
//
// it('testItCompilesGroupNameInSolingenDocument', function () {
// $this->withoutExceptionHandling()->login()->loginNami();
// Tex::spy();
// InvoiceSettings::fake(['from_long' => 'Stamm BiPi']);
//
// $this->call('GET', '/contribution-generate', [
// 'payload' => ContributionRequestFactory::new()->type(CitySolingenDocument::class)->toBase64(),
// ]);
//
// Tex::assertCompiled(CitySolingenDocument::class, fn ($document) => $document->hasAllContent(['Stamm BiPi']));
// });
//
// it('testItCompilesContributionDocumentsViaApi', function (string $type, array $bodyChecks) {
// $this->withoutExceptionHandling();
// Tex::spy();
// Gender::factory()->female()->create();
// Gender::factory()->male()->create();
// Passport::actingAsClient(Client::factory()->create(), ['contribution-generate']);
//
// $response = $this->postJson('/api/contribution-generate', [
// 'country' => Country::factory()->create()->id,
// 'dateFrom' => '1991-06-15',
// 'dateUntil' => '1991-06-16',
// 'eventName' => 'Super tolles Lager',
// 'type' => $type,
// 'zipLocation' => '42777 SG',
// 'member_data' => [
// ContributionMemberApiRequestFactory::new()->create(['address' => 'Maxstr 44', 'zip' => '42719', 'firstname' => 'Max', 'lastname' => 'Muster']),
// ContributionMemberApiRequestFactory::new()->create(['address' => 'Maxstr 44', 'zip' => '42719', 'firstname' => 'Jane', 'lastname' => 'Muster']),
// ],
// ]);
//
// $response->assertSessionDoesntHaveErrors();
// $response->assertOk();
// Tex::assertCompiled($type, fn ($document) => $document->hasAllContent($bodyChecks));
// })->with('contribution-assertions');
//
// it('testInputShouldBeBase64EncodedJson', function (string $payload) {
// $this->login()->loginNami();
//
// $this->call('GET', '/contribution-generate', ['payload' => $payload])->assertSessionHasErrors('payload');
// })->with([
// [""],
// ["aaaa"],
// ["YWFhCg=="],
// ]);
//
// it('testItValidatesInput', function (array $input, string $documentClass, string $errorField) {
// $this->login()->loginNami();
// Country::factory()->create();
// Member::factory()->defaults()->create();
//
// $this->postJson('/contribution-validate', ContributionRequestFactory::new()->type($documentClass)->state($input)->create())
// ->assertJsonValidationErrors($errorField);
// })->with('contribution-validation');
//
// it('testItValidatesInputBeforeGeneration', function (array $input, string $documentClass, string $errorField) {
// $this->login()->loginNami();
// Country::factory()->create();
// Member::factory()->defaults()->create();
//
// $this->call('GET', '/contribution-generate', [
// 'payload' => ContributionRequestFactory::new()->type($documentClass)->state($input)->toBase64(),
// ])->assertSessionHasErrors($errorField);
// })->with('contribution-validation');