New to Kestra?
Use blueprints to kickstart your first workflows.
Nightly Kestra flow that exports one day of Odoo invoices to CSV in S3, with retries, Slack alerting, and backfill-safe partitioning.
Pull customer invoice data out of Odoo on a nightly schedule and land it in your cloud warehouse staging area so analysts can model revenue, receivables, and tax downstream. This Odoo to S3 pipeline solves the gap between an ERP that owns the transactional truth and a data warehouse that needs clean, date-partitioned files. It runs unattended: each remote call retries on transient errors, failures alert Slack, and the data window is derived from the schedule date so backfills and replays land in the right partition instead of today's.
nightly trigger (io.kestra.plugin.core.trigger.Schedule) fires at 02:00 UTC and exports the previous calendar day of invoices.query_invoices (io.kestra.plugin.odoo.Query) runs a SEARCH_READ against the account.move model, filtering on move_type = out_invoice, the selected state input, and an invoice_date window derived from {{ trigger.date ?? execution.startDate }}. It fetches a fixed field set, caps at limit: 100000, and stores the result as an ION file via fetchType: STORE.log_row_count (io.kestra.plugin.core.log.Log) surfaces how many invoices were exported so an empty day is distinguishable from a broken run.convert_to_csv (io.kestra.plugin.serdes.csv.IonToCsv) converts the ION result to a warehouse-friendly CSV using NON_NUMERIC quoting.upload_to_warehouse (io.kestra.plugin.aws.s3.Upload) lands the CSV in the staging bucket under a date-partitioned key, ready for loading into Snowflake, BigQuery, Redshift, or a lakehouse table.s3://{{ inputs.bucket }}/odoo/invoices/yyyy/MM/dd/account_move.csv.Odoo has no built-in scheduler for exporting data to a cloud warehouse. Kestra fills that gap: an event-driven Schedule trigger replaces brittle cron scripts, task-level retry blocks ride out flaky XML-RPC and S3 calls, the errors block guarantees a failed extract is never silent, and the whole pipeline is declarative YAML you can version and review. Execution outputs give you lineage from the Odoo query through the CSV to the uploaded object. The state input is a SELECT, so its value is constrained to a known set and never arbitrary free text flowing into the Odoo domain filter.
account.move records.s3:PutObject. Static IAM keys are shown here; in production prefer the AWS default credentials chain (instance profile, IRSA) or an assumed role for least privilege.ODOO_URL: base URL of the Odoo instance, including scheme and port.ODOO_DB: Odoo database name.ODOO_USERNAME: Odoo login used for XML-RPC authentication.ODOO_PASSWORD: password for that Odoo user.AWS_DEFAULT_REGION: AWS region of the staging bucket.AWS_ACCESS_KEY_ID: AWS access key id for the S3 upload.AWS_SECRET_ACCESS_KEY: AWS secret access key for the S3 upload.SLACK_WEBHOOK: Slack incoming webhook URL used for failure alerts.bucket input to your staging bucket name and pick the invoice state.filters and fields lists to match the invoices and columns you want.Schedule trigger run it at 02:00 UTC. To backfill a past day, start a backfill from the Triggers tab; the window and S3 key follow the backfilled date automatically.COPY, BigQuery load, dbt run) once the CSV lands.account.move.line, res.partner, or sale.order by adding more Query tasks.state filter or add currency and partner filters for multi-entity exports.limit: 100000, narrow the window or add an offset loop.