UNPKG

@sahabaplus/moyasar

Version:

A comprehensive TypeScript SDK for integrating with the Moyasar payment gateway

190 lines 6.17 kB
import { InvoiceStatus } from "./enums"; import { CreateInvoiceSchema, BulkCreateInvoiceSchema, invoiceSchema, } from "./validation/schemas"; import { PaymentStatus } from "../payment/index"; export class InvoiceUtils { /** * Validate single invoice creation request using Zod */ static validateCreateInvoiceRequest(request) { const result = CreateInvoiceSchema.safeParse(request); if (result.success) { return { success: true, data: result.data, errors: [], }; } const errors = result.error.issues.map(err => { const path = err.path.length > 0 ? `${err.path.join(".")}: ` : ""; return `${path}${err.message}`; }); return { success: false, errors, }; } /** * Validate bulk invoice creation request using Zod */ static validateBulkCreateRequest(request) { const result = BulkCreateInvoiceSchema.safeParse(request); if (result.success) { return { success: true, data: result.data, errors: [], }; } const errors = result.error.issues.map(err => { let message = err.message; // Format array index errors more clearly if (err.path.length >= 2 && err.path[0] === "invoices" && typeof err.path[1] === "number") { const invoiceIndex = err.path[1]; const fieldPath = err.path.slice(2).join("."); const fieldPrefix = fieldPath ? `${fieldPath}: ` : ""; message = `Invoice ${invoiceIndex + 1}: ${fieldPrefix}${err.message}`; } else if (err.path.length > 0) { const path = err.path.join("."); message = `${path}: ${err.message}`; } return message; }); return { success: false, errors, }; } /** * Convert amount to display format */ static formatAmount(amount, currency) { const divisors = { KWD: 1000, JPY: 1, SAR: 100, USD: 100, EUR: 100, }; const divisor = divisors[currency] ?? 100; const formattedAmount = (amount / divisor).toFixed(divisor === 1 ? 0 : 2); return `${formattedAmount} ${currency}`; } /** * Parse amount from display format to smallest unit */ static parseAmount(formattedAmount, currency) { const divisors = { KWD: 1000, JPY: 1, SAR: 100, USD: 100, EUR: 100, }; const amount = parseFloat(formattedAmount.replace(/[^\d.]/g, "")); const divisor = divisors[currency.toUpperCase()] || 100; return Math.round(amount * divisor); } /** * Check if invoice is in a final state */ static isInvoiceFinal(status) { const finalStatuses = [ InvoiceStatus.PAID, InvoiceStatus.CANCELED, InvoiceStatus.EXPIRED, InvoiceStatus.VOIDED, ]; return finalStatuses.includes(status); } /** * Check if invoice can be canceled */ static canCancelInvoice(invoice) { const cancelableStatuses = [ InvoiceStatus.INITIATED, InvoiceStatus.FAILED, ]; return cancelableStatuses.includes(invoice.status); } /** * Check if invoice is expired */ static isInvoiceExpired(invoice) { if (!invoice.expired_at) { return false; } return new Date(invoice.expired_at) <= new Date(); } /** * Get time until expiry */ static getTimeUntilExpiry(invoice) { if (!invoice.expired_at) { return null; } const expiryTime = new Date(invoice.expired_at).getTime(); const currentTime = new Date().getTime(); return Math.max(0, expiryTime - currentTime); } /** * Get payment summary for an invoice */ static getPaymentSummary(invoice) { const payments = invoice.payments; return { total: payments.length, paid: payments.filter(p => p.status === PaymentStatus.PAID).length, failed: payments.filter(p => p.status === PaymentStatus.FAILED).length, pending: payments.filter(p => p.status === PaymentStatus.INITIATED) .length, totalAmount: payments.reduce((sum, p) => sum + p.amount, 0), paidAmount: payments .filter(p => p.status === PaymentStatus.PAID) .reduce((sum, p) => sum + p.amount, 0), refundedAmount: payments.reduce((sum, p) => sum + p.refunded, 0), }; } /** * Build metadata query parameters for filtering */ static buildMetadataQuery(metadata) { const query = {}; Object.entries(metadata).forEach(([key, value]) => { query[`metadata[${key}]`] = value; }); return query; } /** * Sanitize invoice description */ static sanitizeDescription(description) { return description.trim().substring(0, 255); } /** * Generate invoice reference number */ static generateReference(prefix = "INV") { const timestamp = Date.now().toString(36); const random = Math.random().toString(36).substring(2, 8); return `${prefix}-${timestamp}-${random}`.toUpperCase(); } /** * Parse and validate a CreateInvoiceRequest, returning sanitized data */ static parseCreateInvoiceRequest(request) { return this.validateCreateInvoiceRequest(request); } /** * Parse and validate a BulkCreateInvoiceRequest, returning sanitized data */ static parseBulkCreateRequest(request) { return this.validateBulkCreateRequest(request); } static parseInvoice(invoice) { return invoiceSchema.parse(invoice); } } //# sourceMappingURL=utils.js.map