bericht/api/orders.php
Eduard Wisch bed611cd8b
All checks were successful
Deploy bericht / deploy (push) Successful in 1s
feat: Phase 2.3 + 2.4 — REST-API mit JWT-Auth
- api/_jwt.php: HS256 JWT encode/decode/from_request, Secret aus
  dolibarr_main_instance_unique_id, 7 Tage TTL
- api/_inc.php: gemeinsamer API-Init mit CORS, JSON-Helpers,
  api_authenticate() lädt User aus JWT und prüft bericht/read
- api/auth.php: POST { login, password } → JWT mit user + perms
- api/orders.php:
  - GET /api/orders.php — Liste der Aufträge des Users (Multi-User
    Filter über fk_user_*, Admin sieht alle)
  - GET /api/orders.php?id=X — Auftrags-Detail mit Kunde + Berichten
  - GET /api/orders.php?id=X&action=photos — Anhänge
  - POST /api/orders.php?id=X&action=upload_photo — Foto hochladen,
    Bericht wird automatisch angelegt falls nicht vorhanden
- api/reports.php:
  - GET /api/reports.php?id=X — Bericht-Detail + Seiten
  - POST /api/reports.php?id=X&action=finalize — Status auf final

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-08 22:40:52 +02:00

180 lines
6.8 KiB
PHP

<?php
/* GET /api/orders.php
* Liefert Aufträge des aktuellen Users.
* GET /api/orders.php?id=<id>
* Liefert Detail eines einzelnen Auftrags.
* GET /api/orders.php?id=<id>&action=photos
* Liefert die Anhang-Bilder/PDFs eines Auftrags.
* POST /api/orders.php?id=<id>&action=upload_photo
* multipart: file=<binary> — fügt ein Foto zum Bericht des Auftrags hinzu
* (legt automatisch einen Bericht an wenn keiner existiert)
*/
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'] ?? '';
/* ----- 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.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,
'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');
// Bericht zum Auftrag suchen oder neu anlegen
$list = Bericht::fetchAllForElement($db, 'order', $cmd->id);
$bericht = !empty($list) ? $list[0] : null;
if (!$bericht) {
$bericht = new Bericht($db);
$bericht->element_type = 'order';
$bericht->fk_element = $cmd->id;
$bericht->titel = 'Bericht '.$cmd->ref;
$bericht->auftragsnummer = $cmd->ref;
$bericht->template_odt = getDolGlobalString('BERICHT_DEFAULT_TEMPLATE', '');
if ($bericht->create($user) <= 0) api_fail('Bericht-Anlage fehlgeschlagen', 500);
}
// Datei speichern
$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');
$workdir = DOL_DATA_ROOT.'/bericht/work/'.$bericht->id;
if (!is_dir($workdir)) dol_mkdir($workdir);
$target = $workdir.'/api_'.dol_print_date(dol_now(), '%Y%m%d_%H%M%S').'_'.uniqid().'.'.$ext;
if (!move_uploaded_file($_FILES['file']['tmp_name'], $target)) api_fail('Upload fehlgeschlagen', 500);
$relpath = str_replace(DOL_DATA_ROOT.'/', '', $target);
// Als Page anlegen
$resm = $db->query("SELECT COALESCE(MAX(page_order),0) AS m FROM ".$db->prefix()."bericht_page WHERE fk_bericht = ".((int) $bericht->id));
$next = ($resm && ($o = $db->fetch_object($resm))) ? ((int) $o->m) + 1 : 1;
$page = new BerichtPage($db);
$page->fk_bericht = $bericht->id;
$page->page_order = $next;
$page->source_type = 'upload';
$page->source_path = $relpath;
if ($page->create() <= 0) api_fail('Page-Insert fehlgeschlagen', 500);
api_ok(array(
'bericht_id' => (int) $bericht->id,
'page_id' => (int) $page->id,
'filename' => basename($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,
));