false, 'error' => 'Missing parameters']); exit; } // 1. Hole Section-Info $sql = "SELECT fk_facture FROM ".MAIN_DB_PREFIX."facture_lines_manager"; $sql .= " WHERE rowid = ".(int)$section_id; $sql .= " AND line_type = 'section'"; $resql = $db->query($sql); if (!$resql || $db->num_rows($resql) == 0) { echo json_encode(['success' => false, 'error' => 'Section not found']); exit; } $section = $db->fetch_object($resql); $facture_id = $section->fk_facture; // 2. Prüfe Rechnungsstatus $facture = new Facture($db); $facture->fetch($facture_id); if ($force && $facture->statut != Facture::STATUS_DRAFT) { echo json_encode(['success' => false, 'error' => 'Rechnung ist nicht im Entwurf']); exit; } // 3. Hole Produkt-IDs DIREKT aus DB $product_ids = []; $sql_products = "SELECT fk_facturedet FROM ".MAIN_DB_PREFIX."facture_lines_manager"; $sql_products .= " WHERE parent_section = ".(int)$section_id; $sql_products .= " AND line_type = 'product'"; $res_products = $db->query($sql_products); while ($prod = $db->fetch_object($res_products)) { $product_ids[] = (int)$prod->fk_facturedet; } $product_count = count($product_ids); subtotaltitle_debug_log('🔍 Gefundene Produkte in Section: ' . implode(', ', $product_ids)); $db->begin(); // 4. Force-Delete: Produkte aus Rechnung löschen if ($force && $product_count > 0) { subtotaltitle_debug_log('🗑️ Lösche ' . $product_count . ' Zeilen aus Rechnung...'); foreach ($product_ids as $line_id) { $sql_del_line = "DELETE FROM ".MAIN_DB_PREFIX."facturedet WHERE rowid = ".(int)$line_id; $res_del = $db->query($sql_del_line); if ($res_del) { subtotaltitle_debug_log('✅ facturedet gelöscht: ' . $line_id); } else { subtotaltitle_debug_log('❌ SQL Fehler: ' . $line_id . ' - ' . $db->lasterror()); } } // Aus Manager-Tabelle löschen $sql_del = "DELETE FROM ".MAIN_DB_PREFIX."facture_lines_manager"; $sql_del .= " WHERE parent_section = ".(int)$section_id; $sql_del .= " AND line_type = 'product'"; $db->query($sql_del); subtotaltitle_debug_log('🔴 Force-Delete abgeschlossen: ' . $product_count . ' Produkte'); } else if (!$force) { // Ohne force: Produkte nur freigeben $sql = "UPDATE ".MAIN_DB_PREFIX."facture_lines_manager"; $sql .= " SET parent_section = NULL"; $sql .= " WHERE parent_section = ".(int)$section_id; $sql .= " AND line_type = 'product'"; $db->query($sql); subtotaltitle_debug_log('🔓 ' . $product_count . ' Produkte freigegeben'); } // ========== NEU: SUBTOTAL LÖSCHEN ========== // Hole Subtotal dieser Section (falls vorhanden) $sql_subtotal = "SELECT rowid, fk_facturedet FROM ".MAIN_DB_PREFIX."facture_lines_manager"; $sql_subtotal .= " WHERE parent_section = ".(int)$section_id; $sql_subtotal .= " AND line_type = 'subtotal'"; $res_subtotal = $db->query($sql_subtotal); if ($obj_sub = $db->fetch_object($res_subtotal)) { // Falls Subtotal in facturedet ist, dort auch löschen if ($obj_sub->fk_facturedet > 0) { $sql_del_fd = "DELETE FROM ".MAIN_DB_PREFIX."facturedet WHERE rowid = ".(int)$obj_sub->fk_facturedet; $db->query($sql_del_fd); subtotaltitle_debug_log('✅ Subtotal aus facturedet gelöscht: ' . $obj_sub->fk_facturedet); } // Aus Manager-Tabelle löschen $sql_del_sub = "DELETE FROM ".MAIN_DB_PREFIX."facture_lines_manager WHERE rowid = ".(int)$obj_sub->rowid; $db->query($sql_del_sub); subtotaltitle_debug_log('✅ Subtotal aus Manager gelöscht: ' . $obj_sub->rowid); } // ========== VERWAISTE SUBTOTALS AUFRÄUMEN ========== // Finde alle Subtotals in dieser Rechnung, deren parent_section nicht mehr existiert $sql_orphans = "SELECT s.rowid, s.fk_facturedet, s.parent_section FROM ".MAIN_DB_PREFIX."facture_lines_manager s WHERE s.fk_facture = ".(int)$facture_id." AND s.line_type = 'subtotal' AND s.parent_section IS NOT NULL AND NOT EXISTS ( SELECT 1 FROM ".MAIN_DB_PREFIX."facture_lines_manager sec WHERE sec.rowid = s.parent_section AND sec.line_type = 'section' )"; $res_orphans = $db->query($sql_orphans); $orphan_count = 0; while ($orphan = $db->fetch_object($res_orphans)) { // Aus facturedet löschen (falls vorhanden) if ($orphan->fk_facturedet > 0) { $sql_del_orphan_fd = "DELETE FROM ".MAIN_DB_PREFIX."facturedet WHERE rowid = ".(int)$orphan->fk_facturedet; $db->query($sql_del_orphan_fd); subtotaltitle_debug_log('🧹 Verwaistes Subtotal aus facturedet gelöscht: ' . $orphan->fk_facturedet . ' (parent_section=' . $orphan->parent_section . ')'); } // Aus Manager-Tabelle löschen $sql_del_orphan = "DELETE FROM ".MAIN_DB_PREFIX."facture_lines_manager WHERE rowid = ".(int)$orphan->rowid; $db->query($sql_del_orphan); subtotaltitle_debug_log('🧹 Verwaistes Subtotal aus Manager gelöscht: ' . $orphan->rowid); $orphan_count++; } if ($orphan_count > 0) { subtotaltitle_debug_log('🧹 Aufgeräumt: ' . $orphan_count . ' verwaiste Subtotals entfernt'); } // ========== ENDE VERWAISTE SUBTOTALS ========== // 5. Section selbst löschen $sql = "DELETE FROM ".MAIN_DB_PREFIX."facture_lines_manager"; $sql .= " WHERE rowid = ".(int)$section_id; $db->query($sql); // Rechnungstotale neu berechnen (nach allen Löschungen) $facture->update_price(1); // 6. Neuordnen $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture_lines_manager"; $sql .= " WHERE fk_facture = ".(int)$facture_id; $sql .= " ORDER BY line_order"; $resql = $db->query($sql); $new_order = 1; while ($obj = $db->fetch_object($resql)) { $sql_upd = "UPDATE ".MAIN_DB_PREFIX."facture_lines_manager"; $sql_upd .= " SET line_order = ".$new_order; $sql_upd .= " WHERE rowid = ".(int)$obj->rowid; $db->query($sql_upd); $new_order++; } // 7. Sync rang $sql = "SELECT fk_facturedet FROM ".MAIN_DB_PREFIX."facture_lines_manager"; $sql .= " WHERE fk_facture = ".(int)$facture_id; $sql .= " AND line_type = 'product'"; $sql .= " ORDER BY line_order"; $resql = $db->query($sql); $rang = 1; while ($obj = $db->fetch_object($resql)) { $sql_upd = "UPDATE ".MAIN_DB_PREFIX."facturedet"; $sql_upd .= " SET rang = ".$rang; $sql_upd .= " WHERE rowid = ".(int)$obj->fk_facturedet; $db->query($sql_upd); $rang++; } $db->commit(); echo json_encode(['success' => true, 'deleted' => $force ? $product_count : 0]);