Workflow Overview
The automation workflow follows a linear pipeline from receiving a purchase order ID to creating completed support documents in Siigo Nube. The entire process takes approximately 30-60 seconds depending on the number of line items.Complete Execution Flow
setNgrok()/scrapping requestsapp.listen(config.PORT, async () => {
const listener = await ngrok.forward({
addr: 3000,
authtoken: config.NGROK_AUTHTOKEN,
});
await setNgrok(listener.url());
});
const compra = await getCompras(body.compra);
// Returns: { com_codigo, comp_asociado, com_micro_ruta }
const compraItems = await getCompraItems(body.compra);
// Returns: [{ citem_material, citem_cantidad, citem_valor_unitario }]
const citem_material = compraItems.map((row) => row.citem_material);
const materiales = await getMateriales(citem_material);
// Returns: [{ mat_id, mat_codigo, mat_nom, emp_id_fk }]
https://corprecam.codesolutions.com.co/administrativo/get_compra.phphttps://corprecam.codesolutions.com.co/administrativo/get_compra_items.phphttps://corprecam.codesolutions.com.co/administrativo/get_materiales.phphttps://corprecam.codesolutions.com.co/administrativo/get_microruta.phpconst productos = compraItems.map((item): Products => {
const material = materiales.find(
(material) => material.mat_id === item.citem_material
);
return {
codigo: material?.mat_codigo || "",
cantidad: item.citem_cantidad,
precio: item.citem_valor_unitario,
empresa: material?.emp_id_fk,
};
});
const [corprecam, reciclemos] = productos.reduce(
(acc, pro) => {
if (pro.empresa === 1) {
acc[0].push(pro); // Corprecam
} else {
acc[1].push(pro); // Reciclemos
}
return acc;
},
[[], []]
);
return {
proveedor_id: compra.comp_asociado,
micro_id: String(micros.mic_nom),
corprecam: corprecam, // Products for company 1
reciclemos: reciclemos, // Products for company 2
};
if (documentoSoporte.corprecam.length > 0) {
await playwright_corprecam_reciclemos(
documentoSoporte.corprecam,
"25470", // Document type code
" BODEGA DE RIOHACHA ", // Warehouse
" CAJA RIOHACHA ", // Account
documentoSoporte.proveedor_id,
config.USER_SIIGO_CORPRECAM,
config.PASSWORD_SIIGO_CORPRECAM,
"900142913" // Corprecam NIT
);
}
if (documentoSoporte.reciclemos.length > 0) {
await playwright_corprecam_reciclemos(
documentoSoporte.reciclemos,
"25470",
" BODEGA DE RIOHACHA ",
" Efectivo ", // Different account
documentoSoporte.proveedor_id,
config.USER_SIIGO_CORPRECAM,
config.PASSWORD_SIIGO_CORPRECAM,
"901328575" // Reciclemos NIT
);
}
Browser Launch
utils/functions.ts:3-10Login to Siigo
Function:login() in utils/functions.ts:12-89Detailed authentication flow:- Navigate to
https://siigonube.siigo.com/#/login - Fill credentials:
- Select company by NIT:
- Click “Crear” button
- Select “Documento soporte” option
- Select document type (Corprecam only: “25470”)
- Search and select supplier by NIT:
- Read and fill auto-generated consecutive number
Product Entry Loop
For each product in the array (transformDs.ts:92-106):Step 6.1: Prepare new rowutils/functions.ts:91-126Step 6.3: Select warehouse (first product only, Corprecam only)utils/functions.ts:128-151Step 6.4: Fill quantity and priceutils/functions.ts:194-246):- Wait for quantity input to be visible
- Fill quantity value
- Fill unit price value
- Click “Agregar otro ítem” button
- Wait for input to clear (confirms row was saved)
- Wait 1 second for DOM stabilization
Payment Account Selection
Function:seleccionarPago() in utils/functions.ts:248-269After all products are added:- Click accounting account dropdown
- Wait for suggestions table
- Select row containing the account name
- Close browser page
Retry and Error Handling
Every Playwright interaction is wrapped withretryUntilSuccess():
- Attempts action up to 5 times
- Waits 1 second between attempts
- Logs warnings for each failure
- Throws error only after all retries exhausted
utils/retryUntilSucces.ts
Timing Characteristics
| Phase | Duration | Notes |
|---|---|---|
| Request reception | Less than 10ms | Express overhead |
| Data gathering | 200-500ms | 4 parallel HTTP calls |
| Transformation | Less than 50ms | Pure computation |
| Browser launch | 2-3s | Firefox initialization |
| Login | 10-15s | Multiple page loads |
| Per product | 3-5s | Autocomplete + waits |
| Payment selection | 2-3s | Final dropdown |
| Total (5 products) | 30-40s | Scales linearly with item count |
Failure Scenarios
API Failures
If anygetCompras(), getCompraItems(), etc. fails:
- Unhandled promise rejection
- HTTP 500 returned to client
- No retry logic at API level
Playwright Failures
If automation fails after 5 retries:- Browser may be left open in error state
- HTTP 500 returned to client
- Partial data may exist in Siigo (previous products saved)
Network Timeouts
Siigo page loads have 60-second timeouts:Parallel vs Sequential Execution
Parallel:- Data gathering (Steps 3.1-3.4)
- Company execution (Corprecam and Reciclemos run sequentially due to
await)
- Product entry loop (must wait for each product to be saved)
- Login steps (depend on previous page navigation)
- Account selection (final step after all products)
State Management
The system is stateless:- No database or persistent storage
- Each request is independent
- No session tracking between requests
- Browser instances are created and destroyed per company
server.ts → main.ts → transformDs.ts → functions.ts.