Overview
The Customers API manages customer records and their categories with built-in validation, duplicate detection, and bulk import capabilities.
Customer Management
getCustomersFromCache
Retrieves customers from in-memory cache synchronously.
export const getCustomersFromCache = (): Customer[]
Array of customers sorted by creation date (newest first)
fetchAndCacheCustomers
Fetches customers from Firebase and updates caches.
export const fetchAndCacheCustomers = async (): Promise<Customer[]>
addCustomer
Creates a new customer with duplicate detection.
export const addCustomer = async (
customerData: Omit<Customer, 'id' | 'createdAt'>
): Promise<Customer>
Phone number (will be trimmed)
Email address (will be lowercased and trimmed)
Customer category ID (defaults to “Nuevo” category if not provided)
Created customer with:
- Generated ID (format:
CUST-{timestamp}-{random})
- Creation timestamp
- Default category if not specified
Duplicate Detection:
- Checks for existing customers with same phone OR email
- Throws error if duplicate found: “Ya existe un cliente con ese teléfono o email.”
import { addCustomer } from './services/customerService';
try {
const customer = await addCustomer({
name: "Laura Fernández",
phone: "+5491178901234",
email: "[email protected]",
address: "Av. Santa Fe 1234, Buenos Aires"
});
console.log('Customer created:', customer.id);
} catch (error) {
console.error('Creation failed:', error.message);
}
updateCustomer
Updates an existing customer with duplicate detection.
export const updateCustomer = async (updatedCustomer: Customer): Promise<Customer>
Complete customer object with all fields
Duplicate Detection:
- Checks other customers (excluding current one) for phone/email conflicts
- Throws error if duplicate found
import { updateCustomer } from './services/customerService';
const updated = await updateCustomer({
id: "CUST-1709876543210-abc67",
name: "Laura M. Fernández",
phone: "+5491178901234",
email: "[email protected]",
address: "Nueva dirección",
categoryId: "CUSTCAT-vip-123",
createdAt: "2024-03-08T10:15:43.210Z"
});
deleteCustomer
Deletes a customer by ID.
export const deleteCustomer = async (customerId: string): Promise<void>
The customer ID to delete
importCustomers
Bulk imports customers with validation and category matching.
export const importCustomers = async (
customersToImport: any[]
): Promise<{ added: number; updated: number; errors: number }>
Array of customer objects with fields:
name (required)
phone (required)
email (required)
address (optional)
categoryName (optional, matched to existing categories)
Number of new customers created
Number of existing customers updated
Number of customers that failed validation
Validation Rules:
- Name, phone, and email are required
- Phone must have at least 10 digits (non-digit characters ignored)
- Email must match pattern:
[email]@[domain].[tld]
- Category name is matched case-insensitively to existing categories
Matching Logic:
- Customers matched by phone OR email
- Existing customers are updated
- New customers are created
import { importCustomers } from './services/customerService';
const customers = [
{
name: "Cliente 1",
phone: "+5491123456789",
email: "[email protected]",
address: "Dirección 1",
categoryName: "VIP"
},
{
name: "Cliente 2",
phone: "11-2345-6789",
email: "[email protected]",
categoryName: "Regular"
}
];
const result = await importCustomers(customers);
console.log(`Added: ${result.added}, Updated: ${result.updated}, Errors: ${result.errors}`);
Customer Category Management
getCustomerCategoriesFromCache
Retrieves customer categories from cache.
export const getCustomerCategoriesFromCache = (): CustomerCategory[]
Array of customer categories sorted alphabetically
fetchAndCacheCustomerCategories
Fetches categories from Firebase.
export const fetchAndCacheCustomerCategories = async (): Promise<CustomerCategory[]>
addCustomerCategory
Creates a new customer category.
export const addCustomerCategory = async (
categoryData: Omit<CustomerCategory, 'id'>
): Promise<CustomerCategory>
Hex color code (e.g., “#4CAF50”)
Created category with generated ID
import { addCustomerCategory } from './services/customerCategoryService';
const category = await addCustomerCategory({
name: "Premium",
color: "#9C27B0"
});
updateCustomerCategory
Updates an existing customer category.
export const updateCustomerCategory = async (
updatedCategory: CustomerCategory
): Promise<CustomerCategory>
deleteCustomerCategory
Deletes a customer category with automatic customer reassignment.
export const deleteCustomerCategory = async (categoryId: string): Promise<void>
The category ID to delete
Protected Categories:
- Cannot delete the “Nuevo” (New) category
- Throws error: “La categoría ‘Nuevo’ no se puede eliminar.”
Automatic Reassignment:
- All customers in deleted category are automatically reassigned to “Nuevo” category
- Uses Firebase batch write for atomicity
import { deleteCustomerCategory } from './services/customerCategoryService';
try {
await deleteCustomerCategory("CUSTCAT-old-category");
console.log('Category deleted, customers reassigned');
} catch (error) {
console.error('Cannot delete:', error.message);
}
getDefaultNewCustomerCategory
Gets the default “Nuevo” category.
export const getDefaultNewCustomerCategory = (): CustomerCategory | undefined
category
CustomerCategory | undefined
The “Nuevo” category or undefined if not found
reassignCustomersFromCategory
Reassigns all customers from one category to the default category.
export const reassignCustomersFromCategory = async (deletedCategoryId: string): Promise<void>
Category ID to reassign customers from
This function is automatically called by deleteCustomerCategory. You typically don’t need to call it directly.
TypeScript Types
Customer Interface
interface Customer {
id: string;
name: string;
phone?: string;
email?: string;
address?: string;
categoryId: string;
createdAt: string; // ISO timestamp
}
CustomerCategory Interface
interface CustomerCategory {
id: string;
name: string;
color: string; // Hex color code
}
Default Categories
The system initializes with three default customer categories:
| Name | Color | Purpose |
|---|
| Nuevo | #4CAF50 (Green) | Default for new customers |
| Regular | #2196F3 (Blue) | Repeat customers |
| VIP | #FFC107 (Amber) | Premium customers |
The “Nuevo” category is protected and cannot be deleted. It serves as the fallback category for all customer operations.
Complete Example
Customer Lifecycle Management
import {
addCustomer,
updateCustomer,
getCustomersFromCache,
addCustomerCategory,
getCustomerCategoriesFromCache
} from './services/customerService';
import { getDefaultNewCustomerCategory } from './services/customerCategoryService';
// 1. Create new customer with validation
try {
const customer = await addCustomer({
name: "Roberto Sánchez",
phone: "+5491189012345",
email: "[email protected]",
address: "Calle Falsa 123"
});
console.log('Customer created with default category:', customer.categoryId);
// 2. After a few successful orders, upgrade to Regular
const regularCategory = getCustomerCategoriesFromCache()
.find(c => c.name === 'Regular');
if (regularCategory) {
const updated = await updateCustomer({
...customer,
categoryId: regularCategory.id
});
console.log('Upgraded to Regular customer');
}
// 3. Create custom VIP category for high-value customers
const vipCategory = await addCustomerCategory({
name: "Gold VIP",
color: "#FFD700"
});
// 4. Promote to Gold VIP
const vipCustomer = await updateCustomer({
...updated,
categoryId: vipCategory.id
});
console.log('Customer is now Gold VIP!');
} catch (error) {
if (error.message.includes('Ya existe un cliente')) {
console.log('Customer already exists in system');
} else {
console.error('Error:', error.message);
}
}