//
// [Link]
// CrusherBooks
//
import Foundation
class EInvoiceService {
static let shared = EInvoiceService()
// Replace with your GSP's e-invoice endpoint
private let apiEndpointURL = URL(string:
"[Link]
// MARK: - E-Invoice Request Model (Simplified)
struct EInvoiceRequest: Codable {
let TranDtls: TransactionDetails
let DocDtls: DocumentDetails
let SellerDtls: PartyDetails
let BuyerDtls: PartyDetails
let ItemList: [Item]
}
struct TransactionDetails: Codable {
let SupTyp: String // B2B
}
struct DocumentDetails: Codable {
let Typ: String // "INV"
let No: String
let Dt: String // "dd/MM/yyyy"
}
struct PartyDetails: Codable {
let Gstin: String
let LglNm: String // Legal Name
let Addr1: String
let Loc: String
let StCd: Int // State Code
}
struct Item: Codable {
let SlNo: String
let PrdDesc: String
let HsnCd: String
let Qty: Double
let Unit: String // e.g., "TON"
let UnitPrice: Double
let TotAmt: Double
let TaxableVal: Double
let CgstRt: Double
let SgstRt: Double
let IgstRt: Double
let CgstAmt: Double
let SgstAmt: Double
let IgstAmt: Double
let TotItemVal: Double // TaxableVal + All GST
}
// MARK: - E-Invoice Response Model
struct EInvoiceResponse: Decodable {
let AckNo: Int
let AckDt: String // "2025-11-10 15:30:00"
let Irn: String
let SignedQRCode: String
}
// MARK: - API Call Function
func generateIRN(
payload: EInvoiceRequest,
apiUsername: String
) async throws -> EInvoiceResponse {
// 1. Get password from Keychain
guard let passwordData = try [Link](account:
apiUsername),
let password = String(data: passwordData, encoding: .utf8) else {
throw [Link](reason: "API Password not found in
Keychain. Please set it in your Profile.")
}
// 2. Prepare request
var request = URLRequest(url: apiEndpointURL)
[Link] = "POST"
[Link]("application/json", forHTTPHeaderField: "Content-Type")
// 3. Set Auth Headers (depends on your GSP)
[Link](apiUsername, forHTTPHeaderField: "GSP-Username")
[Link](password, forHTTPHeaderField: "GSP-Password")
// 4. Encode Payload
do {
let encoder = JSONEncoder()
[Link] = try [Link](payload)
} catch {
print("Failed to encode E-Invoice payload: \(error)")
throw [Link](reason: "Failed to create e-invoice request
payload.")
}
// 5. Make Network Call
// let (data, response) = try await [Link](for: request)
// ... handle response, decode, etc.
// --- MOCK API CALL (For Testing) ---
print("--- E-INVOICE PAYLOAD ---")
print("Username: \(apiUsername)")
try await [Link](nanoseconds: 2_000_000_000)
// Simulate a potential error
if [Link] {
throw [Link](reason: "API Error: Buyer GSTIN is
required for B2B e-invoice.")
}
// Return a MOCK response
let mockAckNo = [Link](in: 100000...999999)
let mockIRN = UUID().[Link](of: "-", with:
"").lowercased()
let dateFormatter = DateFormatter()
[Link] = "yyyy-MM-dd HH:mm:ss"
[Link] = Locale(identifier: "en_US_POSIX")
return EInvoiceResponse(
AckNo: mockAckNo,
AckDt: [Link](from: Date()),
Irn: mockIRN,
SignedQRCode: "MOCK_SIGNED_QR_CODE_STRING_\(mockIRN)"
)
// --- END MOCK API CALL ---
}
}