prepare('SELECT id FROM party WHERE email = :email LIMIT 1'); $stmt->execute([':email' => $email]); $existing = $stmt->fetchColumn(); if ($existing !== false) { return (int) $existing; } } $name = trim( payload_first_non_empty($data, ['Vorname', 'firstName', 'Vorname_RgAdr', 'Vorname_LfAdr']) . ' ' . payload_first_non_empty($data, ['Nachname', 'lastName', 'Nachname_RgAdr', 'Nachname_LfAdr']) ); $name = trim($name); if ($name === '') { $name = payload_first_non_empty($data, ['Firmenname', 'company']); } if ($name === '') { $name = 'Unbekannter Kontakt'; } $stmt = $pdo->prepare( "INSERT INTO party (type, name, email, status, created_at, updated_at) VALUES ('customer', :name, :email, 'active', NOW(), NOW()) RETURNING id" ); $stmt->execute([ ':name' => $name, ':email' => $email !== '' ? $email : null, ]); $id = $stmt->fetchColumn(); if ($id === false) { throw new RuntimeException('Could not create party'); } return (int) $id; } function upsert_addresses(PDO $pdo, int $partyId, array $data): void { $addressData = [ 'billing' => [ 'first_name' => payload_first_non_empty($data, ['Vorname', 'firstName', 'Vorname_RgAdr']), 'last_name' => payload_first_non_empty($data, ['Nachname', 'lastName', 'Nachname_RgAdr']), 'street' => payload_first_non_empty($data, ['Strasse', 'street', 'Strasse_RgAdr']), 'house_number' => payload_first_non_empty($data, ['Hausnummer', 'houseNumber', 'Hausnummer_RgAdr']), 'zip' => payload_first_non_empty($data, ['PLZ', 'zip', 'PLZ_RgAdr']), 'city' => payload_first_non_empty($data, ['Ort', 'city', 'Stadt_RgAdr']), 'country_name' => payload_first_non_empty($data, ['Land', 'country', 'Land_RgAdr'], 'Switzerland'), ], 'shipping' => [ 'first_name' => payload_first_non_empty($data, ['Vorname_LfAdr']), 'last_name' => payload_first_non_empty($data, ['Nachname_LfAdr']), 'street' => payload_first_non_empty($data, ['Strasse_LfAdr']), 'house_number' => payload_first_non_empty($data, ['Hausnummer_LfAdr']), 'zip' => payload_first_non_empty($data, ['PLZ_LfAdr']), 'city' => payload_first_non_empty($data, ['Stadt_LfAdr', 'Ort_LfAdr']), 'country_name' => payload_first_non_empty($data, ['Land_LfAdr'], 'Switzerland'), ], ]; foreach ($addressData as $type => $address) { if ($address['street'] === '' && $address['city'] === '' && $address['zip'] === '') { continue; } $stmt = $pdo->prepare( "INSERT INTO address ( party_id, type, first_name, last_name, street, house_number, zip, city, country_name, created_at, updated_at ) VALUES ( :party_id, :type, :first_name, :last_name, :street, :house_number, :zip, :city, :country_name, NOW(), NOW() )" ); $stmt->execute([ ':party_id' => $partyId, ':type' => $type, ':first_name' => $address['first_name'], ':last_name' => $address['last_name'], ':street' => $address['street'], ':house_number' => $address['house_number'], ':zip' => $address['zip'], ':city' => $address['city'], ':country_name' => $address['country_name'] !== '' ? $address['country_name'] : 'Switzerland', ]); } } function get_manufacturer_options(PDO $pdo): array { $stmt = $pdo->query( "SELECT p.id, p.name, p.email, p.phone FROM party p INNER JOIN party_role pr ON pr.party_id = p.id AND pr.role_code = 'manufacturer' WHERE p.status = 'active' ORDER BY p.name ASC, p.id ASC" ); return array_map( static fn (array $row): array => [ 'id' => (int) $row['id'], 'name' => (string) $row['name'], 'email' => (string) ($row['email'] ?? ''), 'phone' => (string) ($row['phone'] ?? ''), ], $stmt->fetchAll() ); } function get_party_reference(PDO $pdo, int $partyId): ?array { $stmt = $pdo->prepare( 'SELECT id, name, email, phone FROM party WHERE id = :id' ); $stmt->execute([':id' => $partyId]); $party = $stmt->fetch(); return is_array($party) ? $party : null; } function get_contact_reference(PDO $pdo, int $contactId): ?array { $stmt = $pdo->prepare( 'SELECT id, party_id, first_name, last_name, email, phone, position_title FROM contact WHERE id = :id' ); $stmt->execute([':id' => $contactId]); $contact = $stmt->fetch(); return is_array($contact) ? $contact : null; } function get_party_options(PDO $pdo): array { $stmt = $pdo->query( "SELECT id, name FROM party WHERE status = 'active' ORDER BY name ASC, id ASC" ); return array_map( static fn (array $row): array => ['id' => (int) $row['id'], 'name' => (string) ($row['name'] ?? '')], $stmt->fetchAll() ); } function get_contact_options(PDO $pdo): array { $stmt = $pdo->query( "SELECT c.id, c.party_id, c.first_name, c.last_name, p.name AS party_name FROM contact c INNER JOIN party p ON p.id = c.party_id WHERE p.status = 'active' ORDER BY p.name ASC, c.last_name ASC, c.first_name ASC, c.id ASC" ); return array_map( static fn (array $row): array => [ 'id' => (int) $row['id'], 'party_id' => (int) $row['party_id'], 'first_name' => (string) ($row['first_name'] ?? ''), 'last_name' => (string) ($row['last_name'] ?? ''), 'party_name' => (string) ($row['party_name'] ?? ''), ], $stmt->fetchAll() ); } function update_contact_details(PDO $pdo, int $contactId, array $input): array { if ($contactId <= 0) { throw new InvalidArgumentException('contact_person_id muss positiv sein.'); } $sets = []; $params = [':id' => $contactId]; foreach (['email', 'phone'] as $field) { if (array_key_exists($field, $input)) { $sets[] = $field . ' = :' . $field; $value = trim((string) ($input[$field] ?? '')); $params[':' . $field] = $value !== '' ? $value : null; } } if ($sets === []) { throw new InvalidArgumentException('Keine änderbaren Kontaktdaten übergeben.'); } $sets[] = 'updated_at = NOW()'; $stmt = $pdo->prepare( 'UPDATE contact SET ' . implode(', ', $sets) . ' WHERE id = :id RETURNING id, party_id, first_name, last_name, email, phone, position_title' ); $stmt->execute($params); $contact = $stmt->fetch(); if (!is_array($contact)) { throw new RuntimeException('Kontaktperson nicht gefunden.'); } return $contact; } function create_manufacturer(PDO $pdo, string $name, ?string $email = null, ?string $phone = null): array { $name = trim($name); $email = $email !== null ? trim($email) : null; $phone = $phone !== null ? trim($phone) : null; if ($name === '') { throw new InvalidArgumentException('Herstellername fehlt'); } $existingStmt = $pdo->prepare( "SELECT p.id, p.name, p.email, p.phone FROM party p WHERE LOWER(TRIM(p.name)) = LOWER(:name) LIMIT 1 FOR UPDATE" ); $existingStmt->execute([':name' => $name]); $existing = $existingStmt->fetch(); if (is_array($existing)) { $roleStmt = $pdo->prepare( "INSERT INTO party_role (party_id, role_code) VALUES (:party_id, 'manufacturer') ON CONFLICT (party_id, role_code) DO NOTHING" ); $roleStmt->execute([':party_id' => (int) $existing['id']]); return [ 'id' => (int) $existing['id'], 'name' => (string) $existing['name'], 'email' => (string) ($existing['email'] ?? ''), 'phone' => (string) ($existing['phone'] ?? ''), ]; } $stmt = $pdo->prepare( "INSERT INTO party (type, name, email, phone, status, created_at, updated_at) VALUES ('supplier', :name, :email, :phone, 'active', NOW(), NOW()) RETURNING id, name, email, phone" ); $stmt->execute([ ':name' => $name, ':email' => $email !== '' ? $email : null, ':phone' => $phone !== '' ? $phone : null, ]); $party = $stmt->fetch(); if (!is_array($party)) { throw new RuntimeException('Hersteller konnte nicht angelegt werden'); } $roleStmt = $pdo->prepare( "INSERT INTO party_role (party_id, role_code) VALUES (:party_id, 'manufacturer')" ); $roleStmt->execute([':party_id' => (int) $party['id']]); return [ 'id' => (int) $party['id'], 'name' => (string) $party['name'], 'email' => (string) ($party['email'] ?? ''), 'phone' => (string) ($party['phone'] ?? ''), ]; }