'Producer', 'manufacturer' => 'Manufacturer', 'supplier' => 'Supplier', 'vendor' => 'Vendor', 'factory' => 'Factory', 'agent' => 'Agent', 'invoice_to' => 'Invoice To', 'report_to' => 'Report To', 'laboratory' => 'Laboratory', 'other' => 'Other', ]; $partnerStatuses = [ 'active' => 'Active', 'inactive' => 'Inactive', 'suspended' => 'Suspended', ]; $contactStatuses = [ 'active' => 'Active', 'inactive' => 'Inactive', ]; /* * AJAX actions */ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) { $action = $_POST['action']; try { if ($action === 'save_partner') { $idpartner = isset($_POST['idpartner']) ? (int) $_POST['idpartner'] : 0; $idcompany = isset($_POST['idcompany']) ? (int) $_POST['idcompany'] : 0; $partnerType = $_POST['partner_type'] ?? 'supplier'; $partnerName = trim($_POST['partner_name'] ?? ''); $legalName = trim($_POST['legal_name'] ?? ''); $externalCode = trim($_POST['external_code'] ?? ''); $vatNumber = trim($_POST['vat_number'] ?? ''); $taxCode = trim($_POST['tax_code'] ?? ''); $address = trim($_POST['address'] ?? ''); $city = trim($_POST['city'] ?? ''); $zip = trim($_POST['zip'] ?? ''); $countryId = !empty($_POST['country_id']) ? (int) $_POST['country_id'] : null; $email = trim($_POST['email'] ?? ''); $phone = trim($_POST['phone'] ?? ''); $website = trim($_POST['website'] ?? ''); $notes = trim($_POST['notes'] ?? ''); $status = $_POST['status'] ?? 'active'; if ($idcompany <= 0) { jsonResponse([ 'success' => false, 'message' => 'Company is required.' ]); } if ($partnerName === '') { jsonResponse([ 'success' => false, 'message' => 'Partner name is required.' ]); } if (!array_key_exists($partnerType, $partnerTypes)) { $partnerType = 'supplier'; } if (!array_key_exists($status, $partnerStatuses)) { $status = 'active'; } /* * Check company exists. */ $stmt = $db->prepare(" SELECT COUNT(*) FROM companies WHERE idcompany = :idcompany "); $stmt->execute([':idcompany' => $idcompany]); if ((int) $stmt->fetchColumn() === 0) { jsonResponse([ 'success' => false, 'message' => 'Selected company does not exist.' ]); } if ($idpartner > 0) { $sql = " UPDATE business_partners SET idcompany = :idcompany, partner_type = :partner_type, partner_name = :partner_name, legal_name = :legal_name, external_code = :external_code, vat_number = :vat_number, tax_code = :tax_code, address = :address, city = :city, zip = :zip, country_id = :country_id, email = :email, phone = :phone, website = :website, notes = :notes, status = :status, updated_at = NOW() WHERE idpartner = :idpartner "; $stmt = $db->prepare($sql); $stmt->execute([ ':idcompany' => $idcompany, ':partner_type' => $partnerType, ':partner_name' => $partnerName, ':legal_name' => $legalName !== '' ? $legalName : null, ':external_code' => $externalCode !== '' ? $externalCode : null, ':vat_number' => $vatNumber !== '' ? $vatNumber : null, ':tax_code' => $taxCode !== '' ? $taxCode : null, ':address' => $address !== '' ? $address : null, ':city' => $city !== '' ? $city : null, ':zip' => $zip !== '' ? $zip : null, ':country_id' => $countryId, ':email' => $email !== '' ? $email : null, ':phone' => $phone !== '' ? $phone : null, ':website' => $website !== '' ? $website : null, ':notes' => $notes !== '' ? $notes : null, ':status' => $status, ':idpartner' => $idpartner, ]); jsonResponse([ 'success' => true, 'message' => 'Business partner updated successfully.' ]); } $sql = " INSERT INTO business_partners ( idcompany, partner_type, partner_name, legal_name, external_code, vat_number, tax_code, address, city, zip, country_id, email, phone, website, notes, status, created_by, created_at, updated_at ) VALUES ( :idcompany, :partner_type, :partner_name, :legal_name, :external_code, :vat_number, :tax_code, :address, :city, :zip, :country_id, :email, :phone, :website, :notes, :status, :created_by, NOW(), NOW() ) "; $stmt = $db->prepare($sql); $stmt->execute([ ':idcompany' => $idcompany, ':partner_type' => $partnerType, ':partner_name' => $partnerName, ':legal_name' => $legalName !== '' ? $legalName : null, ':external_code' => $externalCode !== '' ? $externalCode : null, ':vat_number' => $vatNumber !== '' ? $vatNumber : null, ':tax_code' => $taxCode !== '' ? $taxCode : null, ':address' => $address !== '' ? $address : null, ':city' => $city !== '' ? $city : null, ':zip' => $zip !== '' ? $zip : null, ':country_id' => $countryId, ':email' => $email !== '' ? $email : null, ':phone' => $phone !== '' ? $phone : null, ':website' => $website !== '' ? $website : null, ':notes' => $notes !== '' ? $notes : null, ':status' => $status, ':created_by' => $iduserlogin, ]); jsonResponse([ 'success' => true, 'message' => 'Business partner created successfully.' ]); } if ($action === 'get_partner') { $idpartner = isset($_POST['idpartner']) ? (int) $_POST['idpartner'] : 0; if ($idpartner <= 0) { jsonResponse([ 'success' => false, 'message' => 'Invalid partner id.' ]); } $stmt = $db->prepare(" SELECT * FROM business_partners WHERE idpartner = :idpartner LIMIT 1 "); $stmt->execute([':idpartner' => $idpartner]); $partner = $stmt->fetch(PDO::FETCH_ASSOC); if (!$partner) { jsonResponse([ 'success' => false, 'message' => 'Business partner not found.' ]); } jsonResponse([ 'success' => true, 'partner' => $partner ]); } if ($action === 'change_partner_status') { $idpartner = isset($_POST['idpartner']) ? (int) $_POST['idpartner'] : 0; $status = $_POST['status'] ?? 'inactive'; if ($idpartner <= 0 || !array_key_exists($status, $partnerStatuses)) { jsonResponse([ 'success' => false, 'message' => 'Invalid request.' ]); } $stmt = $db->prepare(" UPDATE business_partners SET status = :status, updated_at = NOW() WHERE idpartner = :idpartner "); $stmt->execute([ ':status' => $status, ':idpartner' => $idpartner, ]); jsonResponse([ 'success' => true, 'message' => 'Business partner status updated successfully.' ]); } if ($action === 'delete_partner') { $idpartner = isset($_POST['idpartner']) ? (int) $_POST['idpartner'] : 0; if ($idpartner <= 0) { jsonResponse([ 'success' => false, 'message' => 'Invalid partner id.' ]); } /* * Safe delete: * Do not delete a partner if already used by samples or parts. */ $stmt = $db->prepare(" SELECT (SELECT COUNT(*) FROM samples WHERE idproducer = :idpartner1 OR idsupplier = :idpartner2) AS samples_count, (SELECT COUNT(*) FROM sample_parts WHERE supplier_id = :idpartner3 OR producer_id = :idpartner4) AS parts_count "); $stmt->execute([ ':idpartner1' => $idpartner, ':idpartner2' => $idpartner, ':idpartner3' => $idpartner, ':idpartner4' => $idpartner, ]); $usage = $stmt->fetch(PDO::FETCH_ASSOC); if (((int) $usage['samples_count'] > 0) || ((int) $usage['parts_count'] > 0)) { jsonResponse([ 'success' => false, 'message' => 'This partner is linked to samples or BOM parts. Set it as inactive instead of deleting it.' ]); } $stmt = $db->prepare(" DELETE FROM business_partners WHERE idpartner = :idpartner "); $stmt->execute([':idpartner' => $idpartner]); jsonResponse([ 'success' => true, 'message' => 'Business partner deleted successfully.' ]); } if ($action === 'get_partner_contacts') { $idpartner = isset($_POST['idpartner']) ? (int) $_POST['idpartner'] : 0; if ($idpartner <= 0) { jsonResponse([ 'success' => false, 'message' => 'Invalid partner id.' ]); } $stmt = $db->prepare(" SELECT * FROM business_partner_contacts WHERE idpartner = :idpartner ORDER BY is_primary DESC, contact_name ASC "); $stmt->execute([':idpartner' => $idpartner]); jsonResponse([ 'success' => true, 'contacts' => $stmt->fetchAll(PDO::FETCH_ASSOC) ]); } if ($action === 'save_contact') { $idcontact = isset($_POST['idcontact']) ? (int) $_POST['idcontact'] : 0; $idpartner = isset($_POST['idpartner']) ? (int) $_POST['idpartner'] : 0; $contactName = trim($_POST['contact_name'] ?? ''); $role = trim($_POST['role'] ?? ''); $email = trim($_POST['email'] ?? ''); $phone = trim($_POST['phone'] ?? ''); $mobile = trim($_POST['mobile'] ?? ''); $isPrimary = isset($_POST['is_primary']) ? (int) $_POST['is_primary'] : 0; $notes = trim($_POST['notes'] ?? ''); $status = $_POST['status'] ?? 'active'; if ($idpartner <= 0) { jsonResponse([ 'success' => false, 'message' => 'Partner is required.' ]); } if ($contactName === '') { jsonResponse([ 'success' => false, 'message' => 'Contact name is required.' ]); } if (!array_key_exists($status, $contactStatuses)) { $status = 'active'; } /* * If this contact is primary, unset other primary contacts for the same partner. */ if ($isPrimary === 1) { $stmt = $db->prepare(" UPDATE business_partner_contacts SET is_primary = 0 WHERE idpartner = :idpartner "); $stmt->execute([':idpartner' => $idpartner]); } if ($idcontact > 0) { $stmt = $db->prepare(" UPDATE business_partner_contacts SET contact_name = :contact_name, role = :role, email = :email, phone = :phone, mobile = :mobile, is_primary = :is_primary, notes = :notes, status = :status, updated_at = NOW() WHERE idcontact = :idcontact AND idpartner = :idpartner "); $stmt->execute([ ':contact_name' => $contactName, ':role' => $role !== '' ? $role : null, ':email' => $email !== '' ? $email : null, ':phone' => $phone !== '' ? $phone : null, ':mobile' => $mobile !== '' ? $mobile : null, ':is_primary' => $isPrimary === 1 ? 1 : 0, ':notes' => $notes !== '' ? $notes : null, ':status' => $status, ':idcontact' => $idcontact, ':idpartner' => $idpartner, ]); jsonResponse([ 'success' => true, 'message' => 'Contact updated successfully.' ]); } $stmt = $db->prepare(" INSERT INTO business_partner_contacts ( idpartner, contact_name, role, email, phone, mobile, is_primary, notes, status, created_at, updated_at ) VALUES ( :idpartner, :contact_name, :role, :email, :phone, :mobile, :is_primary, :notes, :status, NOW(), NOW() ) "); $stmt->execute([ ':idpartner' => $idpartner, ':contact_name' => $contactName, ':role' => $role !== '' ? $role : null, ':email' => $email !== '' ? $email : null, ':phone' => $phone !== '' ? $phone : null, ':mobile' => $mobile !== '' ? $mobile : null, ':is_primary' => $isPrimary === 1 ? 1 : 0, ':notes' => $notes !== '' ? $notes : null, ':status' => $status, ]); jsonResponse([ 'success' => true, 'message' => 'Contact created successfully.' ]); } if ($action === 'get_contact') { $idcontact = isset($_POST['idcontact']) ? (int) $_POST['idcontact'] : 0; if ($idcontact <= 0) { jsonResponse([ 'success' => false, 'message' => 'Invalid contact id.' ]); } $stmt = $db->prepare(" SELECT * FROM business_partner_contacts WHERE idcontact = :idcontact LIMIT 1 "); $stmt->execute([':idcontact' => $idcontact]); $contact = $stmt->fetch(PDO::FETCH_ASSOC); if (!$contact) { jsonResponse([ 'success' => false, 'message' => 'Contact not found.' ]); } jsonResponse([ 'success' => true, 'contact' => $contact ]); } if ($action === 'delete_contact') { $idcontact = isset($_POST['idcontact']) ? (int) $_POST['idcontact'] : 0; if ($idcontact <= 0) { jsonResponse([ 'success' => false, 'message' => 'Invalid contact id.' ]); } $stmt = $db->prepare(" DELETE FROM business_partner_contacts WHERE idcontact = :idcontact "); $stmt->execute([':idcontact' => $idcontact]); jsonResponse([ 'success' => true, 'message' => 'Contact deleted successfully.' ]); } jsonResponse([ 'success' => false, 'message' => 'Unknown action.' ]); } catch (Throwable $e) { jsonResponse([ 'success' => false, 'message' => $e->getMessage() ]); } } /* * Page data. */ $companies = []; $countries = []; $partners = []; try { $stmt = $db->query(" SELECT idcompany, company_name, status FROM companies ORDER BY company_name ASC "); $companies = $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (Throwable $e) { $companies = []; } try { $stmt = $db->query(" SELECT id, name, iso_3166_2 FROM auth_countries ORDER BY name ASC "); $countries = $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (Throwable $e) { $countries = []; } try { $stmt = $db->query(" SELECT bp.idpartner, bp.idcompany, bp.partner_type, bp.partner_name, bp.legal_name, bp.external_code, bp.vat_number, bp.city, bp.email, bp.phone, bp.status, bp.created_at, c.company_name, ac.name AS country_name, COUNT(DISTINCT bpc.idcontact) AS contacts_count, SUM(CASE WHEN bpc.is_primary = 1 THEN 1 ELSE 0 END) AS primary_contacts_count, COUNT(DISTINCT s1.idsample) AS producer_samples_count, COUNT(DISTINCT s2.idsample) AS supplier_samples_count, COUNT(DISTINCT sp1.idpart) AS producer_parts_count, COUNT(DISTINCT sp2.idpart) AS supplier_parts_count FROM business_partners bp INNER JOIN companies c ON c.idcompany = bp.idcompany LEFT JOIN auth_countries ac ON ac.id = bp.country_id LEFT JOIN business_partner_contacts bpc ON bpc.idpartner = bp.idpartner LEFT JOIN samples s1 ON s1.idproducer = bp.idpartner LEFT JOIN samples s2 ON s2.idsupplier = bp.idpartner LEFT JOIN sample_parts sp1 ON sp1.producer_id = bp.idpartner LEFT JOIN sample_parts sp2 ON sp2.supplier_id = bp.idpartner GROUP BY bp.idpartner, bp.idcompany, bp.partner_type, bp.partner_name, bp.legal_name, bp.external_code, bp.vat_number, bp.city, bp.email, bp.phone, bp.status, bp.created_at, c.company_name, ac.name ORDER BY c.company_name ASC, bp.partner_name ASC "); $partners = $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (Throwable $e) { $partners = []; } $pageTitle = 'Business Partners'; $totalPartners = count($partners); $activePartners = count(array_filter($partners, fn($row) => $row['status'] === 'active')); $totalContacts = array_sum(array_map(fn($row) => (int) $row['contacts_count'], $partners)); ?> <?= e($pageTitle); ?> - <?= isset($titlewebsite) ? e($titlewebsite) : 'TRFgo'; ?>
TRFgo Master Data

Business Partners

Manage producers, suppliers, manufacturers, vendors, factories, laboratories and contacts. These records will be used in sample identity cards, BOM parts, TRF requests and document flows.

Total Partners
Active Partners
Contacts
Partner List

Suppliers, producers, vendors, laboratories and related entities

No companies available. Create at least one company before adding business partners.
Partner Company Type External Code Country / City Email Contacts Usage Status Actions
VAT:
-'; ?>
-'; ?>
-
Active Suspended Inactive