From 6561bda30dde5811df8014c2fdcb447b4a6a3c08 Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Sun, 5 Apr 2026 10:56:29 +0200 Subject: [PATCH] feat(weeztix): auto company from OAuth, remove company UI Store company_guid after OAuth via profile API; drop company select and companies endpoint. Coupons AJAX uses stored company only. Form request no longer accepts company fields from the browser. Made-with: Cursor --- .../Admin/WeeztixApiController.php | 39 ++----- .../Admin/WeeztixOAuthController.php | 4 + .../Admin/UpdateWeeztixConfigRequest.php | 2 - app/Services/WeeztixService.php | 37 +++++++ resources/js/app.js | 101 +----------------- resources/views/admin/weeztix/edit.blade.php | 32 ++---- routes/web.php | 1 - 7 files changed, 60 insertions(+), 156 deletions(-) diff --git a/app/Http/Controllers/Admin/WeeztixApiController.php b/app/Http/Controllers/Admin/WeeztixApiController.php index 5906b7e..13f455b 100644 --- a/app/Http/Controllers/Admin/WeeztixApiController.php +++ b/app/Http/Controllers/Admin/WeeztixApiController.php @@ -13,38 +13,10 @@ use RuntimeException; class WeeztixApiController extends Controller { - public function companies(Request $request): JsonResponse - { - $request->validate([ - 'page_id' => ['required', 'integer', 'exists:preregistration_pages,id'], - ]); - - $page = PreregistrationPage::query()->findOrFail($request->integer('page_id')); - $this->authorize('update', $page); - - $config = $page->weeztixConfig; - if ($config === null || ! $config->is_connected) { - return response()->json([ - 'message' => __('Niet verbonden met Weeztix.'), - ], 422); - } - - try { - $companies = (new WeeztixService($config))->getCompanies(); - - return response()->json(['companies' => $companies]); - } catch (RuntimeException) { - return response()->json([ - 'message' => __('Kon bedrijven niet laden. Vernieuw de verbinding indien nodig.'), - ], 422); - } - } - public function coupons(Request $request): JsonResponse { $request->validate([ 'page_id' => ['required', 'integer', 'exists:preregistration_pages,id'], - 'company_guid' => ['required', 'string', 'max:255'], ]); $page = PreregistrationPage::query()->findOrFail($request->integer('page_id')); @@ -57,9 +29,12 @@ class WeeztixApiController extends Controller ], 422); } - $companyGuid = $request->string('company_guid')->toString(); - $previousGuid = $config->company_guid; - $config->setAttribute('company_guid', $companyGuid); + $companyGuid = $config->company_guid; + if (! is_string($companyGuid) || $companyGuid === '') { + return response()->json([ + 'message' => __('Geen Weeztix-bedrijf gekoppeld. Verbind opnieuw met Weeztix.'), + ], 422); + } try { $raw = (new WeeztixService($config))->getCoupons(); @@ -70,8 +45,6 @@ class WeeztixApiController extends Controller return response()->json([ 'message' => __('Kon kortingsbonnen niet laden.'), ], 422); - } finally { - $config->setAttribute('company_guid', $previousGuid); } } diff --git a/app/Http/Controllers/Admin/WeeztixOAuthController.php b/app/Http/Controllers/Admin/WeeztixOAuthController.php index e5f4bab..bd19ad5 100644 --- a/app/Http/Controllers/Admin/WeeztixOAuthController.php +++ b/app/Http/Controllers/Admin/WeeztixOAuthController.php @@ -100,6 +100,10 @@ class WeeztixOAuthController extends Controller try { $service = new WeeztixService($config); $service->exchangeAuthorizationCode($request->string('code')->toString()); + $config = $config->fresh(); + if ($config !== null) { + (new WeeztixService($config))->ensureCompanyStoredFromWeeztix(); + } } catch (RuntimeException $e) { Log::error('Weeztix OAuth callback failed', [ 'page_id' => $page->id, diff --git a/app/Http/Requests/Admin/UpdateWeeztixConfigRequest.php b/app/Http/Requests/Admin/UpdateWeeztixConfigRequest.php index 69080e1..b0a5988 100644 --- a/app/Http/Requests/Admin/UpdateWeeztixConfigRequest.php +++ b/app/Http/Requests/Admin/UpdateWeeztixConfigRequest.php @@ -44,8 +44,6 @@ class UpdateWeeztixConfigRequest extends FormRequest 'string', 'max:2048', ], - 'company_guid' => ['nullable', 'string', 'max:255'], - 'company_name' => ['nullable', 'string', 'max:255'], 'coupon_guid' => ['nullable', 'string', 'max:255'], 'coupon_name' => ['nullable', 'string', 'max:255'], 'code_prefix' => ['nullable', 'string', 'max:32'], diff --git a/app/Services/WeeztixService.php b/app/Services/WeeztixService.php index 51ae729..e1f4388 100644 --- a/app/Services/WeeztixService.php +++ b/app/Services/WeeztixService.php @@ -13,6 +13,7 @@ use Illuminate\Support\Facades\Log; use InvalidArgumentException; use LogicException; use RuntimeException; +use Throwable; final class WeeztixService { @@ -84,6 +85,42 @@ final class WeeztixService return $this->normalizeCompaniesFromProfile($json); } + /** + * Persist company_guid when still empty after OAuth (single company per page; chosen in Weeztix login). + * Uses the first company returned from the user profile when several are present. + */ + public function ensureCompanyStoredFromWeeztix(): void + { + $this->config->refresh(); + + if (is_string($this->config->company_guid) && $this->config->company_guid !== '') { + return; + } + + try { + $companies = $this->getCompanies(); + if ($companies === []) { + Log::warning('Weeztix: geen bedrijf uit profiel voor automatische koppeling.', [ + 'weeztix_config_id' => $this->config->id, + ]); + + return; + } + + $row = $companies[0]; + $this->config->update([ + 'company_guid' => $row['guid'], + 'company_name' => $row['name'], + ]); + $this->config->refresh(); + } catch (Throwable $e) { + Log::warning('Weeztix: automatisch bedrijf vastleggen mislukt', [ + 'weeztix_config_id' => $this->config->id, + 'message' => $e->getMessage(), + ]); + } + } + /** * Exchange OAuth authorization code for tokens (admin callback). */ diff --git a/resources/js/app.js b/resources/js/app.js index 779ad67..8f81765 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -769,16 +769,12 @@ document.addEventListener('alpine:init', () => { Alpine.data('weeztixSetup', (cfg) => ({ pageId: cfg.pageId, - companiesUrl: cfg.companiesUrl, couponsUrl: cfg.couponsUrl, csrf: cfg.csrf, isConnected: cfg.isConnected === true, callbackUrl: cfg.callbackUrl, errorMessage: '', - companies: [], coupons: [], - companyGuid: '', - companyName: '', couponGuid: '', couponName: '', codePrefix: 'PREREG', @@ -797,19 +793,12 @@ document.addEventListener('alpine:init', () => { } else { this.usageCount = 1; } - this.companyGuid = cfg.existing.company_guid || ''; - this.companyName = cfg.existing.company_name || ''; this.couponGuid = cfg.existing.coupon_guid || ''; this.couponName = cfg.existing.coupon_name || ''; } if (this.isConnected) { - await this.loadCompanies(); - if (this.companyGuid) { - await this.loadCouponsForGuid(this.companyGuid); - } - } else if (cfg.existing && (cfg.existing.company_guid || cfg.existing.coupon_guid)) { - // Show saved choices even when not connected (e.g. expired refresh); lists are from DB only. - this.ensureSelectedCompanyInList(); + await this.loadCoupons(); + } else if (cfg.existing && cfg.existing.coupon_guid) { this.ensureSelectedCouponInList(); } }, @@ -829,18 +818,6 @@ document.addEventListener('alpine:init', () => { return { res, data }; }, - syncCompanyNameFromSelection() { - if (!this.companyGuid) { - this.companyName = ''; - return; - } - const c = this.companies.find((x) => x.guid === this.companyGuid); - if (c && typeof c.name === 'string' && c.name.trim() !== '') { - this.companyName = c.name.trim(); - } - // If API row has no name or list is still loading, keep companyName from server (DB). - }, - syncCouponName() { if (!this.couponGuid) { this.couponName = ''; @@ -852,18 +829,6 @@ document.addEventListener('alpine:init', () => { } }, - ensureSelectedCompanyInList() { - const guid = this.companyGuid; - if (!guid || this.companies.some((x) => x.guid === guid)) { - return; - } - const label = - typeof this.companyName === 'string' && this.companyName.trim() !== '' - ? this.companyName.trim() - : guid; - this.companies = [{ guid, name: label }, ...this.companies]; - }, - ensureSelectedCouponInList() { const guid = this.couponGuid; if (!guid || this.coupons.some((x) => x.guid === guid)) { @@ -876,36 +841,9 @@ document.addEventListener('alpine:init', () => { this.coupons = [{ guid, name: label }, ...this.coupons]; }, - async loadCompanies() { + async loadCoupons() { this.errorMessage = ''; - const { res, data } = await this.postJson(this.companiesUrl, { page_id: this.pageId }); - if (!res.ok) { - this.errorMessage = data.message || this.strings.genericError; - this.ensureSelectedCompanyInList(); - return; - } - this.companies = Array.isArray(data.companies) ? data.companies : []; - this.ensureSelectedCompanyInList(); - this.syncCompanyNameFromSelection(); - }, - - async onCompanyChange() { - this.syncCompanyNameFromSelection(); - this.couponGuid = ''; - this.couponName = ''; - this.coupons = []; - if (!this.companyGuid) { - return; - } - await this.loadCouponsForGuid(this.companyGuid); - }, - - async loadCouponsForGuid(guid) { - this.errorMessage = ''; - const { res, data } = await this.postJson(this.couponsUrl, { - page_id: this.pageId, - company_guid: guid, - }); + const { res, data } = await this.postJson(this.couponsUrl, { page_id: this.pageId }); if (!res.ok) { this.errorMessage = data.message || this.strings.loadCouponsError; this.ensureSelectedCouponInList(); @@ -915,37 +853,6 @@ document.addEventListener('alpine:init', () => { this.ensureSelectedCouponInList(); this.syncCouponName(); }, - - /** Prefer human-readable label; skip API "names" that are just the GUID / UUID. */ - companyLabel(c) { - if (!c || typeof c.guid !== 'string') { - return ''; - } - const g = c.guid; - const isBadLabel = (s) => { - const t = typeof s === 'string' ? s.trim() : ''; - return ( - t === '' || - t.toLowerCase() === g.toLowerCase() || - this.stringLooksLikeUuid(t) - ); - }; - const fromApi = typeof c.name === 'string' ? c.name : ''; - if (!isBadLabel(fromApi)) { - return fromApi.trim(); - } - if (this.companyGuid === g && !isBadLabel(this.companyName)) { - return String(this.companyName).trim(); - } - - return g; - }, - - stringLooksLikeUuid(s) { - return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/.test( - String(s), - ); - }, })); }); diff --git a/resources/views/admin/weeztix/edit.blade.php b/resources/views/admin/weeztix/edit.blade.php index 62983e6..fc3955b 100644 --- a/resources/views/admin/weeztix/edit.blade.php +++ b/resources/views/admin/weeztix/edit.blade.php @@ -3,8 +3,6 @@ $wz = $page->weeztixConfig; $existing = $wz !== null ? [ - 'company_guid' => $wz->company_guid, - 'company_name' => $wz->company_name, 'coupon_guid' => $wz->coupon_guid, 'coupon_name' => $wz->coupon_name, 'code_prefix' => $wz->code_prefix, @@ -24,7 +22,6 @@ class="mx-auto max-w-3xl" x-data="weeztixSetup(@js([ 'pageId' => $page->id, - 'companiesUrl' => route('admin.weeztix.companies'), 'couponsUrl' => route('admin.weeztix.coupons'), 'csrf' => csrf_token(), 'isConnected' => $wz?->is_connected ?? false, @@ -33,7 +30,6 @@ 'existing' => $existing, 'strings' => [ 'genericError' => __('Er ging iets mis. Probeer het opnieuw.'), - 'selectCompany' => __('Selecteer een bedrijf.'), 'loadCouponsError' => __('Kon kortingsbonnen niet laden.'), ], ]))" @@ -57,6 +53,13 @@ @endif + @if ($wz !== null && $wz->is_connected && ($wz->company_guid === null || $wz->company_guid === '')) +
+

{{ __('Bedrijf nog niet vastgelegd') }}

+

{{ __('Verbind opnieuw met Weeztix zodat het juiste bedrijf automatisch wordt gekoppeld.') }}

+
+ @endif + @if ($wz !== null && $wz->is_connected)

{{ __('Verbonden met Weeztix') }}

@@ -154,30 +157,13 @@ @if ($wz !== null)
-

{{ __('Stap 2: Bedrijf en kortingsbon') }}

-

{{ __('Na een geslaagde verbinding kun je een bedrijf en bestaande coupon uit Weeztix kiezen.') }}

+

{{ __('Stap 2: Kortingsbon') }}

+

{{ __('Na een geslaagde verbinding kies je een bestaande coupon uit Weeztix. Het bedrijf volgt uit je Weeztix-login en wordt automatisch opgeslagen.') }}

@csrf @method('PUT') -
- - - -
-