Add Activepieces integration for workflow automation

- Add Activepieces fork with SmoothSchedule custom piece
- Create integrations app with Activepieces service layer
- Add embed token endpoint for iframe integration
- Create Automations page with embedded workflow builder
- Add sidebar visibility fix for embed mode
- Add list inactive customers endpoint to Public API
- Include SmoothSchedule triggers: event created/updated/cancelled
- Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,332 @@
import { Client, createClient, createSecureClient } from "xmlrpc";
import {
AbstractExecuteParams,
ExecuteKwParams,
GetAllCompaniesParams,
GetAllContactsParams,
GetCompanyParams,
GetContactParams,
GetRecordsParams,
CreateRecordParams,
UpdateRecordParams,
OdooConfig,
RenderReportParams,
SaveCompanyParams,
SaveContactParams,
} from "./type";
class Odoo {
config: OdooConfig;
host: string;
port: number;
db: string;
username: string;
password: string;
secure: boolean;
uid: number;
constructor(config: OdooConfig) {
this.config = config;
const { hostname, port, protocol } = new URL(config.url);
this.host = hostname;
this.port = config.port || Number(port);
this.db = config.db;
this.username = config.username;
this.password = config.password;
this.secure = true;
if (protocol !== "https:") {
this.secure = false;
}
this.uid = 0;
}
private getClient(path: string): Client {
const createClientFn = this.secure ? createSecureClient : createClient;
return createClientFn({
host: this.host,
port: this.port,
path,
});
}
private methodCall(client: Client, method: string, params: any[] = []) {
return new Promise((resolve, reject) => {
client.methodCall(method, params, (err, value) => {
if (err) {
console.log(err);
return reject(err);
}
if (value.length == 1)
return resolve(value[0])
else if (value.length > 0)
return resolve(value);
else if (['read', 'search', 'search_read'].includes(params[4]))
return reject("Not found")
else
return resolve(value);
});
});
}
connect(): Promise<number> {
const client = this.getClient("/xmlrpc/2/common");
return new Promise((resolve, reject) => {
client.methodCall(
"authenticate",
[this.db, this.username, this.password, {}],
(error, value) => {
if (error) {
return reject(error);
}
if (!value) {
return reject(new Error("No UID returned from authentication."));
}
this.uid = value;
return resolve(this.uid);
}
);
});
}
async execute<T = any>({ client, endpoint, params }: AbstractExecuteParams) {
try {
const value = await this.methodCall(client, endpoint, [
this.db,
this.uid,
this.password,
...params,
]);
return Promise.resolve(value as T);
} catch (error) {
return Promise.reject(error);
}
}
async execute_kw<T = any>({
model,
method,
params,
}: ExecuteKwParams): Promise<T> {
const client = this.getClient("/xmlrpc/2/object");
return this.execute<T>({
client,
endpoint: "execute_kw",
params: [model, method, ...params],
});
}
async exec_workflow<T = any>({
model,
method,
params,
}: ExecuteKwParams): Promise<T> {
const client = this.getClient("/xmlrpc/2/object");
return this.execute<T>({
client,
endpoint: "exec_workflow",
params: [model, method, ...params],
});
}
async render_report<T = any>({
report,
params,
}: RenderReportParams): Promise<T> {
const client = this.getClient("/xmlrpc/2/report");
return this.execute<T>({
client,
endpoint: "render_report",
params: [report, ...params],
});
}
async getAllContacts<T = any>({
fields = ['name', 'phone', 'email', 'company_name', 'function'],
isCompany = false
}: GetAllContactsParams): Promise<T> {
return this.execute_kw<T>({
model: "res.partner",
method: "search_read",
params: [
[[["is_company", "=", isCompany]],
fields]
]
})
}
async getAllCompanies<T = any>({
fields = ['name', 'phone', 'email', 'country_id'],
}: GetAllCompaniesParams): Promise<T> {
return this.getAllContacts<T>({
fields: fields,
isCompany: true
})
}
async getContact<T = any>({
name,
fields = ['name', 'phone', 'email', 'company_name', 'function'],
isCompany = false
}: GetContactParams): Promise<T> {
return this.execute_kw<T>({
model: "res.partner",
method: "search_read",
params: [
[[["is_company", "=", isCompany], ["name", "like", name]],
fields]
]
})
}
async getCompany<T = any>({
name,
fields = ['name', 'phone', 'email', 'country_id'],
}: GetCompanyParams): Promise<T> {
return this.getContact<T>({
name: name,
fields: fields,
isCompany: true
})
}
async getRecords<T = any>({model, domain, fields, offset, limit}: GetRecordsParams): Promise<T> {
return this.execute_kw<T>({
model: model,
method: "search_read",
params: [
[domain, fields, offset, limit]
]
})
}
async createRecord<T = any>({
model,
fields,
}: CreateRecordParams): Promise<T> {
return this.execute_kw<T>({
model,
method: 'create',
params: [[fields]],
});
}
async updateRecord<T = any>({
model,
recordId,
fields,
}: UpdateRecordParams): Promise<T> {
return this.execute_kw<T>({
model,
method: 'write',
params: [[[recordId], fields]],
});
}
async saveContact<T = any>({
name,
phone,
email,
company,
title,
company_id,
address,
}: SaveContactParams): Promise<T> {
const contact = {
name: name,
phone: phone,
email: email,
company_name: company,
company_id: company_id || null,
function: title,
};
try {
const record = await this.execute_kw<T>({
model: "res.partner",
method: "search",
params: [
[[["is_company", "=", false], ["name", "=", name]]]
]
})
this.execute_kw<T>({
model: "res.partner",
method: "write",
params: [[record, contact]],
});
return Promise.resolve(record as T)
} catch (err) {
if (err === "Not found") {
return this.execute_kw({
model: "res.partner",
method: "create",
params: [[[contact]]],
});
} else
return Promise.reject("Error")
}
}
async saveCompany<T = any>({
name,
phone,
email,
address,
}: SaveCompanyParams): Promise<T> {
const contact = {
name: name,
phone: phone,
email: email,
is_company: true
};
try {
const record = await this.execute_kw<T>({
model: "res.partner",
method: "search",
params: [
[[["is_company", "=", true], ["name", "=", name]]]
]
})
this.execute_kw<T>({
model: "res.partner",
method: "write",
params: [[record, contact]],
});
return Promise.resolve(record as T)
} catch (err) {
if (err === "Not found") {
return this.execute_kw({
model: "res.partner",
method: "create",
params: [[[contact]]],
});
} else
return Promise.reject("Error")
}
}
}
export default Odoo;

View File

@@ -0,0 +1,96 @@
import { Client } from "xmlrpc";
export type OdooConfig = {
url: string;
port?: number;
db: string;
username: string;
password: string;
secure?: boolean;
};
export type ExecuteKwParams = {
model: string;
method: string;
params: any[];
};
export type AbstractExecuteParams = {
endpoint: string;
client: Client;
params: any[];
};
export type RenderReportParams = {
report: string;
params: any[];
};
export type GetAllContactsParams = {
fields?: any[];
isCompany?: boolean;
};
export type GetAllCompaniesParams = {
fields?: any[];
};
export type GetContactParams = {
name: string;
fields?: any[];
isCompany?: boolean;
};
export type GetCompanyParams = {
name: string;
fields?: any[];
};
export type GetRecordsParams = {
model: string;
domain?: any[];
fields?: any[];
offset?: number;
limit?: number;
};
export type CreateRecordParams = {
model: string;
fields: Record<string, any>;
};
export type UpdateRecordParams = {
model: string;
recordId: number;
fields: Record<string, any>;
};
export type SaveContactParams = {
name: string;
phone: string;
email: string;
company: string;
company_id?: number;
title: string;
address?: {
street?: string;
city?: string;
state?: string;
zip?: string;
country?: string;
},
};
export type SaveCompanyParams = {
name: string;
phone: string;
email: string;
address?: {
street?: string;
city?: string;
state?: string;
zip?: string;
country?: string;
},
};

View File

@@ -0,0 +1,60 @@
{
"Open source all-in-one management software": "Open Source All-in-One Management-Software",
"Odoo URL": "Odoo URL",
"Odoo Database": "Odoo-Datenbank",
"Odoo Username": "Odoo Username",
"Odoo API Key": "Odoo API Key",
"Enter the base URL": "Basis-URL eingeben",
"Enter the database name": "Geben Sie den Datenbanknamen ein",
"Enter the username": "Benutzernamen eingeben",
"Enter the API Key": "API-Schlüssel eingeben",
"Get contacts": "Kontakte erhalten",
"Create contact": "Kontakt erstellen",
"Create company": "Firma erstellen",
"Custom Search and read records": "Benutzerdefinierte Such- und Leseeinträge",
"Custom Create Record": "Eigener Datensatz",
"Custom Update Record": "Eigener Update-Eintrag",
"Custom API Call": "Eigener API-Aufruf",
"Get contacts on Odoo": "Kontakte auf Odoo laden",
"Create/Update contact on Odoo": "Kontakt auf Odoo erstellen/aktualisieren",
"Create/Update company on Odoo": "Firma auf Odoo erstellen/aktualisieren",
"Records can be listed and filtered": "Datensätze können aufgelistet und gefiltert werden",
"Create a new record in the specified model": "Neuen Datensatz im angegebenen Modell erstellen",
"Update an existing record in the specified model": "Aktualisiere einen vorhandenen Eintrag im angegebenen Modell",
"Make a custom XML-RPC API call to Odoo": "Benutzerdefinierter XML-RPC-API-Aufruf an Odoo",
"Type": "Typ",
"Contact Name": "Kontaktname",
"Contact Phone": "Telefonkontakt",
"Contact E-mail": "Kontakt-E-Mail",
"Company Name": "Firmenname",
"Job Title": "Job Titel",
"Company Phone": "Firmentelefon",
"Company E-mail": "Firma E-Mail",
"Model": "Modell",
"Search domains": "Domänen durchsuchen",
"Fields": "Felder",
"Offset": "Versatz",
"Limit": "Limit",
"Fields and Values": "Felder und Werte",
"Record ID": "Datensatz-ID",
"Method": "Methode",
"Select which contact type to get": "Wählen Sie den zu erhaltenden Kontakttyp",
"Would you like to search any specific name?": "Möchten Sie einen bestimmten Namen suchen?",
"Model name. e.g.: res.partner": "Modellname. z.B.: res.partner",
"A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.": "Eine Domain ist eine Liste von Kriterien, jedes Kriterium ist ein Dreifachkriterium (field_name, Operator, Wert). Siehe https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains für Details.",
"Returns the requested fields of the records. When undefined, returns all fields.": "Gibt die angeforderten Felder der Datensätze zurück. Wenn nicht definiert, werden alle Felder zurückgegeben.",
"JSON object of field names and their corresponding values": "JSON-Objekt von Feldnamen und deren entsprechenden Werten",
"ID of the record to update": "ID des zu aktualisierenden Datensatzes",
"The Odoo model to interact with (e.g., res.partner, product.product)": "Das Odoo-Modell, mit dem interagiert werden soll (z.B. res.partner, product.product)",
"The method to call on the model (e.g., search_read, create, write)": "Die Methode, die auf das Modell aufgerufen werden soll (z.B. search_read, create, write)",
"Contact": "Kontakt",
"Company": "Firma",
"Read": "Lesen",
"Search read": "Gelesene Suche",
"Search count": "Suchzähler",
"Search": "Suche",
"Create": "Erstellen",
"Write": "Schreiben",
"Unlink": "Link aufheben",
"Fields get": "Felder erhalten"
}

View File

@@ -0,0 +1,60 @@
{
"Open source all-in-one management software": "Software de gestión todo en uno de código abierto",
"Odoo URL": "Odoo URL",
"Odoo Database": "Base de datos Odoo",
"Odoo Username": "Odoo Username",
"Odoo API Key": "Odoo API Key",
"Enter the base URL": "Introduzca la URL base",
"Enter the database name": "Introduzca el nombre de la base de datos",
"Enter the username": "Introduzca el nombre de usuario",
"Enter the API Key": "Introduzca la clave API",
"Get contacts": "Obtener contactos",
"Create contact": "Crear contacto",
"Create company": "Crear empresa",
"Custom Search and read records": "Búsqueda personalizada y lectura de registros",
"Custom Create Record": "Crear registro personalizado",
"Custom Update Record": "Actualizar registro personalizado",
"Custom API Call": "Llamada API personalizada",
"Get contacts on Odoo": "Obtener contactos en Odoo",
"Create/Update contact on Odoo": "Crear/Actualizar contacto en Odoo",
"Create/Update company on Odoo": "Crear/Actualizar empresa en Odoo",
"Records can be listed and filtered": "Los registros pueden ser listados y filtrados",
"Create a new record in the specified model": "Crear un nuevo registro en el modelo especificado",
"Update an existing record in the specified model": "Actualizar un registro existente en el modelo especificado",
"Make a custom XML-RPC API call to Odoo": "Hacer una llamada personalizada a la API XML-RPC a Odoo",
"Type": "Tipo",
"Contact Name": "Nombre de contacto",
"Contact Phone": "Teléfono de contacto",
"Contact E-mail": "E-mail de contacto",
"Company Name": "Nombre De La Empresa",
"Job Title": "Trabajo",
"Company Phone": "Teléfono de empresa",
"Company E-mail": "E-mail de la empresa",
"Model": "Modelo",
"Search domains": "Buscar dominios",
"Fields": "Campos",
"Offset": "Desplazamiento",
"Limit": "Límite",
"Fields and Values": "Campos y valores",
"Record ID": "ID de registro",
"Method": "Método",
"Select which contact type to get": "Seleccione qué tipo de contacto desea obtener",
"Would you like to search any specific name?": "¿Te gustaría buscar algún nombre específico?",
"Model name. e.g.: res.partner": "Nombre del modelo, por ejemplo: res.partner",
"A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.": "Un dominio es una lista de criterios, cada criterio es una triple de (field_name, operador, valor). Vea https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains para más detalles.",
"Returns the requested fields of the records. When undefined, returns all fields.": "Devuelve los campos solicitados de los registros. Cuando indefinido, devuelve todos los campos.",
"JSON object of field names and their corresponding values": "Objeto JSON de nombres de campos y sus valores correspondientes",
"ID of the record to update": "ID del registro a actualizar",
"The Odoo model to interact with (e.g., res.partner, product.product)": "El modelo Odoo para interactuar con (p.ej., res.partner, product.product)",
"The method to call on the model (e.g., search_read, create, write)": "El método para llamar al modelo (por ejemplo, search_read, crear, escribir)",
"Contact": "Contacto",
"Company": "Empresa",
"Read": "Leer",
"Search read": "Buscar leídos",
"Search count": "Número de búsquedas",
"Search": "Buscar",
"Create": "Crear",
"Write": "Escribir",
"Unlink": "Desvincular",
"Fields get": "Obtener campos"
}

View File

@@ -0,0 +1,60 @@
{
"Open source all-in-one management software": "Logiciel de gestion tout-en-un open source",
"Odoo URL": "Odoo URL",
"Odoo Database": "Base de données Odoo",
"Odoo Username": "Odoo Username",
"Odoo API Key": "Odoo API Key",
"Enter the base URL": "Entrez l'URL de base",
"Enter the database name": "Entrez le nom de la base de données",
"Enter the username": "Entrez le nom d'utilisateur",
"Enter the API Key": "Entrez la clé API",
"Get contacts": "Obtenir des contacts",
"Create contact": "Créer un contact",
"Create company": "Créer une entreprise",
"Custom Search and read records": "Recherche personnalisée et lecture des enregistrements",
"Custom Create Record": "Créer un enregistrement personnalisé",
"Custom Update Record": "Enregistrement de mise à jour personnalisé",
"Custom API Call": "Appel API personnalisé",
"Get contacts on Odoo": "Trouver des contacts sur Odoo",
"Create/Update contact on Odoo": "Créer/Mettre à jour le contact sur Odoo",
"Create/Update company on Odoo": "Créer/Mettre à jour la société sur Odoo",
"Records can be listed and filtered": "Les enregistrements peuvent être listés et filtrés",
"Create a new record in the specified model": "Créer un nouvel enregistrement dans le modèle spécifié",
"Update an existing record in the specified model": "Mettre à jour un enregistrement existant dans le modèle spécifié",
"Make a custom XML-RPC API call to Odoo": "Faites un appel à l'API XML-RPC personnalisée vers Odoo",
"Type": "Type de texte",
"Contact Name": "Nom du contact",
"Contact Phone": "Téléphone du contact",
"Contact E-mail": "E-mail du contact",
"Company Name": "Nom de lentreprise",
"Job Title": "Titre du poste",
"Company Phone": "Téléphone de la société",
"Company E-mail": "E-mail de la société",
"Model": "Modélisation",
"Search domains": "Rechercher des domaines",
"Fields": "Champs",
"Offset": "Décalage",
"Limit": "Limite",
"Fields and Values": "Champs et valeurs",
"Record ID": "ID de l'enregistrement",
"Method": "Méthode",
"Select which contact type to get": "Sélectionnez le type de contact à obtenir",
"Would you like to search any specific name?": "Voulez-vous rechercher un nom spécifique ?",
"Model name. e.g.: res.partner": "Nom du modèle. Par exemple: res.partner",
"A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.": "Un domaine est une liste de critères, chaque critère étant un triple de (field_name, operator, value). Voir https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains pour plus de détails.",
"Returns the requested fields of the records. When undefined, returns all fields.": "Renvoie les champs demandés des enregistrements. Quand indéfini, retourne tous les champs.",
"JSON object of field names and their corresponding values": "Objet JSON des noms de champs et leurs valeurs correspondantes",
"ID of the record to update": "ID de l'enregistrement à mettre à jour",
"The Odoo model to interact with (e.g., res.partner, product.product)": "Le modèle Odoo avec lequel interagir (par exemple, res.partner, product.product)",
"The method to call on the model (e.g., search_read, create, write)": "La méthode à appeler sur le modèle (par exemple, search_read, create, write)",
"Contact": "Contacter",
"Company": "Entreprise",
"Read": "Lu",
"Search read": "Recherche lue",
"Search count": "Nombre de recherches",
"Search": "Rechercher",
"Create": "Créer",
"Write": "Écrire",
"Unlink": "Délier",
"Fields get": "Champs obtenus"
}

View File

@@ -0,0 +1,60 @@
{
"Open source all-in-one management software": "オープンソースオールインワン管理ソフトウェア",
"Odoo URL": "Odoo URL",
"Odoo Database": "Odoo データベース",
"Odoo Username": "Odoo Username",
"Odoo API Key": "Odoo API Key",
"Enter the base URL": "ベース URL を入力してください",
"Enter the database name": "データベース名を入力してください",
"Enter the username": "ユーザー名を入力してください",
"Enter the API Key": "API キーを入力",
"Get contacts": "連絡先を取得",
"Create contact": "連絡先を作成",
"Create company": "会社を作成",
"Custom Search and read records": "カスタム検索とレコードの読み取り",
"Custom Create Record": "カスタムレコードの作成",
"Custom Update Record": "カスタム更新履歴",
"Custom API Call": "カスタムAPI通話",
"Get contacts on Odoo": "Odoo で連絡先を取得する",
"Create/Update contact on Odoo": "Odoo で連絡先を作成/更新",
"Create/Update company on Odoo": "Odoo で会社を作成/更新",
"Records can be listed and filtered": "レコードはリストとフィルタリングすることができます",
"Create a new record in the specified model": "指定されたモデルに新しいレコードを作成",
"Update an existing record in the specified model": "指定されたモデルの既存のレコードを更新します",
"Make a custom XML-RPC API call to Odoo": "カスタム XML-RPC API を Odoo に呼び出します。",
"Type": "タイプ",
"Contact Name": "連絡先名",
"Contact Phone": "連絡先電話番号",
"Contact E-mail": "連絡先メールアドレス",
"Company Name": "会社名",
"Job Title": "役職名",
"Company Phone": "勤務先電話番号",
"Company E-mail": "会社のメールアドレス",
"Model": "モデル",
"Search domains": "ドメインを検索",
"Fields": "フィールド",
"Offset": "オフセット",
"Limit": "制限",
"Fields and Values": "フィールドと値",
"Record ID": "レコードID",
"Method": "方法",
"Select which contact type to get": "取得するコンタクトの種類を選択してください",
"Would you like to search any specific name?": "特定の名前を検索しますか?",
"Model name. e.g.: res.partner": "モデル名。例えば: res.partner",
"A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.": "ドメインは基準のリストです。各基準は (field_name, operator, value) の 3 倍です。詳細は https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains を参照してください。",
"Returns the requested fields of the records. When undefined, returns all fields.": "レコードの要求されたフィールドを返します。未定義の場合、すべてのフィールドを返します。",
"JSON object of field names and their corresponding values": "フィールド名と対応する値の JSON オブジェクト",
"ID of the record to update": "更新するレコードの ID",
"The Odoo model to interact with (e.g., res.partner, product.product)": "インタラクションする Odoo モデル (例: res.partner, product.product)",
"The method to call on the model (e.g., search_read, create, write)": "モデルを呼び出すメソッド (例: search_read, create, write)",
"Contact": "お問い合わせ",
"Company": "会社名",
"Read": "既読にする",
"Search read": "既読の検索",
"Search count": "検索数",
"Search": "検索",
"Create": "作成",
"Write": "書き込み",
"Unlink": "リンクを解除",
"Fields get": "項目取得"
}

View File

@@ -0,0 +1,60 @@
{
"Open source all-in-one management software": "Open source alles-in-één managementsoftware",
"Odoo URL": "Odoo URL",
"Odoo Database": "Odoo Database",
"Odoo Username": "Odoo Username",
"Odoo API Key": "Odoo API Key",
"Enter the base URL": "Voer de basis-URL in",
"Enter the database name": "Voer de databasenaam in",
"Enter the username": "Voer de gebruikersnaam in",
"Enter the API Key": "Voer de API-sleutel in",
"Get contacts": "Contacten opvragen",
"Create contact": "Contact maken",
"Create company": "Bedrijf aanmaken",
"Custom Search and read records": "Aangepaste zoek- en lees records",
"Custom Create Record": "Aangepast record maken",
"Custom Update Record": "Aangepaste update record",
"Custom API Call": "Custom API Call",
"Get contacts on Odoo": "Contacten krijgen op Odoo",
"Create/Update contact on Odoo": "Contactpersoon maken/bijwerken op Odoo",
"Create/Update company on Odoo": "Maak/Update bedrijf op Odoo",
"Records can be listed and filtered": "Records kunnen worden weergegeven en gefilterd",
"Create a new record in the specified model": "Maak een nieuw record in het opgegeven model",
"Update an existing record in the specified model": "Update een bestaand record in het opgegeven model",
"Make a custom XML-RPC API call to Odoo": "Maak een aangepaste XML-RPC API call naar Odoo",
"Type": "Type",
"Contact Name": "Naam contactpersoon",
"Contact Phone": "Contact telefoon",
"Contact E-mail": "Contact opnemen via e-mail",
"Company Name": "Bedrijfsnaam",
"Job Title": "Job titel",
"Company Phone": "Telefoon bedrijf",
"Company E-mail": "E-mailadres bedrijf",
"Model": "Model",
"Search domains": "Zoek domeinen",
"Fields": "Velden",
"Offset": "Verschuiving",
"Limit": "Limiet",
"Fields and Values": "Velden en waarden",
"Record ID": "Record ID",
"Method": "Methode",
"Select which contact type to get": "Selecteer welk type contact je wilt krijgen",
"Would you like to search any specific name?": "Wil je een specifieke naam zoeken?",
"Model name. e.g.: res.partner": "Model naam. Bijvoorbeeld: res.partner",
"A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.": "Een domein is een lijst met criteria, elk criterium is een driedubbele van (field_name, operator, value). Zie https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains voor details.",
"Returns the requested fields of the records. When undefined, returns all fields.": "Geeft de opgevraagde velden van de records. Indien niet gedefinieerd, retourneert alle velden.",
"JSON object of field names and their corresponding values": "JSON object van veldnamen en hun overeenkomstige waarden",
"ID of the record to update": "ID van het bij te werken record",
"The Odoo model to interact with (e.g., res.partner, product.product)": "Het Odoo-model waarmee interactie kan worden gevoerd (bijv. res.partner, product.product)",
"The method to call on the model (e.g., search_read, create, write)": "De methode om het model aan te roepen (bijv. zoek_read, maken, schrijven)",
"Contact": "Contactpersoon",
"Company": "Bedrijfsnaam",
"Read": "Lezen",
"Search read": "Zoek gelezen",
"Search count": "Aantal zoekopdrachten",
"Search": "Zoeken",
"Create": "Maak",
"Write": "Schrijven",
"Unlink": "Ontkoppelen",
"Fields get": "Velden krijgen"
}

View File

@@ -0,0 +1,60 @@
{
"Open source all-in-one management software": "Software de gerenciamento de código aberto para todos em um",
"Odoo URL": "Odoo URL",
"Odoo Database": "Base de Odoo",
"Odoo Username": "Odoo Username",
"Odoo API Key": "Odoo API Key",
"Enter the base URL": "Digite a URL base",
"Enter the database name": "Digite o nome do banco de dados",
"Enter the username": "Digite o nome de usuário",
"Enter the API Key": "Digite a chave API",
"Get contacts": "Obter os contatos",
"Create contact": "Criar contato",
"Create company": "Criar empresa",
"Custom Search and read records": "Registros de busca e leitura personalizados",
"Custom Create Record": "Criar Registro Personalizado",
"Custom Update Record": "Registro de Atualização Personalizada",
"Custom API Call": "Chamada de API personalizada",
"Get contacts on Odoo": "Obter contatos em Odoo",
"Create/Update contact on Odoo": "Criar/Atualizar contato no Odoo",
"Create/Update company on Odoo": "Criar/Atualizar empresa no Odoo",
"Records can be listed and filtered": "Os registros podem ser listados e filtrados",
"Create a new record in the specified model": "Criar um novo registro no modelo especificado",
"Update an existing record in the specified model": "Atualizar um registro existente no modelo especificado",
"Make a custom XML-RPC API call to Odoo": "Fazer uma chamada XML-RPC API personalizada para Odoo",
"Type": "tipo",
"Contact Name": "Nome do contato",
"Contact Phone": "Telefone para contato",
"Contact E-mail": "E-mail de contato",
"Company Name": "Nome da Empresa",
"Job Title": "Título do Cargo",
"Company Phone": "Telefone da Empresa",
"Company E-mail": "E-mail da empresa",
"Model": "Modelo",
"Search domains": "Domínios de pesquisa",
"Fields": "campos",
"Offset": "Deslocamento",
"Limit": "Limitar",
"Fields and Values": "Campos e Valores",
"Record ID": "ID do Registro",
"Method": "Método",
"Select which contact type to get": "Selecione quais tipos de contato obter",
"Would you like to search any specific name?": "Gostaria de procurar algum nome específico?",
"Model name. e.g.: res.partner": "Nome do modelo. Ex.: res.partner",
"A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.": "Um domínio é uma lista de critérios, cada critério sendo um triplo de (field_name, operator, valor). Consulte https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains para obter detalhes.",
"Returns the requested fields of the records. When undefined, returns all fields.": "Retorna os campos solicitados dos registros. Quando indefinido, retorna todos os campos.",
"JSON object of field names and their corresponding values": "Objeto JSON de nomes de campo e seus valores correspondentes",
"ID of the record to update": "ID do registro a ser atualizado",
"The Odoo model to interact with (e.g., res.partner, product.product)": "O modelo Odoo para interagir (por exemplo, res.partner, product.product)",
"The method to call on the model (e.g., search_read, create, write)": "O método para chamar o modelo (por exemplo, pesquisa_read, criar, gravar)",
"Contact": "contato",
"Company": "Empresas",
"Read": "Lido",
"Search read": "Pesquisar leitura",
"Search count": "Contagem de pesquisa",
"Search": "Pesquisar",
"Create": "Criar",
"Write": "Salvar",
"Unlink": "Desvincular",
"Fields get": "Obtenção de campos"
}

View File

@@ -0,0 +1,61 @@
{
"Odoo": "Odoo",
"Open source all-in-one management software": "Открытый исходный код в одном программном обеспечении",
"Odoo URL": "Odoo URL",
"Odoo Database": "База данных Odoo",
"Odoo Username": "Odoo Username",
"Odoo API Key": "Odoo API Key",
"Enter the base URL": "Введите базовый URL",
"Enter the database name": "Введите имя базы данных",
"Enter the username": "Введите имя пользователя",
"Enter the API Key": "Введите ключ API",
"Get contacts": "Получить контакты",
"Create contact": "Создать контакт",
"Create company": "Создать компанию",
"Custom Search and read records": "Пользовательский поиск и чтение записей",
"Custom Create Record": "Пользовательское создание записи",
"Custom Update Record": "Пользовательская запись обновления",
"Custom API Call": "Пользовательский вызов API",
"Get contacts on Odoo": "Получить контакты на Odoo",
"Create/Update contact on Odoo": "Создать/Обновить контакт на Odoo",
"Create/Update company on Odoo": "Создать/Обновить компанию в Odoo",
"Records can be listed and filtered": "Можно указать и отфильтровать записи",
"Create a new record in the specified model": "Создать новую запись в указанной модели",
"Update an existing record in the specified model": "Обновить существующую запись в указанной модели",
"Make a custom XML-RPC API call to Odoo": "Сделать пользовательский XML-RPC API вызов Odoo",
"Type": "Тип",
"Contact Name": "Имя контакта",
"Contact Phone": "Контактный телефон",
"Contact E-mail": "Контактный E-mail",
"Company Name": "Название компании",
"Job Title": "Заголовок",
"Company Phone": "Телефон компании",
"Company E-mail": "E-mail компании",
"Model": "Модель",
"Search domains": "Домены поиска",
"Fields": "Поля",
"Offset": "Смещение",
"Limit": "Лимит",
"Fields and Values": "Поля и значения",
"Record ID": "ID записи",
"Method": "Метод",
"Select which contact type to get": "Выберите тип контакта для получения",
"Would you like to search any specific name?": "Вы хотите найти какое-либо конкретное имя?",
"Model name. e.g.: res.partner": "Название модели. Например: res.partner",
"A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.": "Домен — это список критериев, каждый из которых имеет тройку (field_name, operator, value). Смотрите подробности https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains .",
"Returns the requested fields of the records. When undefined, returns all fields.": "Возвращает запрашиваемые поля записей. Когда не определено, возвращает все поля.",
"JSON object of field names and their corresponding values": "JSON наименования полей и их соответствующие значения",
"ID of the record to update": "ID записи для обновления",
"The Odoo model to interact with (e.g., res.partner, product.product)": "Модель Odoo для взаимодействия с (например, res.partner, product.product)",
"The method to call on the model (e.g., search_read, create, write)": "Метод вызова модели (например, search_read, create, write)",
"Contact": "Контакт",
"Company": "Компания",
"Read": "Чтение",
"Search read": "Поиск прочитанных",
"Search count": "Счетчик поиска",
"Search": "Search",
"Create": "Создать",
"Write": "Написать",
"Unlink": "Отвязать",
"Fields get": "Поля получены"
}

View File

@@ -0,0 +1,60 @@
{
"Open source all-in-one management software": "Open source all-in-one management software",
"Odoo URL": "Odoo URL",
"Odoo Database": "Odoo Database",
"Odoo Username": "Odoo Username",
"Odoo API Key": "Odoo API Key",
"Enter the base URL": "Enter the base URL",
"Enter the database name": "Enter the database name",
"Enter the username": "Enter the username",
"Enter the API Key": "Enter the API Key",
"Get contacts": "Get contacts",
"Create contact": "Create contact",
"Create company": "Create company",
"Custom Search and read records": "Custom Search and read records",
"Custom Create Record": "Custom Create Record",
"Custom Update Record": "Custom Update Record",
"Custom API Call": "Custom API Call",
"Get contacts on Odoo": "Get contacts on Odoo",
"Create/Update contact on Odoo": "Create/Update contact on Odoo",
"Create/Update company on Odoo": "Create/Update company on Odoo",
"Records can be listed and filtered": "Records can be listed and filtered",
"Create a new record in the specified model": "Create a new record in the specified model",
"Update an existing record in the specified model": "Update an existing record in the specified model",
"Make a custom XML-RPC API call to Odoo": "Make a custom XML-RPC API call to Odoo",
"Type": "Type",
"Contact Name": "Contact Name",
"Contact Phone": "Contact Phone",
"Contact E-mail": "Contact E-mail",
"Company Name": "Company Name",
"Job Title": "Job Title",
"Company Phone": "Company Phone",
"Company E-mail": "Company E-mail",
"Model": "Model",
"Search domains": "Search domains",
"Fields": "Fields",
"Offset": "Offset",
"Limit": "Limit",
"Fields and Values": "Fields and Values",
"Record ID": "Record ID",
"Method": "Method",
"Select which contact type to get": "Select which contact type to get",
"Would you like to search any specific name?": "Would you like to search any specific name?",
"Model name. e.g.: res.partner": "Model name. e.g.: res.partner",
"A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.": "A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.",
"Returns the requested fields of the records. When undefined, returns all fields.": "Returns the requested fields of the records. When undefined, returns all fields.",
"JSON object of field names and their corresponding values": "JSON object of field names and their corresponding values",
"ID of the record to update": "ID of the record to update",
"The Odoo model to interact with (e.g., res.partner, product.product)": "The Odoo model to interact with (e.g., res.partner, product.product)",
"The method to call on the model (e.g., search_read, create, write)": "The method to call on the model (e.g., search_read, create, write)",
"Contact": "Contact",
"Company": "Company",
"Read": "Read",
"Search read": "Search read",
"Search count": "Search count",
"Search": "Search",
"Create": "Create",
"Write": "Write",
"Unlink": "Unlink",
"Fields get": "Fields get"
}

View File

@@ -0,0 +1,61 @@
{
"Odoo": "Odoo",
"Open source all-in-one management software": "Open source all-in-one management software",
"Odoo URL": "Odoo URL",
"Odoo Database": "Odoo Database",
"Odoo Username": "Odoo Username",
"Odoo API Key": "Odoo API Key",
"Enter the base URL": "Enter the base URL",
"Enter the database name": "Enter the database name",
"Enter the username": "Enter the username",
"Enter the API Key": "Enter the API Key",
"Get contacts": "Get contacts",
"Create contact": "Create contact",
"Create company": "Create company",
"Custom Search and read records": "Custom Search and read records",
"Custom Create Record": "Custom Create Record",
"Custom Update Record": "Custom Update Record",
"Custom API Call": "Custom API Call",
"Get contacts on Odoo": "Get contacts on Odoo",
"Create/Update contact on Odoo": "Create/Update contact on Odoo",
"Create/Update company on Odoo": "Create/Update company on Odoo",
"Records can be listed and filtered": "Records can be listed and filtered",
"Create a new record in the specified model": "Create a new record in the specified model",
"Update an existing record in the specified model": "Update an existing record in the specified model",
"Make a custom XML-RPC API call to Odoo": "Make a custom XML-RPC API call to Odoo",
"Type": "Type",
"Contact Name": "Contact Name",
"Contact Phone": "Contact Phone",
"Contact E-mail": "Contact E-mail",
"Company Name": "Tên công ty",
"Job Title": "Job Title",
"Company Phone": "Company Phone",
"Company E-mail": "Company E-mail",
"Model": "Model",
"Search domains": "Search domains",
"Fields": "Fields",
"Offset": "Offset",
"Limit": "Limit",
"Fields and Values": "Fields and Values",
"Record ID": "Record ID",
"Method": "Method",
"Select which contact type to get": "Select which contact type to get",
"Would you like to search any specific name?": "Would you like to search any specific name?",
"Model name. e.g.: res.partner": "Model name. e.g.: res.partner",
"A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.": "A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.",
"Returns the requested fields of the records. When undefined, returns all fields.": "Returns the requested fields of the records. When undefined, returns all fields.",
"JSON object of field names and their corresponding values": "JSON object of field names and their corresponding values",
"ID of the record to update": "ID of the record to update",
"The Odoo model to interact with (e.g., res.partner, product.product)": "The Odoo model to interact with (e.g., res.partner, product.product)",
"The method to call on the model (e.g., search_read, create, write)": "The method to call on the model (e.g., search_read, create, write)",
"Contact": "Contact",
"Company": "Company",
"Read": "Read",
"Search read": "Search read",
"Search count": "Search count",
"Search": "Search",
"Create": "Create",
"Write": "Write",
"Unlink": "Unlink",
"Fields get": "Fields get"
}

View File

@@ -0,0 +1,60 @@
{
"Open source all-in-one management software": "Open source all-in-one management software",
"Odoo URL": "Odoo URL",
"Odoo Database": "Odoo Database",
"Odoo Username": "Odoo Username",
"Odoo API Key": "Odoo API Key",
"Enter the base URL": "Enter the base URL",
"Enter the database name": "Enter the database name",
"Enter the username": "Enter the username",
"Enter the API Key": "Enter the API Key",
"Get contacts": "Get contacts",
"Create contact": "Create contact",
"Create company": "Create company",
"Custom Search and read records": "Custom Search and read records",
"Custom Create Record": "Custom Create Record",
"Custom Update Record": "Custom Update Record",
"Custom API Call": "自定义 API 呼叫",
"Get contacts on Odoo": "Get contacts on Odoo",
"Create/Update contact on Odoo": "Create/Update contact on Odoo",
"Create/Update company on Odoo": "Create/Update company on Odoo",
"Records can be listed and filtered": "Records can be listed and filtered",
"Create a new record in the specified model": "Create a new record in the specified model",
"Update an existing record in the specified model": "Update an existing record in the specified model",
"Make a custom XML-RPC API call to Odoo": "Make a custom XML-RPC API call to Odoo",
"Type": "类型",
"Contact Name": "Contact Name",
"Contact Phone": "Contact Phone",
"Contact E-mail": "Contact E-mail",
"Company Name": "Company Name",
"Job Title": "Job Title",
"Company Phone": "Company Phone",
"Company E-mail": "Company E-mail",
"Model": "Model",
"Search domains": "Search domains",
"Fields": "Fields",
"Offset": "Offset",
"Limit": "Limit",
"Fields and Values": "Fields and Values",
"Record ID": "Record ID",
"Method": "方法",
"Select which contact type to get": "Select which contact type to get",
"Would you like to search any specific name?": "Would you like to search any specific name?",
"Model name. e.g.: res.partner": "Model name. e.g.: res.partner",
"A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.": "A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.",
"Returns the requested fields of the records. When undefined, returns all fields.": "Returns the requested fields of the records. When undefined, returns all fields.",
"JSON object of field names and their corresponding values": "JSON object of field names and their corresponding values",
"ID of the record to update": "ID of the record to update",
"The Odoo model to interact with (e.g., res.partner, product.product)": "The Odoo model to interact with (e.g., res.partner, product.product)",
"The method to call on the model (e.g., search_read, create, write)": "The method to call on the model (e.g., search_read, create, write)",
"Contact": "Contact",
"Company": "Company",
"Read": "已读",
"Search read": "Search read",
"Search count": "Search count",
"Search": "搜索",
"Create": "Create",
"Write": "写入",
"Unlink": "Unlink",
"Fields get": "Fields get"
}

View File

@@ -0,0 +1,70 @@
import {
createPiece,
PieceAuth,
Property,
} from '@activepieces/pieces-framework';
import Odoo from './commom/index';
import actions from './lib/actions';
export const odooAuth = PieceAuth.CustomAuth({
props: {
base_url: Property.ShortText({
displayName: 'Odoo URL',
description: 'Enter the base URL',
required: true,
}),
database: Property.ShortText({
displayName: 'Odoo Database',
description: 'Enter the database name',
required: true,
}),
username: Property.ShortText({
displayName: 'Odoo Username',
description: 'Enter the username',
required: true,
}),
api_key: PieceAuth.SecretText({
displayName: 'Odoo API Key',
description: 'Enter the API Key',
required: true,
}),
},
// Optional Validation
validate: async ({ auth }) => {
const { base_url, database, username, api_key } = auth;
const odoo = new Odoo({
url: base_url,
port: 443,
db: database,
username: username,
password: api_key,
});
try {
await odoo.connect();
return {
valid: true,
};
} catch (err) {
return {
valid: false,
error:
'Connection failed. Please check your credentials and try again.',
};
}
},
required: true,
});
export const odoo = createPiece({
displayName: 'Odoo',
description: 'Open source all-in-one management software',
auth: odooAuth,
minimumSupportedRelease: '0.30.0',
logoUrl: 'https://cdn.activepieces.com/pieces/odoo.png',
authors: ["mariomeyer","kishanprmr","abuaboud"],
actions,
triggers: [],
});

View File

@@ -0,0 +1,51 @@
import { createAction, Property } from "@activepieces/pieces-framework";
import Odoo from "../../commom/index";
import { odooAuth } from "../..";
export default createAction({
name: 'create_company', // Must be a unique across the piece, this shouldn't be changed.
auth: odooAuth,
displayName: 'Create company',
description: 'Create/Update company on Odoo',
props: {
// Properties to ask from the user, in this ask we will take number of
name: Property.ShortText({
displayName: 'Company Name',
description: undefined,
required: true,
}),
phone: Property.ShortText({
displayName: 'Company Phone',
description: undefined,
required: true,
}),
email: Property.ShortText({
displayName: 'Company E-mail',
description: undefined,
required: true,
})
},
async run(context) {
const odoo = new Odoo({
url: context.auth.props.base_url,
port: 443,
db: context.auth.props.database,
username: context.auth.props.username,
password: context.auth.props.api_key,
})
try {
const uid = await odoo.connect();
console.log("Connected to Odoo server. Uid: ", uid);
const c = await odoo.saveCompany({
name: context.propsValue['name'],
phone: context.propsValue['phone'],
email: context.propsValue['email'],
});
return `Company ${c} created!`
} catch (err) {
return err;
}
},
});

View File

@@ -0,0 +1,62 @@
import { createAction, Property } from "@activepieces/pieces-framework";
import Odoo from "../../commom/index";
import { odooAuth } from "../..";
export default createAction({
name: 'create_contact', // Must be a unique across the piece, this shouldn't be changed.
auth: odooAuth,
displayName: 'Create contact',
description: 'Create/Update contact on Odoo',
props: {
// Properties to ask from the user, in this ask we will take number of
name: Property.ShortText({
displayName: 'Contact Name',
description: undefined,
required: true,
}),
phone: Property.ShortText({
displayName: 'Contact Phone',
description: undefined,
required: true,
}),
email: Property.ShortText({
displayName: 'Contact E-mail',
description: undefined,
required: true,
}),
company: Property.ShortText({
displayName: 'Company Name',
description: undefined,
required: true,
}),
title: Property.ShortText({
displayName: 'Job Title',
description: undefined,
required: true,
}),
},
async run(context) {
const odoo = new Odoo({
url: context.auth.props.base_url,
port: 443,
db: context.auth.props.database,
username: context.auth.props.username,
password: context.auth.props.api_key,
})
try {
await odoo.connect();
const c = await odoo.saveContact({
name: context.propsValue['name'],
phone: context.propsValue['name'],
email: context.propsValue['name'],
company: context.propsValue['company'],
title: context.propsValue['title']
});
return `Contact ${c} created!`
} catch (err) {
return err
}
}
});

View File

@@ -0,0 +1,47 @@
import { createAction, Property } from "@activepieces/pieces-framework";
import Odoo from "../../commom/index";
import { odooAuth } from "../..";
export default createAction({
name: 'create_record',
auth: odooAuth,
displayName: 'Custom Create Record',
description: 'Create a new record in the specified model',
props: {
model: Property.ShortText({
displayName: 'Model',
description: "Model name. e.g.: res.partner",
required: true,
defaultValue: 'res.partner',
}),
fields: Property.Json({
displayName: 'Fields and Values',
description: 'JSON object of field names and their corresponding values',
required: true,
defaultValue: {
"name": "New Partner",
"email": "newpartner@example.com"
},
})
},
async run(context) {
const odoo = new Odoo({
url: context.auth.props.base_url,
port: 443,
db: context.auth.props.database,
username: context.auth.props.username,
password: context.auth.props.api_key,
});
try {
await odoo.connect();
const fields = context.propsValue.fields;
const model = context.propsValue.model;
const recordId = await odoo.createRecord({ model, fields });
return { id: recordId };
} catch (err) {
return err;
}
}
});

View File

@@ -0,0 +1,273 @@
import {
createAction,
Property,
} from '@activepieces/pieces-framework';
import { odooAuth } from '../../index';
import Odoo from '../../commom/index';
export const customOdooApiCall = createAction({
name: 'custom_odoo_api_call',
displayName: 'Custom API Call',
description: 'Make a custom XML-RPC API call to Odoo',
auth: odooAuth,
props: {
model: Property.ShortText({
displayName: 'Model',
description:
'The Odoo model to interact with (e.g., res.partner, product.product)',
required: true,
}),
method: Property.StaticDropdown({
displayName: 'Method',
description:
'The method to call on the model (e.g., search_read, create, write)',
options: {
options: [
{ value: 'read', label: 'Read' },
{ value: 'search_read', label: 'Search read' },
{ value: 'search_count', label: 'Search count' },
{ value: 'search', label: 'Search' },
{ value: 'create', label: 'Create' },
{ value: 'write', label: 'Write' },
{ value: 'unlink', label: 'Unlink' },
{ value: 'fields_get', label: 'Fields get' },
],
},
required: true,
}),
method_params: Property.DynamicProperties({
auth: odooAuth,
displayName: '',
required: true,
refreshers: ['method'],
props: async ({ method }) => {
if (!method) return {};
type propsKey =
| 'search'
| 'search_count'
| 'search_read'
| 'read'
| 'create'
| 'write'
| 'unlink'
| 'fields_get';
const propsMap = {
read: {
record_ids: Property.Array({
displayName: 'Record IDs',
description: 'IDs of the record to read',
required: true,
}),
fields: Property.Array({
displayName: 'Fields',
description:
'Returns the requested fields of the records. When undefined, returns all fields.',
required: false,
}),
},
search: {
domain: Property.Json({
displayName: 'Domain',
description:
'A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.',
defaultValue: [['is_company', '=', true]],
required: false,
}),
limit: Property.Number({
displayName: 'Limit',
description:
'Maximum number of records to return',
required: false,
}),
offset: Property.Number({
displayName: 'Offset',
description:
'Number of records to skip',
required: false,
}),
},
search_read: {
domain: Property.Json({
displayName: 'Domain',
description:
'A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.',
defaultValue: [['is_company', '=', true]],
required: false,
}),
fields: Property.Array({
displayName: 'Fields',
description:
'Returns the requested fields of the records. When undefined, returns all fields.',
required: false,
}),
limit: Property.Number({
displayName: 'Limit',
description:
'Maximum number of records to return',
required: false,
}),
offset: Property.Number({
displayName: 'Offset',
description:
'Number of records to skip',
required: false,
}),
},
search_count: {
domain: Property.Json({
displayName: 'Domain',
description:
'A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.',
defaultValue: [['is_company', '=', true]],
required: false,
}),
},
create: {
values: Property.Object({
displayName: 'Values',
description: 'Values to create',
required: true,
}),
},
write: {
record_id: Property.Number({
displayName: 'Record ID',
description: 'ID of the record to update',
required: true,
}),
values: Property.Object({
displayName: 'Values',
description: 'Values to update',
required: true,
}),
},
unlink: {
record_id: Property.Number({
displayName: 'Record ID',
description: 'ID of the record to delete',
required: true,
}),
},
fields_get: {
attributes: Property.Array({
displayName: 'Attributes',
description:
'Can be used to inspect a models fields and check which ones seem to be of interest.',
required: false,
defaultValue: ['string', 'help', 'type'],
}),
},
};
const key = method as unknown as string;
if (key in propsMap) {
return propsMap[key as propsKey];
}
return {};
},
}),
},
async run({ auth, propsValue }) {
const { props: { base_url, database, username, api_key } } = auth;
const { model, method, method_params } = propsValue;
const odoo = new Odoo({
url: base_url,
port: 443,
db: database,
username: username,
password: api_key,
});
try {
// Connect to Odoo
await odoo.connect();
// Prepare parameters based on the method
let params: any[] = [];
// Otherwise, build params based on the method
let tempParams: any[] = [];
const tempKwParams: any = {};
switch (method) {
case 'search_read': {
const { domain, fields, limit, offset } = method_params;
tempParams = [domain || []];
if (fields && fields.length > 0) tempKwParams.fields = fields;
if (offset !== undefined) tempKwParams.offset = offset;
if (limit !== undefined) tempKwParams.limit = limit;
params = [tempParams, tempKwParams];
break;
}
case 'read': {
// For read, the structure is [[ids], fields]
const { record_ids, fields } = method_params;
const parsedIds = Array.isArray(record_ids)
? record_ids.map(id => parseInt(id, 10))
: [];
params = [parsedIds.length > 0 ? [parsedIds] : [], fields ? { fields } : {}];
break;
}
case 'search': {
// For search, the structure is [[domain], offset, limit]
const { domain, limit, offset } = method_params;
tempParams = [domain || []];
if (offset !== undefined) tempKwParams.offset = offset;
if (limit !== undefined) tempKwParams.limit = limit;
params = [tempParams, tempKwParams];
break;
}
case 'search_count': {
const { domain } = method_params;
tempParams = [domain || []];
params = [tempParams];
break;
}
case 'create': {
// For create, the structure is [values]
const { values } = method_params;
tempParams = [values || {}];
params = [tempParams];
break;
}
case 'write': {
// For write, the structure is [[ids], values]
const { record_id, values } = method_params;
params = [record_id !== undefined ? [[parseInt(record_id, 10)]] : [], values ? { values } : {}];
break;
}
case 'unlink': {
const { record_id } = method_params;
params = [record_id !== undefined ? [[parseInt(record_id, 10)]] : []];
break;
}
}
const result = await odoo.execute_kw({
model,
method,
params,
});
return result;
} catch (error) {
throw new Error(`Odoo API call failed: ${error}`);
}
},
});
export default customOdooApiCall;

View File

@@ -0,0 +1,56 @@
import { createAction, Property } from "@activepieces/pieces-framework";
import Odoo from "../../commom/index";
import { odooAuth } from "../..";
export default createAction({
name: 'get_contacts', // Must be a unique across the piece, this shouldn't be changed.
auth: odooAuth,
displayName: 'Get contacts',
description: 'Get contacts on Odoo',
props: {
// Properties to ask from the user, in this ask we will take number of
type: Property.StaticDropdown({
displayName: 'Type',
description: "Select which contact type to get",
required: true,
options: {
options: [
{
label: "Contact",
value: false,
},
{
label: "Company",
value: true,
},
],
}
}),
name: Property.ShortText({
displayName: 'Contact Name',
description: "Would you like to search any specific name?",
required: false,
}),
},
async run(context) {
const odoo = new Odoo({
url: context.auth.props.base_url,
port: 443,
db: context.auth.props.database,
username: context.auth.props.username,
password: context.auth.props.api_key,
})
try {
await odoo.connect();
if (context.propsValue['name'])
return await odoo.getContact({ name: context.propsValue['name'], isCompany: context.propsValue['type'] })
else
return await odoo.getAllContacts({ isCompany: context.propsValue['type'] })
} catch (err) {
return err
}
}
});

View File

@@ -0,0 +1,65 @@
import { createAction, Property } from "@activepieces/pieces-framework";
import Odoo from "../../commom/index";
import { odooAuth } from "../..";
import { z } from 'zod';
import { propsValidation } from '@activepieces/pieces-common';
export default createAction({
name: 'get_records',
auth: odooAuth,
displayName: 'Custom Search and read records',
description: 'Records can be listed and filtered',
props: {
// Properties to ask from the user, in this ask we will take number of
model: Property.ShortText({
displayName: 'Model',
description: "Model name. e.g.: res.partner",
required: true,
defaultValue: 'res.partner',
}),
domain: Property.Json({
displayName: 'Search domains',
required: false,
description: 'A domain is a list of criteria, each criterion being a triple of (field_name, operator, value). See https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#reference-orm-domains for details.',
defaultValue: [
["is_company", "=", true],
],
}),
fields: Property.Array({
displayName: 'Fields',
description: 'Returns the requested fields of the records. When undefined, returns all fields.',
required: false,
}),
offset: Property.Number({
displayName: 'Offset',
required: false,
}),
limit: Property.Number({
displayName: 'Limit',
required: false,
})
},
async run(context) {
await propsValidation.validateZod(context.propsValue, {
limit: z.number().min(1).optional(),
});
const odoo = new Odoo({
url: context.auth.props.base_url,
port: 443,
db: context.auth.props.database,
username: context.auth.props.username,
password: context.auth.props.api_key,
})
try {
await odoo.connect();
const domainArray = context.propsValue.domain
? (context.propsValue.domain as unknown as any[])
: [];
return await odoo.getRecords({model: context.propsValue.model, domain: domainArray, fields: context.propsValue.fields, offset: context.propsValue.offset, limit: context.propsValue.limit})
} catch (err) {
return err
}
}
});

View File

@@ -0,0 +1,17 @@
import createContact from './create-contact';
import createCompany from './create-company';
import getContacts from './get-contacts';
import getRecords from './get-records';
import createRecord from './create-record';
import updateRecord from './update-record';
import customOdooApiCall from './custom-api-call';
export default [
getContacts,
createContact,
createCompany,
getRecords,
createRecord,
updateRecord,
customOdooApiCall,
];

View File

@@ -0,0 +1,51 @@
import { createAction, Property } from "@activepieces/pieces-framework";
import Odoo from "../../commom/index";
import { odooAuth } from "../..";
export default createAction({
name: 'update_record',
auth: odooAuth,
displayName: 'Custom Update Record',
description: 'Update an existing record in the specified model',
props: {
model: Property.ShortText({
displayName: 'Model',
description: "Model name. e.g.: res.partner",
required: true,
defaultValue: 'res.partner',
}),
recordId: Property.Number({
displayName: 'Record ID',
description: 'ID of the record to update',
required: true,
}),
fields: Property.Json({
displayName: 'Fields and Values',
description: 'JSON object of field names and their corresponding values',
required: true,
defaultValue: {
"email": "updatedemail@example.com"
},
})
},
async run(context) {
const odoo = new Odoo({
url: context.auth.props.base_url,
port: 443,
db: context.auth.props.database,
username: context.auth.props.username,
password: context.auth.props.api_key,
});
try {
await odoo.connect();
const fields = context.propsValue.fields;
const recordId = context.propsValue.recordId;
const model = context.propsValue.model;
const result = await odoo.updateRecord({ model, recordId, fields });
return { success: result };
} catch (err) {
return err;
}
}
});