From 305af64fd6f7b89b8e8efda2f1386bce5d570aea Mon Sep 17 00:00:00 2001 From: DanielS Date: Sat, 4 Jul 2026 16:08:31 +0200 Subject: [PATCH] feat: assign orders to companies directly and support admin reassignment --- funktionen.md | 6 ++-- shop/app/my-orders/page.tsx | 8 +---- shop/app/order/page.tsx | 19 +++++++++++- shop/components/order-wizard.tsx | 31 +++++++++++++++++++ shop/lib/actions/orders.ts | 24 +++++++++----- shop/lib/types.ts | 1 + ...0260704161000_add_company_id_to_orders.sql | 28 +++++++++++++++++ 7 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 shop/supabase/migrations/20260704161000_add_company_id_to_orders.sql diff --git a/funktionen.md b/funktionen.md index 6574f6c..e0dd561 100644 --- a/funktionen.md +++ b/funktionen.md @@ -6,7 +6,7 @@ Diese Datei beschreibt die Architektur, das Datenmodell, die Kernprozesse und da ## 1. Projekt-Überblick -Der CASPOS Webshop ist ein B2B-Portal für Vertriebspartner. Partner können hier Software-Pakete und Zusatzmodule (für POS/Kassenlösungen) konfigurieren, Angebote/Anfragen für ihre Endkunden erstellen und Lizenzen verwalten. +Der CASPOS Webshop ist ein B2B-Portal für Vertriebspartner. Partner können hier Software-Pakete und Zusatzmodule (für POS/Kassenlösungen) konfigurieren, Anfragen für ihre Endkunden erstellen und Lizenzen verwalten. --- @@ -128,11 +128,13 @@ RLS ist auf Datenbankebene in Postgres implementiert und erzwingt Datenisolierun - `USING (partner_id = (SELECT company_id FROM public.users WHERE id = auth.uid()))` - Partner sehen und modifizieren nur Endkunden, deren `partner_id` mit der `company_id` des angemeldeten Benutzers übereinstimmt. - **Bestellungen (`orders`)**: - - Partner sehen und modifizieren nur Bestellungen von Benutzern, die derselben Company angehören (oder ihre eigenen, falls keine Company zugewiesen ist). + - Partner sehen und modifizieren nur Bestellungen von Benutzern, die derselben Company angehören (sie müssen einer company zugewiesen sein). - Admins haben uneingeschränkten Zugriff. - **Lizenzen (`licenses`)**: - Partner sehen nur Lizenzen von Endkunden, die ihrer Company zugeordnet sind. +- **Erstellung: jede bestellung wird der firma des erstellers zugewiesen. Ein admin ist aber fähig einer bestellung nachträglich eine andere firma zuzuweisen. + --- ## Kommentarbereich diff --git a/shop/app/my-orders/page.tsx b/shop/app/my-orders/page.tsx index 077d54f..6875751 100644 --- a/shop/app/my-orders/page.tsx +++ b/shop/app/my-orders/page.tsx @@ -36,13 +36,7 @@ export default async function MyOrdersPage() { let query = supabase.from('orders').select('*') if (dbUser?.company_id) { - const { data: companyUsers } = await supabase - .from('users') - .select('id') - .eq('company_id', dbUser.company_id) - - const userIds = (companyUsers ?? []).map(u => u.id) - query = query.in('user_id', userIds) + query = query.eq('company_id', dbUser.company_id) } else { query = query.eq('user_id', user.id) } diff --git a/shop/app/order/page.tsx b/shop/app/order/page.tsx index 733d542..1459014 100644 --- a/shop/app/order/page.tsx +++ b/shop/app/order/page.tsx @@ -3,6 +3,7 @@ import { createAdminClient } from '@/lib/supabase/admin' import { getProducts, getCategories } from '@/lib/actions/products' import { getEndCustomers } from '@/lib/actions/end-customers' import { OrderWizard } from '@/components/order-wizard' +import { getCompanies } from '@/lib/actions/companies' import { redirect } from 'next/navigation' import { Suspense } from 'react' @@ -121,5 +122,21 @@ async function OrderDataWrapper({ orderId }: { orderId?: string }) { console.error('Fehler beim Laden des Profils:', e) } - return + // Fetch companies list for admin + let companies: any[] = [] + if (userData?.role === 'admin') { + companies = await getCompanies().catch(() => []) + } + + return ( + + ) } diff --git a/shop/components/order-wizard.tsx b/shop/components/order-wizard.tsx index 1949084..a82334f 100644 --- a/shop/components/order-wizard.tsx +++ b/shop/components/order-wizard.tsx @@ -81,16 +81,23 @@ export function OrderWizard({ initialProfile, initialEndCustomers, initialOrder, + isAdmin = false, + companies = [], }: { products: Product[] categories: Category[] initialProfile: Profile | null initialEndCustomers: EndCustomer[] initialOrder?: Order | null + isAdmin?: boolean + companies?: any[] }) { const router = useRouter() const [step, setStep] = useState(initialOrder ? 3 : 1) const [isSubmitting, setIsSubmitting] = useState(false) + const [selectedCompanyId, setSelectedCompanyId] = useState( + initialOrder?.company_id ?? null + ) // Partner-Profil (Fallback) const [customerData] = useState>(initialProfile || {}) @@ -414,6 +421,7 @@ export function OrderWizard({ endCustomer: selectedEndCustomer, billingInterval: selectedBillingInterval, lastLicenseDate: lastLicenseDate || null, + companyId: selectedCompanyId, }) } else { order = await submitOrder({ @@ -482,6 +490,29 @@ export function OrderWizard({ + {/* Admin Company Selector */} + {isAdmin && ( +
+ + +
+ )} + {/* Modus-Toggle */}