false, 'error' => 'Data permintaan tidak valid']); exit; } $db = db(); $db->beginTransaction(); try { $invoice_no = 'INV-' . strtoupper(bin2hex(random_bytes(4))); $member_id = $data['member_id'] ? (int)$data['member_id'] : null; $total_amount = (float)$data['total']; $payment_method = $data['payment_method'] ?? 'cash'; $cash_received = (float)($data['cash_received'] ?? 0); $change_amount = (float)($data['change_amount'] ?? 0); $points_redeemed = (int)($data['points_redeemed'] ?? 0); $voucher_id = $data['voucher_id'] ? (int)$data['voucher_id'] : null; // Points calculation (1 point for every 10k spent) $points_earned = $member_id ? (int)floor($total_amount / 10000) : 0; // Insert sale $stmt = $db->prepare("INSERT INTO sales (invoice_no, member_id, total_amount, payment_method, cash_received, change_amount, points_earned, points_redeemed, voucher_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->execute([$invoice_no, $member_id, $total_amount, $payment_method, $cash_received, $change_amount, $points_earned, $points_redeemed, $voucher_id]); $sale_id = $db->lastInsertId(); // Process items $stmtItem = $db->prepare("INSERT INTO sale_items (sale_id, product_id, quantity, unit_price, subtotal) VALUES (?, ?, ?, ?, ?)"); $stmtStock = $db->prepare("UPDATE products SET stock = stock - ? WHERE id = ?"); foreach ($data['items'] as $item) { $subtotal = $item['qty'] * $item['price']; $stmtItem->execute([$sale_id, $item['id'], $item['qty'], $item['price'], $subtotal]); $stmtStock->execute([$item['qty'], $item['id']]); } // Update member points if ($member_id) { $stmtMember = $db->prepare("UPDATE members SET points = points + ? - ? WHERE id = ?"); $stmtMember->execute([$points_earned, $points_redeemed, $member_id]); } // Mark voucher as used if ($voucher_id) { $stmtVoucher = $db->prepare("UPDATE vouchers SET is_used = 1 WHERE id = ?"); $stmtVoucher->execute([$voucher_id]); } $db->commit(); echo json_encode(['success' => true, 'invoice_no' => $invoice_no]); } catch (Exception $e) { $db->rollBack(); echo json_encode(['success' => false, 'error' => $e->getMessage()]); }