Skip to main content

Overview

StockPro uses Cloud Firestore as its primary database for storing products, sales, users, and other business data. This page documents the Firestore operations and collection structure used throughout the application.

Core Firestore Imports

import { db } from "./firebase.js";
import { 
  getDocs, 
  collection, 
  query, 
  where,
  addDoc 
} from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

Firestore Operations

collection

Creates a reference to a Firestore collection. Source: public/js/auth.js:3, public/js/agregar_empleado.js:3
import { collection } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

const usuariosRef = collection(db, "usuarios");
const productosRef = collection(db, "productos");
const ventasRef = collection(db, "ventas");
db
Firestore
required
Firestore database instance from firebase.js
collectionPath
string
required
Path to the collection (e.g., “usuarios”, “productos”, “ventas”)
CollectionReference
CollectionReference
Reference to the specified collection that can be used for queries and operations

getDocs

Retrieves all documents from a collection or query. Source: public/js/auth.js:3
import { getDocs, collection } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

const querySnapshot = await getDocs(collection(db, "productos"));

querySnapshot.forEach((doc) => {
    console.log(doc.id, " => ", doc.data());
});
query
Query | CollectionReference
required
Collection reference or query to retrieve documents from
QuerySnapshot
QuerySnapshot
Contains all the documents returned by the query
QuerySnapshot.forEach
function
Iterates over each document in the snapshot
doc.id
string
Unique document ID
doc.data()
object
Document data as a JavaScript object

query

Creates a query against a collection with filters and constraints. Source: public/js/auth.js:3
import { query, collection, where } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

const q = query(
    collection(db, "productos"),
    where("categoria", "==", "electrónica"),
    where("precio", "<", 1000)
);

const querySnapshot = await getDocs(q);
collection
CollectionReference
required
Collection to query
...constraints
QueryConstraint[]
Query constraints like where, orderBy, limit
Query
Query
Query object that can be passed to getDocs()

where

Creates a filter constraint for queries. Source: public/js/auth.js:3
import { where } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

// Equal to
where("estado", "==", "activo")

// Less than
where("precio", "<", 100)

// Greater than
where("stock", ">", 0)

// Array contains
where("categorias", "array-contains", "herramientas")
fieldPath
string
required
Field name to filter on
opStr
WhereFilterOp
required
Comparison operator: ==, !=, <, <=, >, >=, array-contains, in, array-contains-any
value
any
required
Value to compare against
QueryConstraint
QueryConstraint
Filter constraint to be used in a query

addDoc

Adds a new document to a collection with an auto-generated ID. Source: public/js/agregar_empleado.js:39
import { addDoc, collection } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

const usuario = {
    uid: user.uid,
    name: name,
    email: email,
    tipo: tipo
};

await addDoc(collection(db, "usuarios"), usuario);
collection
CollectionReference
required
Collection reference to add the document to
data
object
required
Document data as a JavaScript object
DocumentReference
DocumentReference
Reference to the newly created document with auto-generated ID

Collection Structure

usuarios Collection

Stores user account information and roles. Used in: public/js/agregar_empleado.js:39
const usuario = {
    uid: "firebase-auth-uid",
    name: "Juan Pérez",
    email: "[email protected]",
    tipo: "empleado" // or "admin"
};

await addDoc(collection(db, "usuarios"), usuario);

Document Schema

uid
string
required
Firebase Authentication user ID
name
string
required
User’s full name
email
string
required
User’s email address
tipo
string
required
User role: “empleado” or “admin”

productos Collection

Stores product inventory information. Referenced in: public/js/nuevo-producto.js, public/js/productos.js
const producto = {
    nombre: "Filtro de Aceite",
    sku: "FLT-001",
    costo: 50.00,
    venta: 75.00,
    margen: "33.3%",
    stock: 25,
    categoria: "Filtros",
    createdAt: new Date()
};

await addDoc(collection(db, "productos"), producto);

Document Schema

nombre
string
required
Product name
sku
string
required
Stock Keeping Unit - unique product identifier
costo
number
required
Product cost price
venta
number
required
Product sale price
margen
string
Profit margin percentage (calculated: (venta - costo) / venta * 100)
stock
number
Available inventory quantity
categoria
string
Product category
createdAt
Timestamp
Document creation timestamp

ventas Collection

Stores sales transaction records. Referenced in: public/js/nueva-venta.js, public/js/ventas.js
const venta = {
    items: [
        {
            id: "producto-id",
            nombre: "Filtro de Aceite",
            precio: 75.00,
            qty: 2
        }
    ],
    subtotal: 150.00,
    iva: 24.00,
    total: 174.00,
    vendedor: "usuario-uid",
    fecha: new Date(),
    metodo_pago: "efectivo"
};

await addDoc(collection(db, "ventas"), venta);

Document Schema

items
array
required
Array of products sold in this transaction
items[].id
string
Product document ID
items[].nombre
string
Product name at time of sale
items[].precio
number
Product price at time of sale
items[].qty
number
Quantity sold
subtotal
number
required
Sale subtotal before tax
iva
number
required
Tax amount (16% in this implementation)
total
number
required
Total sale amount including tax
vendedor
string
User ID of the salesperson
fecha
Timestamp
required
Sale timestamp
metodo_pago
string
Payment method: “efectivo”, “tarjeta”, “transferencia”

Common Query Patterns

Fetching All Documents

import { getDocs, collection } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";
import { db } from "./firebase.js";

const querySnapshot = await getDocs(collection(db, "productos"));
const productos = [];

querySnapshot.forEach((doc) => {
    productos.push({
        id: doc.id,
        ...doc.data()
    });
});

console.log(productos);

Filtered Query

import { query, where, getDocs, collection } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

const q = query(
    collection(db, "productos"),
    where("stock", ">", 0)
);

const querySnapshot = await getDocs(q);
const productosDisponibles = [];

querySnapshot.forEach((doc) => {
    productosDisponibles.push({
        id: doc.id,
        ...doc.data()
    });
});

Query by User

import { query, where, getDocs, collection } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

const q = query(
    collection(db, "ventas"),
    where("vendedor", "==", usuario.uid)
);

const querySnapshot = await getDocs(q);
const misVentas = [];

querySnapshot.forEach((doc) => {
    misVentas.push({
        id: doc.id,
        ...doc.data()
    });
});

Adding a New Document

import { addDoc, collection } from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";
import { db } from "./firebase.js";

try {
    const docRef = await addDoc(collection(db, "productos"), {
        nombre: "Aceite 10W-40",
        sku: "ACE-001",
        costo: 80.00,
        venta: 120.00,
        stock: 50,
        createdAt: new Date()
    });
    
    console.log("Producto agregado con ID:", docRef.id);
} catch (error) {
    console.error("Error al agregar producto:", error);
}

Complete Employee Registration Example

This example shows the full flow of creating a user account and storing additional data:
public/js/agregar_empleado.js
import { auth, db } from "./js/firebase.js";
import { 
    createUserWithEmailAndPassword, 
    fetchSignInMethodsForEmail 
} from "https://www.gstatic.com/firebasejs/10.12.2/firebase-auth.js";
import { 
    addDoc, 
    collection 
} from "https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore.js";

document.getElementById("agregar_empleado_form").addEventListener("submit", async (e) => {
    e.preventDefault();
    const name = document.getElementById("name").value;
    const email = document.getElementById("email").value;
    const password = document.getElementById("password").value;
    const tipo = document.getElementById("tipo").value;

    try {
        // Check if email already exists
        const signInMethods = await fetchSignInMethodsForEmail(auth, email);
        
        if (signInMethods && signInMethods.length > 0) {
            console.log(`El correo ${email} ya registrado.`);
            return;
        }

        // Create authentication account
        const credenciales = await createUserWithEmailAndPassword(auth, email, password);
        const user = credenciales.user;

        // Store additional user data in Firestore
        const usuario = {
            uid: user.uid,
            name: name,
            email: email,
            tipo: tipo
        };

        await addDoc(collection(db, "usuarios"), usuario);

        alert(`Registrado como: Usuario ${name}, Tipo: ${tipo}`);
    } catch (error) {
        console.error("Error al agregar usuario:", error);
        alert("Hubo un error al agregar el usuario.");
    }
});

Error Handling

Always wrap Firestore operations in try-catch blocks:
try {
    const querySnapshot = await getDocs(collection(db, "productos"));
    // Process documents
} catch (error) {
    console.error("Error al obtener productos:", error);
    // Display user-friendly error message
}

Build docs developers (and LLMs) love