Files
Gas-Tank-AR-App/GasTankAR/Services/DocuframeService.swift
2026-09-02 20:54:36 +02:00

72 lines
2.6 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// DocuframeService.swift
// GasTankAR
//
// Created by Dennis Nemec on 28.08.26.
//
import Foundation
/// Foto-Übergabeobjekt für DOCUframe-Vorgänge – bewusst unabhängig von der
/// Persistenzschicht (SwiftData), damit die Domäne keine Speicher-Details kennt.
struct DocuframePhoto: Sendable {
let imageData: Data
let creationDate: Date
let latitude: Double?
let longitude: Double?
}
/// Fehler bei DOCUframe-Vorgängen.
enum DocuframeError: LocalizedError, Equatable {
case noPhotosSelected
/// Der Server hat mit einem 4xx-Status geantwortet (fehlerhafte Anfrage).
case clientError(statusCode: Int)
/// Der Server hat mit einem 5xx-Status geantwortet (Serverproblem).
case serverError(statusCode: Int)
/// Netzwerk-/Transportfehler (z. B. keine Verbindung).
case transport(String)
var errorDescription: String? {
switch self {
case .noPhotosSelected:
"Es wurden keine Fotos ausgewählt."
case .clientError(let statusCode):
"Die Anfrage wurde von DOCUframe abgelehnt (Fehler \(statusCode)). Bitte prüfe die Daten und versuche es erneut."
case .serverError(let statusCode):
"DOCUframe ist derzeit nicht erreichbar (Serverfehler \(statusCode)). Bitte versuche es später erneut."
case .transport(let message):
message
}
}
/// Bildet einen HTTP-Statuscode auf den passenden Fehler ab – `nil` bei Erfolg (2xx/3xx).
static func from(statusCode: Int) -> DocuframeError? {
switch statusCode {
case 400..<500: .clientError(statusCode: statusCode)
case 500..<600: .serverError(statusCode: statusCode)
default: nil
}
}
}
extension HTTPURLResponse {
/// Wirft einen ``DocuframeError``, wenn der Statuscode einen 4xx-/5xx-Fehler darstellt.
func validateDocuframeStatus() throws {
if let error = DocuframeError.from(statusCode: statusCode) {
throw error
}
}
}
/// Abstraktion des DOCUframe-Zugriffs (Upload & Mailversand).
///
/// Clean-Architecture-Grenze: Die Präsentationsschicht hängt nur von diesem Protokoll ab,
/// nicht von der konkreten DOCUframe-Anbindung. Konkrete Implementierungen (Stub, echte
/// Anbindung, Mock für Tests) liegen in der Infrastruktur- bzw. Testschicht.
protocol DocuframeService: Sendable {
/// Lädt die übergebenen Fotos zum Projekt (Lead) in DOCUframe hoch.
func uploadPhotos(_ photos: [DocuframePhoto], projectLeadID: String) async throws
/// Versendet die übergebenen Fotos als E-Mail über DOCUframe.
func sendEmail(_ photos: [DocuframePhoto], projectLeadID: String) async throws
}