72 lines
2.6 KiB
Swift
72 lines
2.6 KiB
Swift
//
|
||
// 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
|
||
}
|