### Get All Clients (TypeScript) Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Retrieves a list of all clients associated with the active company, sorted alphabetically by name. The output is an array of client objects, suitable for use in UI components like dropdowns. ```typescript import { getClientes } from "@/lib/actions/cliente" const clients = await getClientes() // Returns array: // [ // { // id: "uuid-1", // nombre: "Acme Corp", // email: "contact@acme.com", // telefono: "+34 91 000 00 00", // ... // }, // ... // ] // Use in component: clients.map(client => ( )) ``` -------------------------------- ### Get Stripe Pricing Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Retrieves current subscription prices from Stripe, including IVA (VAT) calculations and discounts for additional companies. This function requires access to Stripe API configurations and returns a detailed pricing object for monthly and yearly plans. ```typescript import { getStripePrices } from "@/lib/actions/stripe" const pricing = await getStripePrices() // Returns: // { // ivaRate: 0.21, // ivaPercent: 21, // additionalCompanyDiscount: 0.15, // additionalCompanyDiscountPercent: 15, // monthly: { base: 21.99, iva: 4.62, total: 26.61, priceId: "price_1234" }, // yearly: { base: 211.10, iva: 44.33, total: 255.43, monthlyEquivalent: 21.29, savingsPercent: 20, priceId: "price_5678" }, // discounted: { // 15% off for additional companies // monthly: { base: 18.69, iva: 3.93, total: 22.62 }, // yearly: { base: 179.44, iva: 37.68, total: 217.12, monthlyEquivalent: 18.09 } // } // } // Display pricing: console.log(`Primera empresa: €${pricing.monthly.total}/mes`) console.log(`Empresas adicionales: €${pricing.discounted.monthly.total}/mes (-${pricing.additionalCompanyDiscountPercent}%)`) console.log(`Plan anual: €${pricing.yearly.total}/año (ahorro ${pricing.yearly.savingsPercent}%)`) ``` -------------------------------- ### Add Document Hierarchy (TypeScript) Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Adds hierarchical content such as titles, subtitles, and line items to documents. It requires importing specific creation functions and provides examples for creating each level of the hierarchy. Calculations for line items, including subtotals, discounts, base amounts, and VAT, are demonstrated. ```typescript import { createTitulo, createSubtitulo, createLinea } from "@/lib/actions/documento" // Add section (título) const titulo = await createTitulo({ documento_id: "uuid-doc-123", nombre: "Servicios de Desarrollo", descripcion: "Desarrollo aplicación web React/Next.js", orden: 0 }) // Add subsection (subtítulo) const subtitulo = await createSubtitulo({ titulo_id: titulo.id, nombre: "Frontend Development", descripcion: "Implementación de componentes UI", orden: 0 }) // Add line items (líneas) const linea = await createLinea({ subtitulo_id: subtitulo.id, descripcion: "Desarrollo de dashboard administrativo", informacion_adicional: "Incluye gráficos y reportes", cantidad: 80, unidad: "horas", precio_unitario: 65.00, descuento_porcentaje: 10, tipo_iva: 21, // 21%, 10%, 4%, or 0% orden: 0 }) // Line calculations: // Subtotal = 80 * 65.00 = 5200.00 // Discount = 5200.00 * 10% = 520.00 // Base = 5200.00 - 520.00 = 4680.00 // IVA = 4680.00 * 21% = 982.80 ``` -------------------------------- ### Get Current User Information Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Retrieves the details of the currently authenticated user. If no user is authenticated, it prompts a redirect to the login page. This function allows access to user email, ID, and other metadata, making it essential for personalized user experiences. ```typescript import { getCurrentUser } from "@/lib/actions/auth" const user = await getCurrentUser() if (!user) { // Not authenticated, redirect to login redirect("/login") } else { console.log("User:", user.email) console.log("User ID:", user.id) // Access user metadata: console.log("Full name:", user.user_metadata?.full_name) } ``` -------------------------------- ### Get Expense Statistics Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Retrieves aggregated statistics for expenses incurred within the current month. It returns the total amount spent, total IVA, and the count of pending and paid expenses. ```typescript import { getGastosStats } from "@/lib/actions/gasto" const stats = await getGastosStats() // Returns: // { // total: 1500.50, // Total expenses this month // iva: 315.11, // Total IVA this month // pendientes: 3, // Count of pending payments // pagados: 12 // Count of paid expenses this month // } // Display in dashboard: console.log(`Gastos del mes: €${stats.total.toFixed(2)}`) console.log(`${stats.pendientes} facturas pendientes de pago`) ``` -------------------------------- ### Convert Document Type - TypeScript Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Converts a document from one type to another, for example, from a quote to a final invoice. This operation clones all existing content, including titles, subtitles, and lines, while updating series, numbers, and relevant flags. The financial data remains the same. ```typescript import { convertDocumento } from "@/lib/actions/documento" // Convert quote to final invoice const newInvoice = await convertDocumento( "uuid-presupuesto-123", "factura_definitiva" ) // Creates new document with: // - New series and number (e.g., P-2025-0010 → F-2025-0042) // - All títulos, subtítulos, and líneas cloned // - Same client and financial data // - Updated flags (es_editable, estado_envio_aeat) console.log(`Converted ${oldDoc.numero_completo} to ${newInvoice.numero_completo}`) ``` -------------------------------- ### Get Company Subscription Status Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Retrieves the current subscription status and trial information for a given company ID from Stripe. It returns details on whether the subscription is active, in trial, or past due, along with renewal dates and trial end information. Requires a company ID as input. ```typescript import { getCompanySubscription } from "@/lib/actions/stripe" const subscription = await getCompanySubscription("uuid-company-123") if (!subscription) { console.log("No active subscription or trial") } else if (subscription.status === "trialing") { console.log(`Trial ends in ${subscription.trialDaysLeft} days`) console.log(`Trial expires: ${subscription.trialEndsAt.toLocaleDateString()}`) } else { console.log(`Status: ${subscription.status}`) // "active", "past_due", etc. console.log(`${subscription.isYearly ? "Yearly" : "Monthly"} plan`) console.log(`Renews: ${subscription.currentPeriodEnd.toLocaleDateString()}`) console.log(`Cancel scheduled: ${subscription.cancelAtPeriodEnd}`) } ``` -------------------------------- ### Create Project Record Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Creates a new project record. This includes essential project details such as name, description, and optional client assignment and a specific site address for the work. ```typescript import { createProyecto } from "@/lib/actions/proyecto" const project = await createProyecto({ nombre: "Desarrollo Plataforma E-commerce", descripcion: "Tienda online con pasarela de pago integrada y panel de administración", cliente_id: "uuid-cliente-123", direccion_obra: "Oficinas cliente - Calle Gran Vía 50, Madrid" }) // Returns: // { // id: "uuid-proyecto-789", // nombre: "Desarrollo Plataforma E-commerce", // company_id: "uuid-company", // created_at: "2025-01-15T10:00:00Z", // ... // } ``` -------------------------------- ### Project Management API Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Endpoints for creating, updating, and organizing projects, including linking documents and clients. ```APIDOC ## POST /api/projects ### Description Creates a new project with optional client and location information. ### Method POST ### Endpoint /api/projects ### Parameters #### Request Body - **nombre** (string) - Required - The name of the project. - **descripcion** (string) - Optional - A detailed description of the project. - **cliente_id** (string) - Optional - The ID of the client associated with the project. - **direccion_obra** (string) - Optional - The construction or work site address. ### Response #### Success Response (200) - **id** (string) - The unique identifier for the created project. - **nombre** (string) - The name of the project. - **company_id** (string) - The ID of the company the project belongs to. - **created_at** (string) - Timestamp of when the project was created. ### Request Example ```json { "nombre": "Desarrollo Plataforma E-commerce", "descripcion": "Tienda online con pasarela de pago integrada y panel de administración", "cliente_id": "uuid-cliente-123", "direccion_obra": "Oficinas cliente - Calle Gran Vía 50, Madrid" } ``` #### Response Example ```json { "id": "uuid-proyecto-789", "nombre": "Desarrollo Plataforma E-commerce", "company_id": "uuid-company", "created_at": "2025-01-15T10:00:00Z" } ``` ## PUT /api/projects/{projectId}/move-document ### Description Assigns a document (invoice or quote) to a specific project for organization. Setting `proyecto_id` to `null` unassigns the document. ### Method PUT ### Endpoint /api/projects/{projectId}/move-document ### Parameters #### Path Parameters - **projectId** (string or null) - Required - The ID of the project to assign the document to, or `null` to unassign. #### Request Body - **documentoId** (string) - Required - The ID of the document to move. ### Response #### Success Response (200) - Indicates successful assignment or unassignment. The response body might be empty or confirm the action. ### Assign Example (Request Body) ```json { "documentoId": "uuid-documento-123" } ``` ### Unassign Example (Request Body) ```json { "documentoId": "uuid-documento-123" } ``` ## PUT /api/projects/{projectId} ### Description Modifies existing project information, including name, description, client assignment, and work address. ### Method PUT ### Endpoint /api/projects/{projectId} ### Parameters #### Path Parameters - **projectId** (string) - Required - The ID of the project to update. #### Request Body - **nombre** (string) - Optional - The updated name of the project. - **descripcion** (string) - Optional - The updated description of the project. - **cliente_id** (string) - Optional - The ID of the client to associate with the project. - **direccion_obra** (string) - Optional - The updated work site address. ### Response #### Success Response (200) - **id** (string) - The ID of the updated project. - **updated_at** (string) - Timestamp of when the project was last updated. ### Request Example ```json { "nombre": "E-commerce Platform + Mobile App", "descripcion": "Expanded scope: Added iOS and Android apps", "cliente_id": "uuid-cliente-456", "direccion_obra": "Nueva dirección de obra" } ``` ``` -------------------------------- ### Client Management API Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt APIs for creating, retrieving, updating, and checking the existence of client records. ```APIDOC ## POST /api/clients ### Description Creates a new client record with contact and address information. ### Method POST ### Endpoint `/api/clients` ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **nombre** (string) - Required - The name of the client company. - **nif_cif** (string) - Optional - The tax identification number of the client. - **direccion** (string) - Required - The street address of the client. - **codigo_postal** (string) - Required - The postal code of the client's city. - **ciudad** (string) - Required - The city where the client is located. - **provincia** (string) - Required - The province or state of the client. - **pais** (string) - Required - The country where the client is located. - **email** (string) - Required - The primary email address for the client. - **telefono** (string) - Required - The primary phone number for the client. - **persona_contacto** (string) - Optional - The name and title of the primary contact person. - **notas** (string) - Optional - Any additional notes or remarks about the client. ### Request Example ```json { "nombre": "Tech Innovations S.L.", "nif_cif": "B87654321", "direccion": "Paseo de la Castellana 100", "codigo_postal": "28046", "ciudad": "Madrid", "provincia": "Madrid", "pais": "España", "email": "contacto@techinnovations.es", "telefono": "+34 91 123 45 67", "persona_contacto": "María García - CFO", "notas": "Cliente desde 2020. Pago a 30 días. Descuento 5% en proyectos grandes." } ``` ### Response #### Success Response (200) Returns the complete client object, including the newly generated `id` and `created_at` timestamp, along with all provided input fields. #### Response Example ```json { "id": "uuid", "company_id": "uuid", "created_at": "2024-01-01T12:00:00.000Z", "updated_at": "2024-01-01T12:00:00.000Z", "nombre": "Tech Innovations S.L.", "nif_cif": "B87654321", "direccion": "Paseo de la Castellana 100", "codigo_postal": "28046", "ciudad": "Madrid", "provincia": "Madrid", "pais": "España", "email": "contacto@techinnovations.es", "telefono": "+34 91 123 45 67", "persona_contacto": "María García - CFO", "notas": "Cliente desde 2020. Pago a 30 días. Descuento 5% en proyectos grandes." } ``` ## GET /api/clients ### Description Retrieves all clients for the active company, sorted alphabetically by name. ### Method GET ### Endpoint `/api/clients` ### Parameters #### Path Parameters N/A #### Query Parameters N/A ### Request Example N/A (No request body or parameters needed) ### Response #### Success Response (200) Returns an array of client objects, each containing basic information like `id`, `nombre`, `email`, and `telefono`. #### Response Example ```json [ { "id": "uuid-1", "nombre": "Acme Corp", "email": "contact@acme.com", "telefono": "+34 91 000 00 00", "nif_cif": "A12345678", "direccion": "Calle Inventada 1", "codigo_postal": "28001", "ciudad": "Madrid", "provincia": "Madrid", "pais": "España", "persona_contacto": "Juan Perez", "notas": "Primer cliente.", "created_at": "2023-01-15T10:00:00.000Z", "updated_at": "2023-01-15T10:00:00.000Z" }, { "id": "uuid-2", "nombre": "Beta Solutions", "email": "info@betasolutions.com", "telefono": "+34 93 111 22 33", "nif_cif": "B98765432", "direccion": "Avinguda Diagonal 200", "codigo_postal": "08008", "ciudad": "Barcelona", "provincia": "Barcelona", "pais": "España", "persona_contacto": "Ana Lopez", "notas": "Pagos puntuales.", "created_at": "2023-05-20T14:30:00.000Z", "updated_at": "2023-05-20T14:30:00.000Z" } ] ``` ## PUT /api/clients/{id} ### Description Updates client information for existing records. Requires the client's ID. ### Method PUT ### Endpoint `/api/clients/{id}` ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the client to update. #### Query Parameters N/A #### Request Body - **nombre** (string) - Optional - The updated name of the client company. - **nif_cif** (string) - Optional - The updated tax identification number. - **direccion** (string) - Optional - The updated street address. - **codigo_postal** (string) - Optional - The updated postal code. - **ciudad** (string) - Optional - The updated city. - **provincia** (string) - Optional - The updated province or state. - **pais** (string) - Optional - The updated country. - **email** (string) - Optional - The updated primary email address. - **telefono** (string) - Optional - The updated primary phone number. - **persona_contacto** (string) - Optional - The updated contact person's name and title. - **notas** (string) - Optional - Updated additional notes about the client. ### Request Example ```json { "email": "newemail@techinnovations.es", "telefono": "+34 91 999 88 77", "direccion": "Nueva ubicación - Calle Serrano 45", "notas": "Actualizado método de pago - ahora por transferencia" } ``` ### Response #### Success Response (200) Returns the complete, updated client object, including the `updated_at` timestamp. #### Response Example ```json { "id": "uuid-cliente-123", "company_id": "uuid", "created_at": "2024-01-01T12:00:00.000Z", "updated_at": "2024-01-02T10:30:00.000Z", "nombre": "Tech Innovations S.L.", "nif_cif": "B87654321", "direccion": "Nueva ubicación - Calle Serrano 45", "codigo_postal": "28046", "ciudad": "Madrid", "provincia": "Madrid", "pais": "España", "email": "newemail@techinnovations.es", "telefono": "+34 91 999 88 77", "persona_contacto": "María García - CFO", "notas": "Actualizado método de pago - ahora por transferencia" } ``` ## GET /api/clients/exists/{id} ### Description Verifies if a client with the specified ID exists in the active company. ### Method GET ### Endpoint `/api/clients/exists/{id}` ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the client to check. #### Query Parameters N/A ### Request Example N/A (Only path parameter is needed) ### Response #### Success Response (200) Returns a boolean value: `true` if the client exists, `false` otherwise. #### Response Example ```json true ``` ### Error Handling - If the client ID is invalid or not found, it returns `false`. ``` -------------------------------- ### Create Client Record (TypeScript) Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Creates a new client record, including company details, contact information, and address. The function returns the complete client object, including a generated ID and timestamps. ```typescript import { createCliente } from "@/lib/actions/cliente" const newClient = await createCliente({ nombre: "Tech Innovations S.L.", nif_cif: "B87654321", direccion: "Paseo de la Castellana 100", codigo_postal: "28046", ciudad: "Madrid", provincia: "Madrid", pais: "España", email: "contacto@techinnovations.es", telefono: "+34 91 123 45 67", persona_contacto: "María García - CFO", notas: "Cliente desde 2020. Pago a 30 días. Descuento 5% en proyectos grandes." }) // Returns complete client object with: // { id: "uuid", company_id: "uuid", created_at: "...", ...input } ``` -------------------------------- ### Move Document to Project Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Assigns a document (like an invoice or quote) to a specific project for better financial organization. It can also be used to unassign a document by setting the project ID to null. This action revalidates project and document-related paths. ```typescript import { moveDocumentoToProyecto } from "@/lib/actions/proyecto" // Assign document to project await moveDocumentoToProyecto( "uuid-documento-123", "uuid-proyecto-789" ) // Remove from project (unassign) await moveDocumentoToProyecto( "uuid-documento-123", null ) // Revalidates /proyectos, /facturas, /presupuestos // Document now appears in project financial summary ``` -------------------------------- ### Document Management API Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt APIs for managing hierarchical content within documents, including adding sections, subsections, and line items. ```APIDOC ## Add Document Structure ### Description Adds hierarchical content to documents, including titles, subtitles, and line items. ### Method Not specified (this is a function call example, not a direct HTTP endpoint) ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A (function arguments) ### Request Example ```typescript import { createTitulo, createSubtitulo, createLinea } from "@/lib/actions/documento" // Add section (título) const titulo = await createTitulo({ documento_id: "uuid-doc-123", nombre: "Servicios de Desarrollo", descripcion: "Desarrollo aplicación web React/Next.js", orden: 0 }) // Add subsection (subtítulo) const subtitulo = await createSubtitulo({ titulo_id: titulo.id, nombre: "Frontend Development", descripcion: "Implementación de componentes UI", orden: 0 }) // Add line items (líneas) const linea = await createLinea({ subtitulo_id: subtitulo.id, descripcion: "Desarrollo de dashboard administrativo", informacion_adicional: "Incluye gráficos y reportes", cantidad: 80, unidad: "horas", precio_unitario: 65.00, descuento_porcentaje: 10, tipo_iva: 21, // 21%, 10%, 4%, or 0% orden: 0 }) // Line calculations: // Subtotal = 80 * 65.00 = 5200.00 // Discount = 5200.00 * 10% = 520.00 // Base = 5200.00 - 520.00 = 4680.00 // IVA = 4680.00 * 21% = 982.80 ``` ### Response #### Success Response (200) Returns the created document element (titulo, subtitulo, or linea) with its ID and other properties. #### Response Example ```json { "id": "uuid", "documento_id": "uuid-doc-123", "titulo_id": null, // or "uuid" "subtitulo_id": null, // or "uuid" "nombre": "Example Name", "descripcion": "Example Description", "orden": 0, "informacion_adicional": null, "cantidad": null, "unidad": null, "precio_unitario": null, "descuento_porcentaje": null, "tipo_iva": null, "created_at": "2024-01-01T12:00:00.000Z", "updated_at": "2024-01-01T12:00:00.000Z" } ``` ## Delete Document ### Description Deletes a document if the `es_eliminable` flag is true. ### Method Not specified (this is a function call example, not a direct HTTP endpoint) ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A (function arguments) ### Request Example ```typescript import { deleteDocumento } from "@/lib/actions/documento" try { await deleteDocumento("uuid-doc-123") console.log("Document deleted successfully") } catch (error) { // Throws: "Este documento no se puede eliminar" if es_eliminable is false console.error(error) } ``` ### Response #### Success Response (200) Indicates successful deletion of the document. #### Response Example `console.log("Document deleted successfully")` ### Error Handling Throws an error if the document cannot be deleted (e.g., `es_eliminable` is false). ``` -------------------------------- ### Create Document (Invoice, Quote, Draft) - TypeScript Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Creates a new document such as an invoice, quote, or draft. It automatically handles series numbering and tax calculations, including IRPF withholding. The function requires detailed input for client information, financial data, and VeriFactu compliance fields. The response includes auto-generated fields like series, number, and status. ```typescript "use server" import { createDocumento } from "@/lib/actions/documento" // Create a new invoice const newInvoice = await createDocumento({ tipo: "factura_definitiva", // or "presupuesto", "borrador", "factura_rectificativa" cliente_id: "uuid-cliente-123", cliente_nombre: "Acme Corporation S.L.", cliente_nif: "B12345678", cliente_direccion: "Calle Mayor 123, 28013 Madrid", fecha_vencimiento: "2025-02-14", referencia: "Proyecto Web 2025", notas: "Pago a 30 días", // VeriFactu compliance fields descripcion_operacion: "Servicios de desarrollo web", clave_regimen_iva: "01", fecha_operacion: "2025-01-15", mostrar_verifactu: true, // Tax calculations total_base: 5000.00, base_21: 5000.00, iva_21: 1050.00, total_iva: 1050.00, retencion_irpf_porcentaje: 15, total_general: 5300.00, // base + iva - irpf // Additional options recargo_equivalencia: false, gastos_suplidos: 50.00, descripcion_gastos_suplidos: "Gastos de envío", cantidad_pagada: 0, observaciones_receptor: "Factura según contrato firmado", mostrar_observaciones: true }) // Response includes auto-generated fields: // { // id: "uuid", // serie: "F", // numero: 42, // numero_completo: "F-2025-0042", // es_editable: false, // es_eliminable: false, // estado_envio_aeat: "pendiente", // created_at: "2025-01-15T10:30:00Z" // } ``` -------------------------------- ### Create Stripe Checkout Session Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Initiates a Stripe checkout session for subscription purchases. It automatically applies a discount for additional companies and handles tax ID and billing address collection. The function redirects the user to Stripe's checkout page and requires a company ID and subscription period ('monthly' or 'yearly'). ```typescript import { createCheckoutSession } from "@/lib/actions/stripe" // Redirect to Stripe checkout (Server Action automatically redirects) await createCheckoutSession( "uuid-company-123", "yearly" // or "monthly" ) // Checkout session includes: // - Automatic 15% discount if order_index > 1 // - Tax ID collection for Spanish businesses // - Billing address collection // - Subscription metadata (company_id, user_id) // - Success URL: /suscripcion/exito?session_id={CHECKOUT_SESSION_ID} // - Cancel URL: /suscripcion ``` -------------------------------- ### Expense Management API Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt API endpoints for managing expense records, including creation, retrieval of statistics, and assignment to projects. ```APIDOC ## POST /api/expenses ### Description Creates a new expense record with optional project assignment. ### Method POST ### Endpoint /api/expenses ### Parameters #### Request Body - **concepto** (string) - Required - The concept of the expense. - **descripcion** (string) - Optional - A detailed description of the expense. - **fecha** (string) - Required - The date of the expense (YYYY-MM-DD). - **proveedor** (string) - Required - The name of the vendor or provider. - **nif_proveedor** (string) - Optional - The tax identification number of the provider. - **categoria** (string) - Required - The category the expense belongs to. - **base_imponible** (number) - Required - The taxable amount of the expense. - **iva** (number) - Required - The amount of VAT (IVA) for the expense. - **total** (number) - Required - The total amount of the expense. - **tipo_iva** (number) - Required - The VAT rate applied (e.g., 21). - **metodo_pago** (string) - Required - The payment method used. - **numero_factura** (string) - Optional - The invoice number. - **es_deducible** (boolean) - Required - Whether the expense is deductible. - **estado** (string) - Required - The status of the expense (e.g., "pagado", "pendiente"). - **proyecto_id** (string) - Optional - The ID of the project this expense is associated with. - **notas** (string) - Optional - Additional notes about the expense. - **archivo_url** (string) - Optional - URL to the receipt or invoice file. ### Response #### Success Response (200) - **id** (string) - The unique identifier for the created expense. - **user_id** (string) - The ID of the user who created the expense. - **company_id** (string) - The ID of the company the expense belongs to. - **created_at** (string) - Timestamp of when the expense was created. ### Request Example ```json { "concepto": "Servidor AWS - Enero 2025", "descripcion": "Instancias EC2 y S3 storage", "fecha": "2025-01-31", "proveedor": "Amazon Web Services", "nif_proveedor": "W0184081H", "categoria": "Servicios cloud", "base_imponible": 250.00, "iva": 52.50, "total": 302.50, "tipo_iva": 21, "metodo_pago": "Tarjeta de crédito", "numero_factura": "INV-2025-0142", "es_deducible": true, "estado": "pagado", "proyecto_id": "uuid-proyecto-123", "notas": "Renovación automática mensual", "archivo_url": "https://storage.com/recibo-aws-ene.pdf" } ``` #### Response Example ```json { "id": "uuid-gasto-456", "user_id": "uuid-user", "company_id": "uuid-company", "created_at": "2025-01-15T10:00:00Z" } ``` ## GET /api/expenses/stats ### Description Retrieves aggregated expense statistics for the current month. ### Method GET ### Endpoint /api/expenses/stats ### Response #### Success Response (200) - **total** (number) - Total expenses for the current month. - **iva** (number) - Total VAT (IVA) for the current month. - **pendientes** (integer) - Count of pending payment expenses. - **pagados** (integer) - Count of paid expenses. #### Response Example ```json { "total": 1500.50, "iva": 315.11, "pendientes": 3, "pagados": 12 } ``` ## PUT /api/expenses/{expenseId}/assign-project ### Description Links an expense to a specific project for cost tracking. Can also be used to unassign an expense from a project by setting `proyecto_id` to null. ### Method PUT ### Endpoint /api/expenses/{expenseId}/assign-project ### Parameters #### Path Parameters - **expenseId** (string) - Required - The ID of the expense to assign. #### Request Body - **proyecto_id** (string or null) - Optional - The ID of the project to assign the expense to, or `null` to unassign. ### Response #### Success Response (200) - Indicates successful assignment or unassignment. The response body might be empty or confirm the action. ### Request Example ```json { "proyecto_id": "uuid-proyecto-123" } ``` ### Unassign Example ```json { "proyecto_id": null } ``` ``` -------------------------------- ### Send WhatsApp Message - Twilio Integration (Commented) Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt This commented-out section shows a potential production integration for sending WhatsApp messages using the Twilio API. It requires Twilio credentials and defines the parameters for sending a message with media (the PDF invoice). ```javascript // Production integration (currently commented): // const twilio = require('twilio')(accountSid, authToken) // const result = await twilio.messages.create({ // from: 'whatsapp:+14155238886', // to: `whatsapp:${telefono}`, // body: mensaje, // mediaUrl: [pdfUrl] // }) ``` -------------------------------- ### Email Communication API Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt API for sending emails, specifically designed for sending invoices or quotes with PDF attachments. ```APIDOC ## POST /api/send-email ### Description Sends an invoice or quote via email with a PDF attachment using the Resend API. ### Method POST ### Endpoint `/api/send-email` ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **type** (string) - Required - The type of communication, typically 'invoice' or 'quote'. - **destinatario** (string) - Required - The email address of the recipient. - **asunto** (string) - Required - The subject line of the email. - **clienteNombre** (string) - Required - The name of the client. - **tipoDocumento** (string) - Required - The type of document being sent (e.g., 'factura_definitiva', 'presupuesto'). - **numeroDocumento** (string) - Required - The reference number of the document. - **companyInfo** (object) - Required - An object containing the sender's company details. - **nombre** (string) - Required - Sender company name. - **email** (string) - Required - Sender company email. - **telefono** (string) - Optional - Sender company phone number. - **direccion** (string) - Optional - Sender company address. - **codigoPostal** (string) - Optional - Sender company postal code. - **ciudad** (string) - Optional - Sender company city. - **nif** (string) - Optional - Sender company tax ID. - **pdfBase64** (string) - Required - The PDF content encoded in Base64. - **pdfFilename** (string) - Required - The filename for the attached PDF. ### Request Example ```json { "type": "invoice", "destinatario": "cliente@empresa.com", "asunto": "Factura F-2025-0042 - Servicios enero 2025", "clienteNombre": "Acme Corporation S.L.", "tipoDocumento": "factura_definitiva", // or "presupuesto" "numeroDocumento": "F-2025-0042", "companyInfo": { "nombre": "Mi Empresa S.L.", "email": "facturas@miempresa.com", "telefono": "+34 91 123 45 67", "direccion": "Calle Principal 1", "codigoPostal": "28001", "ciudad": "Madrid", "nif": "B12345678" }, "pdfBase64": "JVBERi0xLjQKJeLjz9MKMy...", // Base64 encoded PDF "pdfFilename": "Factura-F-2025-0042.pdf" } ``` ### Response #### Success Response (200) Indicates if the email was sent successfully. #### Response Example ```json { "success": true, "messageId": "resend-message-id" } ``` ### Error Handling - If the email fails to send, the response will indicate `success: false` and include an error message. - Possible errors include: - `Email service not configured` (missing `RESEND_API_KEY` environment variable). - `Error sending email` (indicates an issue with the Resend API or the provided data). #### Response Example (Error) ```json { "success": false, "error": "Email service not configured" } ``` ``` -------------------------------- ### Create Expense Record Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Creates a new expense record in the system. This function allows for detailed expense information including concept, description, date, vendor, amounts (base, IVA, total), payment method, invoice number, and deduction status. It can optionally be assigned to a project. ```typescript import { createGasto } from "@/lib/actions/gasto" const expense = await createGasto({ concepto: "Servidor AWS - Enero 2025", descripcion: "Instancias EC2 y S3 storage", fecha: "2025-01-31", proveedor: "Amazon Web Services", nif_proveedor: "W0184081H", categoria: "Servicios cloud", base_imponible: 250.00, iva: 52.50, total: 302.50, tipo_iva: 21, metodo_pago: "Tarjeta de crédito", numero_factura: "INV-2025-0142", es_deducible: true, estado: "pagado", // or "pendiente" proyecto_id: "uuid-proyecto-123", // optional notas: "Renovación automática mensual", archivo_url: "https://storage.com/recibo-aws-ene.pdf" }) // Returns expense with id, user_id, company_id, created_at ``` -------------------------------- ### Update Project Information Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Modifies the details of an existing project. This includes updating the project's name, description, and potentially changing the assigned client. The function returns the updated project object with a new timestamp. ```typescript import { updateProyecto } from "@/lib/actions/proyecto" const updated = await updateProyecto("uuid-proyecto-789", { nombre: "E-commerce Platform + Mobile App", descripcion: "Expanded scope: Added iOS and Android apps", cliente_id: "uuid-cliente-456", // Change client direccion_obra: "Nueva dirección de obra" }) // Returns updated project with new updated_at timestamp ``` -------------------------------- ### Check Client Existence (TypeScript) Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Verifies whether a client with the specified ID exists within the active company. This is useful for preventing operations on non-existent clients, such as invoice creation. ```typescript import { checkClienteExists } from "@/lib/actions/cliente" const exists = await checkClienteExists("uuid-cliente-123") if (exists) { // Proceed with invoice creation } else { // Show error or create client first console.log("Client not found, please create client first") } ``` -------------------------------- ### Send Team Invitation Email Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Sends a styled invitation email to new team members. It requires a recipient email, company name, invitation URL, and a personalized message. The email includes a styled header, company name, message, and a call-to-action button. ```typescript // POST /api/send-email const response = await fetch("/api/send-email", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ type: "invitation", destinatario: "nuevo.miembro@email.com", asunto: "Invitación al equipo de Mi Empresa S.L.", empresaNombre: "Mi Empresa S.L.", invitationUrl: "https://app.yotu.com/invitacion/token-abc123", mensaje: "Te invitamos a colaborar en la gestión de facturación" }) }) const result = await response.json() // { success: true, messageId: "resend-message-id" } // Email includes: // - Styled header with gradient // - Company name // - Personalized message // - Call-to-action button with invitation URL // - Fallback plain text link ``` -------------------------------- ### Handle Stripe Webhooks Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Processes incoming Stripe webhook events to manage the subscription lifecycle. This includes updating subscription status, storing subscription IDs, handling payment successes and failures, and managing cancellations. Requires configuring a webhook URL in the Stripe dashboard and setting the STRIPE_WEBHOOK_SECRET environment variable. ```typescript // POST /api/stripe/webhook // Stripe automatically sends webhooks to this endpoint // Handled events: // 1. checkout.session.completed // - Updates subscription_status to "active" // - Stores stripe_subscription_id // - Disables trial (is_trial_active = false) // 2. customer.subscription.updated // - Updates subscription_status (active, past_due, canceled, etc.) // 3. customer.subscription.deleted // - Marks subscription as canceled // 4. invoice.payment_succeeded // - Logs successful payment // 5. invoice.payment_failed // - Logs payment failure for company // Configure in Stripe Dashboard: // Webhook URL: https://your-app.com/api/stripe/webhook // Events: checkout.session.completed, customer.subscription.*, invoice.* // Webhook secret: Set STRIPE_WEBHOOK_SECRET env variable ``` -------------------------------- ### Send Team Invitation Email Source: https://context7.com/huliichuk/yotu-plus-verifactu-copia/llms.txt Sends a styled invitation email to new team members, including company branding and a personalized message with a call-to-action button. ```APIDOC ## POST /api/send-email ### Description Sends styled invitation email for team members to join a company. ### Method POST ### Endpoint /api/send-email ### Parameters #### Request Body - **type** (string) - Required - Type of email, expected to be "invitation". - **destinatario** (string) - Required - The email address of the recipient. - **asunto** (string) - Required - The subject line of the email. - **empresaNombre** (string) - Required - The name of the company sending the invitation. - **invitationUrl** (string) - Required - The URL for the invitation. - **mensaje** (string) - Required - The personalized message for the invitation. ### Request Example ```json { "type": "invitation", "destinatario": "nuevo.miembro@email.com", "asunto": "Invitación al equipo de Mi Empresa S.L.", "empresaNombre": "Mi Empresa S.L.", "invitationUrl": "https://app.yotu.com/invitacion/token-abc123", "mensaje": "Te invitamos a colaborar en la gestión de facturación" } ``` ### Response #### Success Response (200) - **success** (boolean) - Indicates if the email was sent successfully. - **messageId** (string) - The ID of the sent message. #### Response Example ```json { "success": true, "messageId": "resend-message-id" } ``` ```