Add complete Tryton RPC client implementation with examples and tests

This commit is contained in:
2025-09-26 14:04:07 -05:00
parent 6543e80525
commit 0771466433
13 changed files with 3333 additions and 0 deletions

200
examples/advanced.js Normal file
View File

@@ -0,0 +1,200 @@
/**
* Advanced usage examples for Tryton RPC Client
*/
const { TrytonClient, Fault, ProtocolError } = require("../src");
async function advancedExamples() {
console.log("🔬 Advanced Tryton RPC Client Examples");
console.log("=====================================\n");
const client = new TrytonClient({
hostname: "localhost",
database: "tryton",
username: "admin",
password: "admin",
options: {
verbose: false,
cache: true,
keepMax: 6,
timeout: 45000,
},
});
try {
await client.connect();
console.log("✅ Connected to Tryton server\n");
// Example 1: Batch operations
console.log("📦 Example 1: Batch Operations");
console.log("------------------------------");
const batchData = [
{ name: "Company A", code: "COMP_A" },
{ name: "Company B", code: "COMP_B" },
{ name: "Company C", code: "COMP_C" },
];
const createdIds = await client.create("party.party", batchData);
console.log("Created parties:", createdIds);
// Read them back
const createdParties = await client.read("party.party", createdIds, [
"id",
"name",
"code",
]);
console.log("Created party details:", createdParties);
console.log();
// Example 2: Complex search with domain
console.log("🔍 Example 2: Complex Search");
console.log("---------------------------");
const complexDomain = [
"OR",
[["name", "like", "Company%"]],
[["code", "like", "COMP_%"]],
];
const foundIds = await client.search("party.party", complexDomain);
console.log("Found IDs with complex domain:", foundIds);
const foundParties = await client.searchRead(
"party.party",
complexDomain,
["id", "name", "code"],
0, // offset
10 // limit
);
console.log("Found parties:", foundParties);
console.log();
// Example 3: Update operations
console.log("✏️ Example 3: Update Operations");
console.log("------------------------------");
if (createdIds.length > 0) {
await client.write("party.party", [createdIds[0]], {
name: "Updated Company Name",
});
console.log(`Updated party ${createdIds[0]}`);
// Verify update
const updated = await client.read(
"party.party",
[createdIds[0]],
["id", "name", "code"]
);
console.log("Updated party:", updated[0]);
}
console.log();
// Example 4: Parallel operations
console.log("⚡ Example 4: Parallel Operations");
console.log("--------------------------------");
const parallelCalls = [
{ method: "model.party.party.search_count", args: [[]] },
{ method: "model.company.company.search_count", args: [[]] },
{ method: "common.version", args: [] },
];
const parallelResults = await client.callParallel(parallelCalls);
console.log("Parallel results:");
console.log("- Total parties:", parallelResults[0]);
console.log("- Total companies:", parallelResults[1]);
console.log("- Server version:", parallelResults[2]);
console.log();
// Example 5: Working with dates
console.log("📅 Example 5: Working with Dates");
console.log("-------------------------------");
const today = new Date();
const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
console.log("Today:", today.toISOString());
console.log("Tomorrow:", tomorrow.toISOString());
// Note: Date handling depends on your specific Tryton models
// This is just to show how dates are serialized
console.log();
// Example 6: Error handling patterns
console.log("⚠️ Example 6: Error Handling");
console.log("---------------------------");
try {
await client.call("nonexistent.model.method", []);
} catch (error) {
if (error instanceof Fault) {
console.log("✅ Caught RPC Fault:", error.faultCode);
} else if (error instanceof ProtocolError) {
console.log("✅ Caught Protocol Error:", error.errcode);
} else {
console.log("✅ Caught Generic Error:", error.message);
}
}
try {
await client.read("party.party", [999999], ["name"]);
} catch (error) {
console.log(
"✅ Caught read error (likely record not found):",
error.message
);
}
console.log();
// Example 7: Cache usage
console.log("💾 Example 7: Cache Usage");
console.log("------------------------");
// First call - will hit server
console.time("First call");
const result1 = await client.read("party.party", [1], ["name"]);
console.timeEnd("First call");
// Second call - should be faster due to cache
console.time("Second call (cached)");
const result2 = await client.read("party.party", [1], ["name"]);
console.timeEnd("Second call (cached)");
console.log(
"Results are equal:",
JSON.stringify(result1) === JSON.stringify(result2)
);
// Clear cache
client.clearCache();
console.log("Cache cleared");
console.log();
// Cleanup: Delete created test records
console.log("🧹 Cleanup: Deleting test records");
console.log("---------------------------------");
if (createdIds.length > 0) {
try {
await client.delete("party.party", createdIds);
console.log("✅ Deleted test records:", createdIds);
} catch (error) {
console.log("⚠️ Could not delete test records:", error.message);
}
}
} catch (error) {
console.error("❌ Advanced examples failed:", error.message);
console.error(error.stack);
} finally {
client.close();
console.log("\n👋 Advanced examples completed");
}
}
if (require.main === module) {
advancedExamples().catch(console.error);
}
module.exports = { advancedExamples };

68
examples/basic.js Normal file
View File

@@ -0,0 +1,68 @@
/**
* Basic usage example of Tryton RPC Client
* Simple example similar to the README
*/
const { TrytonClient } = require("../src/client");
async function basicExample() {
console.log("📖 Basic Tryton RPC Client Example");
console.log("==================================\n");
// Create client
const client = new TrytonClient({
hostname: "https://demo7.6.tryton.org", // Using HTTPS demo server
database: "demo7.6",
username: "admin",
password: "admin",
port: 8000,
language: "en",
});
try {
// Connect
console.log("Connecting...");
await client.connect();
console.log("✅ Connected!\n");
// Read a party
console.log("Reading party with ID 1...");
const party = await client.read(
"party.party",
[1],
["id", "name", "code"]
);
console.log("Party:", party[0]);
console.log();
// Create a new party
console.log("Creating new party...");
const newIds = await client.create("party.party", [
{ name: "Test Party from JS" },
]);
console.log("Created party with ID:", newIds[0]);
console.log();
// Search for parties
console.log("Searching for parties...");
const searchResults = await client.searchRead(
"party.party",
[["name", "like", "Test%"]],
["id", "name"],
0, // offset
5 // limit
);
console.log("Found parties:", searchResults);
} catch (error) {
console.error("❌ Error:", error.message);
} finally {
client.close();
console.log("\n👋 Connection closed");
}
}
if (require.main === module) {
basicExample().catch(console.error);
}
module.exports = { basicExample };

126
examples/test-parties.js Normal file
View File

@@ -0,0 +1,126 @@
/**
* Test para obtener terceros (parties) de Tryton
* Muestra el nombre de cada tercero y el total de terceros
*/
const { TrytonClient } = require("../src/client");
async function testParties() {
console.log("🏢 Test de Terceros (Parties) en Tryton");
console.log("=======================================\n");
// Configuración del servidor Tryton
// Modifica estos valores según tu servidor
//
// Ejemplos de configuración:
//
// Para servidor local:
// hostname: "localhost" o "127.0.0.1"
//
// Para servidor remoto HTTP:
// hostname: "mi-servidor.com"
//
// Para servidor remoto HTTPS:
// hostname: "https://mi-servidor.com"
//
// Para servidor demo:
// hostname: "https://demo7.6.tryton.org", database: "demo7.6"
const config = {
hostname: "https://naliia.onecluster.com.co", // Sin barra final
database: "tryton", // Cambia por el nombre de tu base de datos
username: "admin", // Tu usuario de Tryton
password: "admin", // Tu contraseña
port: 8000, // Puerto del servidor (8000 para HTTP, 8443 para HTTPS)
language: "es", // Idioma (es, en, fr, etc.)
options: {
verbose: true, // Activar para ver qué está pasando
},
};
// Crear cliente
const client = new TrytonClient(config);
try {
console.log("📡 Conectando al servidor Tryton...");
await client.connect();
console.log("✅ Conexión exitosa!\n");
// 1. Obtener el total de terceros
console.log("🔢 Obteniendo cantidad total de terceros...");
const totalParties = await client.searchCount("party.party", []);
console.log(`📊 Total de terceros en el sistema: ${totalParties}\n`);
// 2. Obtener todos los terceros con información básica
console.log("👥 Obteniendo lista de todos los terceros...");
const parties = await client.searchRead(
"party.party",
[], // Sin filtros, obtener todos
["id", "name", "code"], // Campos que queremos
0, // offset
null, // sin límite para obtener todos
null, // sin orden específico
{} // contexto vacío
);
console.log(
`\n📋 Lista completa de terceros (${parties.length} encontrados):`
);
console.log("=" + "=".repeat(60));
// Mostrar cada tercero
parties.forEach((party, index) => {
const number = (index + 1).toString().padStart(3, " ");
const id = party.id.toString().padStart(4, " ");
const code = party.code ? `[${party.code}]` : "[Sin código]";
const name = party.name || "Sin nombre";
console.log(`${number}. ID:${id} ${code.padEnd(12)} ${name}`);
});
console.log("=" + "=".repeat(60));
console.log(`\n✨ Resumen:`);
console.log(` • Total de terceros: ${totalParties}`);
console.log(` • Terceros mostrados: ${parties.length}`);
console.log(
` • Terceros con nombre: ${
parties.filter((p) => p.name && p.name.trim()).length
}`
);
console.log(
` • Terceros con código: ${
parties.filter((p) => p.code && p.code.trim()).length
}`
);
// Mostrar algunos terceros destacados si los hay
const partiesWithNames = parties.filter(
(p) => p.name && p.name.trim().length > 0
);
if (partiesWithNames.length > 0) {
console.log(`\n🌟 Algunos terceros destacados:`);
partiesWithNames.slice(0, 5).forEach((party) => {
console.log(`${party.name} (ID: ${party.id})`);
});
if (partiesWithNames.length > 5) {
console.log(` • ... y ${partiesWithNames.length - 5} más`);
}
}
} catch (error) {
console.error("\n❌ Error durante la ejecución:", error.message);
if (error.stack) {
console.error("\n📍 Stack trace:");
console.error(error.stack);
}
} finally {
console.log("\n🔌 Cerrando conexión...");
client.close();
console.log("👋 ¡Adiós!");
}
}
// Ejecutar si se llama directamente
if (require.main === module) {
testParties().catch(console.error);
}
module.exports = { testParties };

154
examples/test.js Normal file
View File

@@ -0,0 +1,154 @@
/**
* Test script for Tryton RPC Client
* Equivalent to the Python test_client.py
*/
const { TrytonClient } = require("../src/client");
async function main() {
console.log("🚀 Testing Tryton RPC Client for JavaScript");
console.log("============================================\n");
// Create client instance (equivalent to Python version)
const client = new TrytonClient({
hostname: "https://demo7.6.tryton.org", // Explicitly use HTTPS
database: "demo7.6",
username: "admin",
password: "admin",
port: 8000, // Keep original port but force HTTPS
language: "en",
options: {
verbose: true, // Enable logging to see requests/responses
cache: true, // Enable caching
keepMax: 4, // Maximum pooled connections
},
});
try {
console.log("📡 Connecting to Tryton server...");
await client.connect();
console.log("✅ Connected successfully!\n");
console.log("📋 Client configuration:");
console.log(JSON.stringify(client.getConfig(), null, 2));
console.log();
// Test 1: Read party record (equivalent to Python test)
console.log("🔍 Test 1: Reading party record...");
const readResult = await client.call("model.party.party.read", [
[1],
["id", "name", "code"],
{},
]);
console.log("📄 Read result:", JSON.stringify(readResult, null, 2));
console.log();
// Test 2: Create party record (equivalent to Python test)
console.log(" Test 2: Creating new party record...");
const createResult = await client.call("model.party.party.create", [
[{ name: "Desde JavaScript" }],
{},
]);
console.log("🆕 Create result (new IDs):", createResult);
console.log();
// Test 3: Using helper methods
console.log("🛠️ Test 3: Using helper methods...");
// Read using helper method
const parties = await client.read(
"party.party",
[1],
["id", "name", "code"]
);
console.log("👥 Parties (helper method):", parties);
// Search for parties
const partyIds = await client.search(
"party.party",
[["name", "like", "%"]],
0,
5
);
console.log("🔎 Found party IDs:", partyIds);
// Search and read in one call
const partyRecords = await client.searchRead(
"party.party",
[["id", "in", partyIds.slice(0, 3)]],
["id", "name", "code"]
);
console.log("📋 Party records:", partyRecords);
// Count parties
const partyCount = await client.searchCount("party.party", []);
console.log("📊 Total parties count:", partyCount);
console.log();
// Test 4: Server information
console.log(" Test 4: Server information...");
try {
const version = await client.getVersion();
console.log("🏷️ Server version:", version);
} catch (error) {
console.log("⚠️ Could not get version:", error.message);
}
try {
const databases = await client.listDatabases();
console.log("🗄️ Available databases:", databases);
} catch (error) {
console.log("⚠️ Could not list databases:", error.message);
}
console.log();
// Test 5: Error handling
console.log("❌ Test 5: Error handling...");
try {
await client.call("invalid.method.name", []);
} catch (error) {
console.log("✅ Correctly caught error:", error.message);
}
console.log();
// Test 6: Multiple calls
console.log("🔄 Test 6: Multiple calls...");
const multipleCalls = [
{ method: "model.party.party.read", args: [[1], ["name"]] },
{ method: "model.party.party.search_count", args: [[]] },
];
const multiResults = await client.callMultiple(multipleCalls);
console.log("🔢 Multiple call results:", multiResults);
console.log();
console.log("✅ All tests completed successfully!");
} catch (error) {
console.error("❌ Test failed with error:", error.message);
console.error("Stack trace:", error.stack);
} finally {
console.log("\n🔌 Closing connection...");
client.close();
console.log("👋 Goodbye!");
}
}
// Handle unhandled promise rejections
process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled Rejection at:", promise, "reason:", reason);
process.exit(1);
});
// Handle uncaught exceptions
process.on("uncaughtException", (error) => {
console.error("Uncaught Exception:", error);
process.exit(1);
});
// Run the test
if (require.main === module) {
main().catch(console.error);
}
module.exports = { main };