* Liefert Detail eines einzelnen Auftrags. * GET /api/orders.php?id=&action=photos * Liefert die Anhang-Bilder/PDFs eines Auftrags. * POST /api/orders.php?id=&action=upload_photo * multipart: file= — fügt ein Foto zum Bericht des Auftrags hinzu * (legt automatisch einen Bericht an wenn keiner existiert) * POST /api/orders.php?action=create * JSON-Body: { socid, title, ref_client?, note_private?, date? } * Legt einen Draft-Auftrag an und übernimmt Kunden-Defaults (Zahlungsbedingungen, * Zahlart, Bankkonto, Incoterms, Lieferadresse, Default-Ansprechpartner). */ require_once __DIR__.'/_inc.php'; api_authenticate(); global $db, $user, $conf; require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; $id = (int) ($_GET['id'] ?? 0); $action = $_GET['action'] ?? ''; /* ----- NEUEN AUFTRAG ANLEGEN ----- */ if ($action === 'create' && $_SERVER['REQUEST_METHOD'] === 'POST') { if (!$user->hasRight('commande', 'creer')) api_fail('Keine Berechtigung zum Anlegen von Aufträgen', 403); $in = api_input(); $socid = (int) ($in['socid'] ?? 0); $title = trim((string) ($in['title'] ?? '')); $ref_client = trim((string) ($in['ref_client'] ?? '')); $note_private = trim((string) ($in['note_private'] ?? '')); $date = (int) ($in['date'] ?? 0); if ($date <= 0) $date = dol_now(); if ($socid <= 0) api_fail('socid fehlt'); // Kundenstamm holen, um Defaults zu ziehen (wie Dolibarr-Web beim Auftrag-Anlegen) $soc = new Societe($db); if ($soc->fetch($socid) <= 0) api_fail('Kunde nicht gefunden', 404); $cmd = new Commande($db); $cmd->socid = $socid; $cmd->date_commande = $date; $cmd->date = $date; $cmd->ref_client = $ref_client; $cmd->note_private = $note_private; // Kunden-Defaults übernehmen if (!empty($soc->cond_reglement_id)) $cmd->cond_reglement_id = (int) $soc->cond_reglement_id; if (!empty($soc->mode_reglement_id)) $cmd->mode_reglement_id = (int) $soc->mode_reglement_id; if (!empty($soc->fk_account)) $cmd->fk_account = (int) $soc->fk_account; if (!empty($soc->fk_incoterms)) $cmd->fk_incoterms = (int) $soc->fk_incoterms; if (!empty($soc->location_incoterms)) $cmd->location_incoterms = $soc->location_incoterms; if (!empty($soc->fk_delivery_address)) $cmd->fk_delivery_address = (int) $soc->fk_delivery_address; // Titel des Auftrags in Extrafield "auftragsbeschreibung" ablegen (das Bericht-Modul nutzt dieses) if ($title !== '') { if (!is_array($cmd->array_options)) $cmd->array_options = array(); $cmd->array_options['options_auftragsbeschreibung'] = $title; } $newid = $cmd->create($user); if ($newid <= 0) api_fail('Anlegen fehlgeschlagen: '.$cmd->error, 500); // Hauptansprechpartner aus llx_socpeople als externen Kontakt hinzufügen (falls vorhanden) $sql_c = "SELECT rowid FROM ".$db->prefix()."socpeople" ." WHERE fk_soc = ".((int) $socid)." AND statut = 1" ." ORDER BY rowid ASC LIMIT 1"; $rc = $db->query($sql_c); if ($rc && ($oc = $db->fetch_object($rc))) { $cmd->add_contact((int) $oc->rowid, 'CUSTOMER', 'external'); } // Für identische Response-Shape wie GET ?id= neu laden $cmd->fetch($newid); $cmd->fetch_thirdparty(); if (method_exists($cmd, 'fetch_optionals')) $cmd->fetch_optionals(); api_ok(array( 'order' => array( 'id' => (int) $cmd->id, 'ref' => $cmd->ref, 'date' => $cmd->date_commande, 'status' => (int) $cmd->statut, 'total' => (float) $cmd->total_ttc, 'note_private' => $cmd->note_private, 'auftragsbeschreibung' => $cmd->array_options['options_auftragsbeschreibung'] ?? '', ), 'customer' => array( 'id' => (int) ($cmd->thirdparty->id ?? 0), 'name' => $cmd->thirdparty->name ?? '', 'address' => $cmd->thirdparty->address ?? '', 'zip' => $cmd->thirdparty->zip ?? '', 'town' => $cmd->thirdparty->town ?? '', 'phone' => $cmd->thirdparty->phone ?? '', 'email' => $cmd->thirdparty->email ?? '', ), )); } /* ----- LISTE ----- */ if (!$id) { // Filter: nur Aufträge des aktuellen Users (oder Admin sieht alle) $where = "c.entity IN (".getEntity('commande').")"; if (empty($user->admin)) { $where .= " AND (c.fk_user_author = ".((int) $user->id) ." OR c.fk_user_valid = ".((int) $user->id) ." OR c.fk_user_modif = ".((int) $user->id).")"; } // Optional: nur offene if (!empty($_GET['open'])) { $where .= " AND c.fk_statut IN (1, 2)"; // validiert + in Bearbeitung } // Suchterm if (!empty($_GET['q'])) { $q = $db->escape($_GET['q']); $where .= " AND (c.ref LIKE '%$q%' OR s.nom LIKE '%$q%')"; } $sql = "SELECT c.rowid, c.ref, c.ref_client, c.date_commande, c.fk_statut, c.total_ttc," ." s.rowid AS soc_id, s.nom AS soc_name, s.zip, s.town, s.address," ." (SELECT COUNT(*) FROM ".$db->prefix()."bericht b WHERE b.element_type='order' AND b.fk_element=c.rowid) AS bericht_count" ." FROM ".$db->prefix()."commande c" ." LEFT JOIN ".$db->prefix()."societe s ON s.rowid = c.fk_soc" ." WHERE ".$where ." ORDER BY c.date_commande DESC, c.rowid DESC" ." LIMIT 200"; $r = $db->query($sql); if (!$r) api_fail('DB-Fehler: '.$db->lasterror(), 500); $orders = array(); while ($o = $db->fetch_object($r)) { $orders[] = array( 'id' => (int) $o->rowid, 'ref' => $o->ref, 'ref_client' => $o->ref_client, 'date' => $db->jdate($o->date_commande), 'status'=> (int) $o->fk_statut, 'total' => (float) $o->total_ttc, 'customer' => array( 'id' => (int) $o->soc_id, 'name' => $o->soc_name, 'zip' => $o->zip, 'town' => $o->town, 'address' => $o->address, ), 'bericht_count' => (int) $o->bericht_count, ); } api_ok(array('orders' => $orders, 'count' => count($orders))); } /* ----- DETAIL eines Auftrags ----- */ $cmd = new Commande($db); if ($cmd->fetch($id) <= 0) api_fail('Auftrag nicht gefunden', 404); $cmd->fetch_thirdparty(); if (method_exists($cmd, 'fetch_optionals')) $cmd->fetch_optionals(); if ($action === 'photos') { // Anhänge des Auftrags $upload_dir = $conf->commande->multidir_output[$cmd->entity].'/'.dol_sanitizeFileName($cmd->ref); $files = is_dir($upload_dir) ? dol_dir_list($upload_dir, 'files', 1, '', '(\.meta|_preview.*\.png|thumbs)$') : array(); $out = array(); foreach ($files as $f) { $out[] = array( 'filename' => $f['name'], 'size' => (int) $f['size'], 'mime' => dol_mimetype($f['name']), 'date' => (int) $f['date'], 'relpath' => str_replace(DOL_DATA_ROOT.'/', '', $f['fullname']), ); } api_ok(array('photos' => $out, 'count' => count($out))); } if ($action === 'upload_photo' && $_SERVER['REQUEST_METHOD'] === 'POST') { if (!$user->hasRight('bericht', 'write')) api_fail('Schreibrechte fehlen', 403); if (empty($_FILES['file']['tmp_name'])) api_fail('file fehlt'); // Datei validieren $orig = dol_sanitizeFileName($_FILES['file']['name']); $ext = strtolower(pathinfo($orig, PATHINFO_EXTENSION)); if (!in_array($ext, array('jpg', 'jpeg', 'png'))) api_fail('Dateityp nicht unterstützt'); // Foto direkt in den Dolibarr-Standard-Auftragsordner speichern (kein Bericht nötig) $upload_dir = $conf->commande->multidir_output[$cmd->entity].'/'.dol_sanitizeFileName($cmd->ref); if (!is_dir($upload_dir)) dol_mkdir($upload_dir); $filename = 'foto_'.dol_print_date(dol_now(), '%Y%m%d_%H%M%S').'_'.uniqid().'.'.$ext; $target = $upload_dir.'/'.$filename; if (!move_uploaded_file($_FILES['file']['tmp_name'], $target)) api_fail('Upload fehlgeschlagen', 500); $relpath = str_replace(DOL_DATA_ROOT.'/', '', $target); api_ok(array( 'filename' => $filename, 'relpath' => $relpath, 'size' => filesize($target), )); } // Default: Auftrags-Detail $berichte = Bericht::fetchAllForElement($db, 'order', $cmd->id); $berichte_out = array(); foreach ($berichte as $b) { $berichte_out[] = array( 'id' => (int) $b->id, 'ref' => $b->ref, 'titel' => $b->titel, 'status' => (int) $b->status, 'datec' => (int) $b->datec, ); } api_ok(array( 'order' => array( 'id' => (int) $cmd->id, 'ref' => $cmd->ref, 'date' => $cmd->date_commande, 'status'=> (int) $cmd->statut, 'total' => (float) $cmd->total_ttc, 'note_private' => $cmd->note_private, 'auftragsbeschreibung' => $cmd->array_options['options_auftragsbeschreibung'] ?? '', ), 'customer' => array( 'id' => (int) ($cmd->thirdparty->id ?? 0), 'name' => $cmd->thirdparty->name ?? '', 'address' => $cmd->thirdparty->address ?? '', 'zip' => $cmd->thirdparty->zip ?? '', 'town' => $cmd->thirdparty->town ?? '', 'phone' => $cmd->thirdparty->phone ?? '', 'email' => $cmd->thirdparty->email ?? '', ), 'berichte' => $berichte_out, ));