Files
hub/app/Http/Controllers/Portal/PromoController.php
kelly c7fdc67060 feat: add dispensary marketing portal (Phase 5)
Add white-labeled marketing portal for dispensary partners:

- Business branding settings table and model for white-labeling
- Portal middleware (EnsureMarketingPortalAccess) with contact_type check
- Portal route group at /portal/{business}/*
- DashboardController with stats and CannaiQ recommendations
- PromoController for viewing recommended/existing promos
- CampaignController with create/send/schedule/cancel
- ListController for managing contact lists
- Policies for MarketingCampaign and MarketingPromo
- White-labeled portal layout with custom branding CSS
- Marketing Portal link in Filament admin for buyer businesses
- MarketingPortalUserSeeder for development testing
- PORTAL_ACCESS.md documentation
2025-12-09 15:59:40 -07:00

76 lines
2.2 KiB
PHP

<?php
namespace App\Http\Controllers\Portal;
use App\Http\Controllers\Controller;
use App\Models\Branding\BusinessBrandingSetting;
use App\Models\Business;
use App\Models\Marketing\MarketingPromo;
use App\Services\Marketing\PromoRecommendationService;
use Illuminate\Http\Request;
class PromoController extends Controller
{
public function __construct(
protected PromoRecommendationService $promoService
) {}
public function index(Request $request, Business $business)
{
$branding = BusinessBrandingSetting::forBusiness($business);
// Get recommended promos from CannaiQ
$recommendedPromos = collect();
try {
$storeExternalIds = $business->cannaiqStores()
->pluck('external_id')
->toArray();
if (! empty($storeExternalIds)) {
$recommendations = $this->promoService->getRecommendations(
$business,
$storeExternalIds[0] ?? null,
limit: 20
);
$recommendedPromos = collect($recommendations['recommendations'] ?? []);
}
} catch (\Exception $e) {
// CannaiQ not available
}
// Get existing promos for this business
$existingPromos = MarketingPromo::forBusiness($business->id)
->with('brand')
->when($request->status, fn ($q, $status) => $q->where('status', $status))
->latest()
->paginate(12);
$statuses = MarketingPromo::getStatuses();
return view('portal.promos.index', compact(
'business',
'branding',
'recommendedPromos',
'existingPromos',
'statuses'
));
}
public function show(Request $request, Business $business, MarketingPromo $promo)
{
// Ensure promo belongs to this business
if ($promo->business_id !== $business->id) {
abort(404);
}
$branding = BusinessBrandingSetting::forBusiness($business);
$promo->load('brand');
return view('portal.promos.show', compact(
'business',
'branding',
'promo'
));
}
}