AI News Hub Logo

AI News Hub

Cómo construimos Rents: gestión de alquileres para el mercado argentino con Expo + Node.js

DEV Community
Rents Argentina

El mercado de alquileres en Argentina es único: inflación alta, contratos ajustados por índices oficiales (ICL, IPC, CER), operaciones en doble moneda (ARS/USD), y regulación cambiante. Construir una app para propietarios argentinos requirió resolver estos desafíos específicos. Los propietarios con 2-10 propiedades en alquiler necesitan: Controlar cuándo vence cada contrato Calcular el próximo ajuste según ICL Registrar cobros en pesos y dólares Enviar recordatorios a inquilinos por WhatsApp No existía ninguna herramienta diseñada para esta realidad. Construimos Rents — una plataforma cross-platform (iOS, Android, Web) que automatiza la gestión de alquileres con lógica específica para Argentina. Frontend: Expo (React Native) + TypeScript Backend: Node.js + Hono + TypeScript Database: PostgreSQL + Drizzle ORM Cache: Redis Storage: Cloudflare R2 Auth: Lucia Auth + JWT Deploy: Kamal (Docker) en VPS Usamos un monorepo con pnpm workspaces para compartir tipos y schemas de validación entre frontend y backend: // packages/validation/src/schemas/contract.ts export const createContractSchema = z.object({ propertyId: z.string().uuid(), tenantId: z.string().uuid(), startDate: z.string(), monthlyRent: z.number().positive(), currency: z.enum(['ARS', 'USD']), adjustmentIndex: z.enum(['ICL', 'IPC', 'CER', 'NONE']), }); El mismo schema se usa tanto en el formulario de React Native como en la validación del endpoint de Hono. El cálculo de ajuste de alquiler según ICL es complejo: cada período tiene una fecha de inicio, un índice base y uno de comparación. Lo modelamos como un scheduler de ajustes: // Genera todos los períodos de ajuste automáticamente async function createAdjustmentSchedule( contract: Contract, indexData: ICLData[] ) { const periods = generateAdjustmentPeriods( contract.startDate, contract.endDate, contract.adjustmentFrequency ); return periods.map(period => ({ contractId: contract.id, periodStart: period.start, periodEnd: period.end, baseIndex: getIndexForDate(indexData, period.start), newIndex: getIndexForDate(indexData, period.end), adjustmentFactor: null, // se calcula cuando llega la fecha })); } Los contratos en dólares se registran en USD pero se puede llevar el tracking en ambas monedas. La clave fue no intentar convertir en tiempo real — simplemente guardamos la moneda del pago junto al monto. Con Expo Router, el mismo código corre en iOS, Android y Web. La lógica de negocio está completamente separada de la UI, lo que facilita testear la parte crítica (cálculos financieros) sin el overhead de React Native Testing Library. Cambios legales frecuentes: La Ley de Alquileres cambió en 2023 y otra vez en 2024. Necesitábamos que los ajustes sean configurables, no hardcodeados. ICL mensual: El índice se publica el primer día hábil de cada mes. Tuvimos que construir un job que lo consulta y actualiza automáticamente los contratos pendientes. WhatsApp como canal primario: Los propietarios argentinos no mandan emails — mandan WhatsApp. Integramos envío de recordatorios via API de WhatsApp Business directamente desde la plataforma. Una plataforma que entiende que $ 150.000 y u$s 500 son dos realidades distintas que coexisten en el mismo portfolio. Pueden probarla en rents.ar. ¿Tenés experiencia construyendo apps financieras para mercados con alta inflación? Me interesa el intercambio.