56 lines
2.1 KiB
Swift
56 lines
2.1 KiB
Swift
import Foundation
|
|
|
|
/// `/api/export/{csv,excel,pdf}` — Pro-only (403 `pro_required` for a
|
|
/// free-plan account, surfaced via `APIError.server`). Every route takes the
|
|
/// same request body and returns the raw file with its name in
|
|
/// `Content-Disposition`; present the returned `Data` via `UIActivityViewController`
|
|
/// (share sheet) or write it into a temp file and use `.fileExporter` /
|
|
/// `QLPreviewController` — either is fine, this layer just gets you the bytes.
|
|
enum ExportAPI {
|
|
enum Format: String {
|
|
case csv, excel, pdf
|
|
|
|
var path: String { "/api/export/\(rawValue)" }
|
|
var fallbackExtension: String {
|
|
switch self {
|
|
case .csv: return "csv"
|
|
case .excel: return "xlsx"
|
|
case .pdf: return "pdf"
|
|
}
|
|
}
|
|
}
|
|
|
|
struct ExportRequestBody: Encodable {
|
|
let receipts: [Receipt]
|
|
let locale: String
|
|
// Only meaningful for the PDF export (date range on the cover page);
|
|
// harmless to omit for csv/excel, which ignore unknown fields.
|
|
var dateFrom: String?
|
|
var dateTo: String?
|
|
}
|
|
|
|
struct ExportResult {
|
|
let data: Data
|
|
let fileName: String
|
|
}
|
|
|
|
/// - Parameters:
|
|
/// - receipts: exactly the receipts to include — the backend does not
|
|
/// look anything up server-side, it only formats what you send.
|
|
/// - locale: `"de"` or `"en"`; anything else falls back to German on
|
|
/// the backend, so just always pass one of the two.
|
|
static func export(
|
|
_ format: Format,
|
|
receipts: [Receipt],
|
|
locale: String = "de",
|
|
dateFrom: String? = nil,
|
|
dateTo: String? = nil
|
|
) async throws -> ExportResult {
|
|
let body = ExportRequestBody(receipts: receipts, locale: locale, dateFrom: dateFrom, dateTo: dateTo)
|
|
let request = try APIRequest.json(path: format.path, method: .post, body: body)
|
|
let (data, suggestedName) = try await APIClient.shared.sendForFile(request)
|
|
let fileName = suggestedName ?? "Belege_Export.\(format.fallbackExtension)"
|
|
return ExportResult(data: data, fileName: fileName)
|
|
}
|
|
}
|