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");
Firestore database instance from firebase.js
Path to the collection (e.g., “usuarios”, “productos”, “ventas”)
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
Contains all the documents returned by the query
Iterates over each document in the snapshot
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
Query constraints like where, orderBy, limit
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")
Comparison operator: ==, !=, <, <=, >, >=, array-contains, in, array-contains-any
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
Document data as a JavaScript object
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
Firebase Authentication user ID
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
Stock Keeping Unit - unique product identifier
Profit margin percentage (calculated: (venta - costo) / venta * 100)
Available inventory quantity
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
Array of products sold in this transaction
Product name at time of sale
Product price at time of sale
Tax amount (16% in this implementation)
Total sale amount including tax
User ID of the salesperson
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
}