RepuestosOriente
Cuentas con RIF, permisos a nivel de vista y de objeto, órdenes separadas por vendedor con precios congelados, y una infraestructura que cuesta $0/mes en producción real, con el cold start hecho visible en vez de escondido.
La infraestructura de este marketplace cuesta $0 al mes. El precio se paga en otra moneda: el servidor se duerme.
Repuestos automotrices con tres roles, un checkout que produce una orden por vendedor y un catálogo con fotos. Cuatro planes gratuitos, un producto en producción real, y el cold start hecho visible en vez de escondido.
Una petición viaja de la SPA a Postgres pasando por dos preguntas de permiso
Pulsa los pasos o deja que avance. Cada paso ilumina la pieza de la que habla.
company_name y rif: el marketplace nace pensado para negocios que se compran entre sí, y el catálogo queda abierto al público sin login.Un taller compra a dos distribuidoras en un solo checkout
Un caso inventado con números pequeños, marcado como ejemplo, para ver qué pasa en cada tramo.
product.seller. Orden 1 para Distribuidora Oriente ($36 + $12), orden 2 para Repuestos Maturín ($20). Cada OrderItem guarda precio, precio original y descuento del momento. El stock baja y el carrito se vacía.Cinco veces en que la solución obvia estaba mal
Lo que cualquiera haría primero, por qué no sirve, lo que se hizo y el número que lo demuestra. El detalle técnico queda plegado.
Cada plan gratuito cobra en algo que no es dinero: Render en latencia al despertar, Supabase en un pooler sin estado, R2 en URLs que no se parecen a las de local. El trabajo fue pagar esos peajes en el código, no en la factura.
Un filtro: ¿esto añade una factura mensual o quita tiempo de producto?
Si añadía factura, se buscó el plan gratuito equivalente. Si quitaba tiempo, se eligió lo que ya viene resuelto.
Profundizar
El admin de Django es el back-office desde el primer día: cargar catálogo, verificar vendedores, revisar órdenes. Escribirlo a mano habría sido la mitad del proyecto.
None en vez de lanzar, para no cortar la cadena de autenticación.Profundizar
Los tokens se guardan en localStorage y un hook renueva el access token cinco minutos antes de que expire, con un candado para no lanzar dos refresh a la vez.
BaseModel marca deleted_at y reimplementa la cascada de Django introspeccionando _meta.related_objects: CASCADE borra en cadena, SET_NULL anula el campo, ManyToMany se limpia, y restore() deshace la cascada.Profundizar
Un _deletion_context con las claves ya visitadas evita los ciclos A→B→A. Dos managers por modelo: objects filtra los borrados, all_objects no. Es el código más sofisticado del proyecto y también el más frágil: cualquier constraint único puede chocar con una fila "borrada".
Profundizar
Reparto: Firebase Hosting sirve la SPA desde CDN con rewrite a index.html; Render construye y despliega la API con cada push; Supabase da Postgres con pooler; R2 guarda las fotos con API S3 y sin cobrar egress; Whitenoise sirve los estáticos de Django sin un bucket más.
La versión mínima de la conexión a datos en producción, tal como la lee prod.py: