From 4decb3cb3cae186a1f606a75f6a2d5302851aacf Mon Sep 17 00:00:00 2001 From: Kevin Bataille Date: Thu, 26 Feb 2026 00:23:07 +0100 Subject: [PATCH] Initial implementation of the reconciliation script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Standalone Ruby script reconciling GoCardless payments, Dolibarr invoices (via API), and Shine bank statements. Three-pass engine: GC↔Dolibarr matching, open invoice audit, payout↔bank verification. Includes dry-run and --fix mode to auto-mark Dolibarr invoices as paid. Co-Authored-By: Claude Sonnet 4.6 --- .env.example | 12 + .gitignore | 13 + Gemfile | 4 + Gemfile.lock | 24 + README.md | 280 + bin/reconcile | 88 + docs/dolibarr.json | 18004 ++++++++++++++++++++++ docs/reconciliation_plan.md | 269 + lib/boot.rb | 12 + lib/dolibarr/client.rb | 83 + lib/reconciliation/dolibarr_fetcher.rb | 115 + lib/reconciliation/engine.rb | 243 + lib/reconciliation/fixer.rb | 56 + lib/reconciliation/gocardless_parser.rb | 64 + lib/reconciliation/reporter.rb | 203 + lib/reconciliation/shine_parser.rb | 64 + 16 files changed, 19534 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 README.md create mode 100755 bin/reconcile create mode 100644 docs/dolibarr.json create mode 100644 docs/reconciliation_plan.md create mode 100644 lib/boot.rb create mode 100644 lib/dolibarr/client.rb create mode 100644 lib/reconciliation/dolibarr_fetcher.rb create mode 100644 lib/reconciliation/engine.rb create mode 100644 lib/reconciliation/fixer.rb create mode 100644 lib/reconciliation/gocardless_parser.rb create mode 100644 lib/reconciliation/reporter.rb create mode 100644 lib/reconciliation/shine_parser.rb diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..8d3e241 --- /dev/null +++ b/.env.example @@ -0,0 +1,12 @@ +# Dolibarr API +DOLIBARR_URL=https://your-dolibarr.example.com/api/index.php +DOLIBARR_API_KEY=your_api_key + +# GoCardless payment method ID for GoCardless +# Find it with: GET /setup/dictionary/payment_types +# Look for "Prélèvement GoCardless" or similar +DOLIBARR_GC_PAYMENT_ID=6 + +# Dolibarr bank account ID (for recording payments) +# Find it with: GET /bankaccounts +DOLIBARR_BANK_ACCOUNT_ID=1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cf7e632 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Credentials — never commit +.env + +# Input data — contains customer PII and financial data +gocardless/ +shine/ + +# Output +tmp/ + +# Ruby +.bundle/ +vendor/bundle/ diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..7db78a1 --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source "https://rubygems.org" + +gem "httparty" +gem "dotenv" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..1d5baf2 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,24 @@ +GEM + remote: https://rubygems.org/ + specs: + bigdecimal (4.0.1) + csv (3.3.5) + dotenv (3.2.0) + httparty (0.24.2) + csv + mini_mime (>= 1.0.0) + multi_xml (>= 0.5.2) + mini_mime (1.1.5) + multi_xml (0.8.1) + bigdecimal (>= 3.1, < 5) + +PLATFORMS + ruby + x86_64-linux + +DEPENDENCIES + dotenv + httparty + +BUNDLED WITH + 2.6.7 diff --git a/README.md b/README.md new file mode 100644 index 0000000..fad2b58 --- /dev/null +++ b/README.md @@ -0,0 +1,280 @@ +# Dolibarr / GoCardless / Shine Reconciliation + +A standalone Ruby script that cross-checks three financial systems and flags discrepancies. + +## The problem it solves + +Payments flow through three separate systems that are not automatically linked: + +``` +Shine bank account ← GoCardless payouts ← GoCardless payments ← Dolibarr invoices +``` + +**Typical workflow:** +1. GoCardless initiates a direct debit for a customer +2. If the debit succeeds, you create the corresponding invoice in Dolibarr and mark it paid +3. If the debit fails, you cancel or delete the draft invoice +4. GoCardless batches collected payments into payouts and transfers them to your Shine account + +Discrepancies arise when any of these steps is missed: +- A GoCardless payment succeeded but the Dolibarr invoice was never created +- A Dolibarr invoice is marked paid but no GoCardless payment can be found for it +- A GoCardless payout never appeared in the Shine bank account + +--- + +## Requirements + +- Ruby 3.x +- Bundler (`gem install bundler`) +- Network access to your Dolibarr instance + +--- + +## Installation + +```bash +cd dolibarr_shine_reconciliation +bundle install +cp .env.example .env +``` + +Edit `.env` and fill in your Dolibarr credentials: + +```dotenv +DOLIBARR_URL=https://your-dolibarr.example.com/api/index.php +DOLIBARR_API_KEY=your_api_key + +# GoCardless payment method ID in Dolibarr (used by --fix mode) +# Find it: GET /setup/dictionary/payment_types +# Look for the "Prélèvement GoCardless" entry +DOLIBARR_GC_PAYMENT_ID=6 + +# Bank account ID in Dolibarr (used by --fix mode) +# Find it: GET /bankaccounts +DOLIBARR_BANK_ACCOUNT_ID=1 +``` + +--- + +## Exporting the data + +### GoCardless — payments CSV + +Dashboard → **Payments** → filter by date range → **Export CSV** + +Place the file in `gocardless/`. The expected columns are: + +| Column | Description | +|--------|-------------| +| `id` | Payment ID, e.g. `PM014J7X4PY98T` | +| `charge_date` | Date the customer was debited (`YYYY-MM-DD`) | +| `amount` | Amount in euros (`30.52`) | +| `description` | Free text — used as the primary match key against the Dolibarr invoice ref | +| `status` | `paid_out`, `confirmed`, `failed`, `cancelled` | +| `links.payout` | Payout ID this payment belongs to | +| `payout_date` | Date the payout was sent to your bank | +| `customers.given_name` | Customer first name | +| `customers.family_name` | Customer last name | + +### Shine — bank statement CSV + +App → **Comptes** → **Exporter le relevé** → select year → download + +Place the annual CSV in `shine/`. The expected columns are: + +| Column | Description | +|--------|-------------| +| `Date de la valeur` | Value date (`DD/MM/YYYY`) | +| `Crédit` | Credit amount in French format (`51,10`) | +| `Débit` | Debit amount | +| `Libellé` | Transaction description | +| `Nom de la contrepartie` | Counterparty name — GoCardless payouts show `GOCARDLESS SAS` here | + +The Shine CSV uses semicolons as separator (`;`), UTF-8 encoding, and Windows CRLF line endings. The script handles all of this automatically. + +--- + +## Usage + +### Dry run — report only, no changes to Dolibarr + +```bash +ruby bin/reconcile \ + --from 2026-01-01 \ + --to 2026-01-31 \ + --gc gocardless/payments_export.csv \ + --shine shine/Cyanet_2026-01-01_2026-12-31_EXPORT/BANQUE_2026-01-01_2026-12-31/BQ_2026-01-01_2026-12-31.csv +``` + +The Shine file is optional. Without it, payout verification (Pass 3) is skipped: + +```bash +ruby bin/reconcile \ + --from 2026-01-01 \ + --to 2026-01-31 \ + --gc gocardless/payments_export.csv +``` + +### Fix mode — auto-mark Dolibarr invoices as paid + +When the script detects a GoCardless payment that was collected but the matching Dolibarr invoice is still open, `--fix` records the payment in Dolibarr via the API: + +```bash +ruby bin/reconcile \ + --from 2026-01-01 \ + --to 2026-01-31 \ + --gc gocardless/payments_export.csv \ + --shine shine/.../BQ_2026-01-01_2026-12-31.csv \ + --fix +``` + +`--fix` only affects invoices flagged `GC_PAID_DOLIBARR_OPEN`. All other entries are reported only. + +--- + +## How matching works + +The script runs three passes over the data. + +### Pass 1 — GoCardless ↔ Dolibarr + +For each GoCardless payment, an attempt is made to find a matching Dolibarr invoice in two steps: + +**Strong match** — the GoCardless `description` field equals the Dolibarr invoice `ref` exactly (case-insensitive). This fires when you put the invoice reference in the GoCardless payment description at creation time. + +**Soft match** — if no strong match is found, the script looks for a Dolibarr invoice where: +- The amount is identical (compared in cents to avoid floating-point errors) +- The invoice date is within 7 days of the GoCardless `charge_date` +- The customer name on the Dolibarr invoice matches the GoCardless customer name (accent-insensitive, word-order-insensitive) + +Once matched (or not), each payment is assigned one of these flags: + +| Flag | Meaning | Action | +|------|---------|--------| +| `MATCHED` | GC payment collected, Dolibarr invoice paid | None | +| `GC_PAID_DOLIBARR_OPEN` | GC collected but Dolibarr invoice is still open | Create the invoice / use `--fix` | +| `GC_NO_INVOICE` | GC payment collected, no Dolibarr invoice found at all | Create the invoice in Dolibarr | +| `GC_FAILED` | GC payment failed | Check if Dolibarr invoice was correctly cancelled | +| `GC_CANCELLED` | GC payment was cancelled before collection | No action | +| `DOLIBARR_PAID_NO_GC` | Dolibarr invoice paid (in the date range), no GC payment found | Verify — may be a manual or cash payment | + +After processing all GC payments, open Dolibarr invoices with no GC counterpart are flagged: + +| Flag | Meaning | Action | +|------|---------|--------| +| `DOLIBARR_OPEN_NO_GC` | Dolibarr invoice open, no GC payment found | Follow up — missed debit or GC export is incomplete | + +### Pass 2 — open Dolibarr invoice audit + +All invoices fetched from Dolibarr with status `open` (validated, not yet paid) that were not matched by any GC payment are listed as `DOLIBARR_OPEN_NO_GC`. Overdue invoices (due date in the past) are highlighted. + +### Pass 3 — GoCardless payouts ↔ Shine bank + +GoCardless batches individual payments into payouts and transfers them as a single bank credit. The script groups `paid_out` payments by their payout ID, sums the amounts, and looks for a matching credit in Shine: + +1. **Exact match** — same amount, date within 2 days → `PAYOUT_VERIFIED` +2. **Date match only** — date within 2 days but amount differs → `PAYOUT_AMOUNT_MISMATCH` (expected: GoCardless deducts its fee from the payout, so the bank credit is always slightly less than the sum of payments) +3. **No match found** → `PAYOUT_MISSING` + +`PAYOUT_AMOUNT_MISMATCH` is the normal case when GoCardless fees are deducted. The difference shown in the report is the total fee charged for the period. + +--- + +## Output + +### Terminal report + +``` +============================================================ + RECONCILIATION REPORT: 2026-01-01 to 2026-01-31 +============================================================ + +DOLIBARR + Total invoices in scope: 9 + Open (no GC match): 2 ← needs attention + Paid (GC matched): 3 + +GOCARDLESS ↔ DOLIBARR + Matched (paid both sides): 3 ✓ + GC paid / Dolibarr open: 0 + Dolibarr paid / no GC: 0 + GC failed: 1 + GC cancelled: 0 + GC payment / no invoice: 4 ← investigate + +SHINE ↔ GOCARDLESS PAYOUTS + Payouts expected: 2 + Verified: 0 + Amount mismatch: 2 ← check GC fees + Missing in Shine: 0 + Expected total: €107.74 + Actual total: €104.91 + Difference: €-2.83 ← GoCardless fees + +ACTIONS NEEDED (6) +------------------------------------------------------------ + 1. [DOLIBARR_OPEN_NO_GC] FA2502-0075 €29.44 ARTHUR Muriel overdue since 2025-02-01 + 2. [GC_NO_INVOICE] GC: PM01RE90... €26.10 MARIE RIVIERE 2026-01-05 + ... +``` + +### CSV export + +A file `tmp/reconciliation_YYYY-MM-DD.csv` is written after every run with one row per invoice/payment, including the flag and recommended action. Suitable for importing into a spreadsheet for manual review. + +--- + +## Project structure + +``` +bin/reconcile Entry point — parses CLI arguments, orchestrates the run +lib/ + boot.rb Loads all dependencies + dolibarr/ + client.rb HTTP client for the Dolibarr REST API (HTTParty) + reconciliation/ + dolibarr_fetcher.rb Fetches invoices and customer names via Dolibarr API + gocardless_parser.rb Parses the GoCardless payments CSV + shine_parser.rb Parses the Shine bank statement CSV + engine.rb 3-pass matching logic, produces flagged result set + reporter.rb Formats and prints the terminal report, writes CSV + fixer.rb Calls Dolibarr API to record payments (--fix mode) +gocardless/ Drop GoCardless CSV exports here +shine/ Shine annual export directories (as downloaded) +tmp/ Output CSVs written here +.env.example Environment variable template +docs/ + reconciliation_plan.md Original design document + dolibarr.json Dolibarr Swagger API spec +``` + +--- + +## Dolibarr API notes + +The script uses the Dolibarr REST API with an API key (`DOLAPIKEY` header). Key endpoints: + +| Method | Path | Purpose | +|--------|------|---------| +| `GET` | `/invoices?status=1` | Fetch all non-draft invoices (open and paid) | +| `GET` | `/thirdparties` | Fetch customer names for invoice matching | +| `POST` | `/invoices/paymentsdistributed` | Record a payment against an invoice (`--fix`) | +| `GET` | `/setup/dictionary/payment_types` | Look up the GoCardless payment method ID | +| `GET` | `/bankaccounts` | Look up the bank account ID | + +The `status=1` query in Dolibarr returns all non-draft invoices regardless of payment state. The script uses the `statut` field in the response (`1`=open, `2`=paid, `3`=cancelled) to distinguish them. Cancelled invoices are excluded from reconciliation. + +--- + +## Limitations and known behaviour + +**GoCardless fee deductions** — Payout amounts in Shine are always slightly less than the sum of the underlying payments because GoCardless deducts its transaction fee from the payout. This is expected and reported as `PAYOUT_AMOUNT_MISMATCH`, not an error. + +**Incomplete GoCardless export** — If your CSV export does not cover the full date range, payments from outside the export window will cause open Dolibarr invoices to appear as `DOLIBARR_OPEN_NO_GC`. Export all payments for the period you are reconciling. + +**Customer name matching** — The soft match normalises names by stripping accents, lowercasing, and sorting words, so "DUPONT Jean" matches "Jean Dupont". If a customer's name is spelled differently in GoCardless vs Dolibarr, the soft match will fail and the payment will appear as `GC_NO_INVOICE`. Correct the name in one of the systems and rerun. + +**Credit notes** — Dolibarr credit notes (`AV...` prefix) with negative amounts are included in the invoice fetch and will appear as `DOLIBARR_PAID_NO_GC` if they fall in the reconciliation period with no corresponding GoCardless refund. This is normal — credit notes are typically settled internally, not via GoCardless. + +**Supplier invoices** — Dolibarr supplier invoices (`/supplierinvoices` endpoint) are on a completely separate API path and are never fetched or considered by this script. diff --git a/bin/reconcile b/bin/reconcile new file mode 100755 index 0000000..d53c68f --- /dev/null +++ b/bin/reconcile @@ -0,0 +1,88 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "optparse" +require "date" +require_relative "../lib/boot" + +options = { + fix: false, + from: nil, + to: nil, + gc: nil, + shine: nil +} + +OptionParser.new do |opts| + opts.banner = <<~BANNER + Usage: bin/reconcile --from DATE --to DATE --gc PATH [--shine PATH] [--fix] + + Options: + BANNER + + opts.on("--from DATE", "Start date (YYYY-MM-DD), inclusive") do |v| + options[:from] = Date.parse(v) + end + + opts.on("--to DATE", "End date (YYYY-MM-DD), inclusive") do |v| + options[:to] = Date.parse(v) + end + + opts.on("--gc PATH", "GoCardless payments CSV file path") do |v| + options[:gc] = v + end + + opts.on("--shine PATH", "Shine bank statement CSV file path (optional)") do |v| + options[:shine] = v + end + + opts.on("--fix", "Apply fixes: mark matching Dolibarr invoices as paid via API") do + options[:fix] = true + end + + opts.on("-h", "--help", "Show this help") do + puts opts + exit + end +end.parse! + +# Validate required options +errors = [] +errors << "--from is required" unless options[:from] +errors << "--to is required" unless options[:to] +errors << "--gc is required" unless options[:gc] +errors << "--gc file not found: #{options[:gc]}" if options[:gc] && !File.exist?(options[:gc]) +errors << "--shine file not found: #{options[:shine]}" if options[:shine] && !File.exist?(options[:shine]) + +unless errors.empty? + errors.each { |e| warn "Error: #{e}" } + exit 1 +end + +# Run reconciliation +client = Dolibarr::Client.new +fetcher = Reconciliation::DolibarrFetcher.new(client, from: options[:from], to: options[:to]) +gc_data = Reconciliation::GocardlessParser.parse(options[:gc], from: options[:from], to: options[:to]) +shine_data = options[:shine] ? Reconciliation::ShineParser.parse(options[:shine]) : [] + +dolibarr_invoices = fetcher.fetch_invoices + +engine = Reconciliation::Engine.new( + dolibarr_invoices: dolibarr_invoices, + gc_payments: gc_data, + shine_transactions: shine_data, + from: options[:from], + to: options[:to] +) + +result = engine.run + +reporter = Reconciliation::Reporter.new(result, from: options[:from], to: options[:to]) +reporter.print_summary + +if options[:fix] + fixer = Reconciliation::Fixer.new(client) + fixer.apply(result[:gc_paid_dolibarr_open]) +end + +reporter.write_csv diff --git a/docs/dolibarr.json b/docs/dolibarr.json new file mode 100644 index 0000000..8d6fb31 --- /dev/null +++ b/docs/dolibarr.json @@ -0,0 +1,18004 @@ +{ + "swagger": "2.0", + "host": "crm.dev.cyanet.fr", + "basePath": "/api/index.php", + "produces": [ + "application/json", + "application/xml" + ], + "consumes": [ + "application/json", + "application/xml", + "multipart/form-data" + ], + "paths": { + "/bankaccounts": { + "get": { + "operationId": "listBankaccounts", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "category", + "type": "integer", + "format": "int64", + "description": "Use this param to filter list by category", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.import_key:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + } + ], + "summary": "Get the list of accounts. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createBankaccounts", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "createBankaccountsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createBankaccountsModel" + } + } + ], + "summary": "Create account object 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/bankaccounts/{id}": { + "get": { + "operationId": "retrieveBankaccounts", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of account", + "in": "path", + "required": true + } + ], + "summary": "Get account by ID. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateBankaccounts", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of account", + "in": "path", + "required": true + }, + { + "name": "updateBankaccountsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateBankaccountsModel" + } + } + ], + "summary": "Update account 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeBankaccounts", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of account", + "in": "path", + "required": true + } + ], + "summary": "Delete account 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/bankaccounts/transfer": { + "post": { + "operationId": "bankaccountsTransfer", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "bankaccountsTransferModel", + "description": "bankaccount_from_id \nbankaccount_to_id \ndate \ndescription \namount \namount_to \ncheque_number \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/bankaccountsTransferModel" + } + } + ], + "summary": "Create an internal wire transfer between two bank accounts 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized: User does not have permission to configure bank accounts" + }, + "404": { + "description": "Not Found: Either the source or the destination bankaccount for the provided id does not exist" + }, + "500": { + "description": "Internal Server Error: Error(s) returned by the RDBMS" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/bankaccounts/{id}/lines": { + "get": { + "operationId": "bankaccountsRetrieveLines", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of account", + "in": "path", + "required": true + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.import_key:<:'20160101')\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of lines of the account. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "bankaccountsAddLine", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of account", + "in": "path", + "required": true + }, + { + "name": "bankaccountsAddLineModel", + "description": "**date** (required) \n**type** (required) \n**label** (required) \n**amount** (required) \ncategory \ncheque_number \ncheque_writer \ncheque_bank \naccountancycode \ndatev \nnum_releve \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/bankaccountsAddLineModel" + } + } + ], + "summary": "Add a line to an account 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/bankaccounts/{id}/lines/{line_id}/links": { + "post": { + "operationId": "bankaccountsAddLink", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of account", + "in": "path", + "required": true + }, + { + "name": "line_id", + "type": "integer", + "format": "int64", + "description": "ID of account line", + "in": "path", + "required": true + }, + { + "name": "bankaccountsAddLinkModel", + "description": "**url_id** (required) \n**url** (required) \n**label** (required) \n**type** (required) \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/bankaccountsAddLinkModel" + } + } + ], + "summary": "Add a link to an account line 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "get": { + "operationId": "bankaccountsRetrieveLinks", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of account", + "in": "path", + "required": true + }, + { + "name": "line_id", + "type": "integer", + "format": "int64", + "description": "ID of account line", + "in": "path", + "required": true + } + ], + "summary": "Get the list of links for a line of the account. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/bankaccounts/{id}/lines/{line_id}": { + "put": { + "operationId": "bankaccountsUpdateLine", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of account", + "in": "path", + "required": true + }, + { + "name": "line_id", + "type": "integer", + "format": "int64", + "description": "ID of account line", + "in": "path", + "required": true + }, + { + "name": "bankaccountsUpdateLineModel", + "description": "**label** (required) \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/bankaccountsUpdateLineModel" + } + } + ], + "summary": "Update an account line 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "bankaccountsRemoveLine", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of account", + "in": "path", + "required": true + }, + { + "name": "line_id", + "type": "integer", + "format": "int64", + "description": "ID of account line", + "in": "path", + "required": true + } + ], + "summary": "Delete an account line 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/bankaccounts/{id}/balance": { + "get": { + "operationId": "bankaccountsRetrieveBalance", + "tags": [ + "bankaccounts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of account", + "in": "path", + "required": true + } + ], + "summary": "Get current account balance by ID 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "number", + "format": "double" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/categories/{id}": { + "get": { + "operationId": "retrieveCategories", + "tags": [ + "categories" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + }, + { + "name": "include_childs", + "type": "boolean", + "description": "Include child categories list (true or false)", + "in": "query", + "required": false + } + ], + "summary": "Get properties of a category object 🔐", + "description": "Return an array with category information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateCategories", + "tags": [ + "categories" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of category to update", + "in": "path", + "required": true + }, + { + "name": "updateCategoriesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateCategoriesModel" + } + } + ], + "summary": "Update category 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeCategories", + "tags": [ + "categories" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Category ID", + "in": "path", + "required": true + } + ], + "summary": "Delete category 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/categories": { + "get": { + "operationId": "listCategories", + "tags": [ + "categories" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "type", + "type": "string", + "description": "Type of category ('member', 'customer', 'supplier', 'product', 'contact', 'actioncomm')", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + } + ], + "summary": "List categories 🔐", + "description": "Get a list of categories according to filters", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createCategories", + "tags": [ + "categories" + ], + "parameters": [ + { + "name": "createCategoriesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createCategoriesModel" + } + } + ], + "summary": "Create category object 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/categories/object/{type}/{id}": { + "get": { + "operationId": "categoriesRetrieveListForObject", + "tags": [ + "categories" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Object ID", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of category ('member', 'customer', 'supplier', 'product', 'contact', 'project', 'actioncomm')", + "in": "path", + "required": true + }, + { + "name": "sortfield", + "type": "string", + "defaultValue": "s.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + } + ], + "summary": "List categories of an object 🔐", + "description": "Get the list of categories linked to an object", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/categories/{id}/objects/{type}/{object_id}": { + "post": { + "operationId": "categoriesLinkObjectById", + "tags": [ + "categories" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of category ('member', 'customer', 'supplier', 'product', 'contact', 'actioncomm')", + "in": "path", + "required": true + }, + { + "name": "object_id", + "type": "integer", + "format": "int64", + "description": "ID of object", + "in": "path", + "required": true + } + ], + "summary": "Link an object to a category by id 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "categoriesUnlinkObjectById", + "tags": [ + "categories" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of category ('member', 'customer', 'supplier', 'product', 'contact', 'actioncomm')", + "in": "path", + "required": true + }, + { + "name": "object_id", + "type": "integer", + "format": "int64", + "description": "ID of the object", + "in": "path", + "required": true + } + ], + "summary": "Unlink an object from a category by id 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/categories/{id}/objects/{type}/ref/{object_ref}": { + "post": { + "operationId": "categoriesLinkObjectByRef", + "tags": [ + "categories" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of category ('member', 'customer', 'supplier', 'product', 'contact')", + "in": "path", + "required": true + }, + { + "name": "object_ref", + "type": "string", + "description": "Reference of object (product, thirdparty, member, ...)", + "in": "path", + "required": true + } + ], + "summary": "Link an object to a category by ref 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "categoriesUnlinkObjectByRef", + "tags": [ + "categories" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of category ('member', 'customer', 'supplier', 'product', 'contact', 'actioncomm')", + "in": "path", + "required": true + }, + { + "name": "object_ref", + "type": "string", + "description": "Reference of the object (product, thirdparty, member, ...)", + "in": "path", + "required": true + } + ], + "summary": "Unlink an object from a category by ref 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/categories/{id}/objects": { + "get": { + "operationId": "categoriesRetrieveObjects", + "tags": [ + "categories" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of category ('member', 'customer', 'supplier', 'product', 'contact', 'project')", + "in": "query", + "required": true + }, + { + "name": "onlyids", + "type": "integer", + "format": "int64", + "description": "Return only ids of objects (consume less memory)", + "in": "query", + "required": false + } + ], + "summary": "Get the list of objects in a category. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contacts/{id}": { + "get": { + "operationId": "retrieveContacts", + "tags": [ + "contacts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of contact", + "in": "path", + "required": true + }, + { + "name": "includecount", + "type": "integer", + "format": "int64", + "description": "Include count of elements the contact is used as a link for", + "in": "query", + "required": false + }, + { + "name": "includeroles", + "type": "integer", + "format": "int64", + "description": "Includes roles of the contact", + "in": "query", + "required": false + } + ], + "summary": "Get a contact 🔐", + "description": "Return an array with contact information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateContacts", + "tags": [ + "contacts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of contact to update", + "in": "path", + "required": true + }, + { + "name": "updateContactsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateContactsModel" + } + } + ], + "summary": "Update a contact 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "Internal Server Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeContacts", + "tags": [ + "contacts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Contact ID", + "in": "path", + "required": true + } + ], + "summary": "Delete a contact 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contacts/email/{email}": { + "get": { + "operationId": "contactsRetrieveByEmail", + "tags": [ + "contacts" + ], + "parameters": [ + { + "name": "email", + "type": "string", + "description": "Email of contact", + "in": "path", + "required": true + }, + { + "name": "includecount", + "type": "integer", + "format": "int64", + "description": "Include count of elements the contact is used as a link for", + "in": "query", + "required": false + }, + { + "name": "includeroles", + "type": "integer", + "format": "int64", + "description": "Includes roles of the contact", + "in": "query", + "required": false + } + ], + "summary": "Get a contact by Email 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Insufficient rights" + }, + "404": { + "description": "User or group not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contacts": { + "get": { + "operationId": "listContacts", + "tags": [ + "contacts" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "thirdparty_ids", + "type": "string", + "description": "Third party ids to filter contacts of (example '1' or '1,2,3')", + "in": "query", + "required": false + }, + { + "name": "category", + "type": "integer", + "format": "int64", + "description": "Use this param to filter list by category", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "includecount", + "type": "integer", + "format": "int64", + "description": "Include count of elements the contact is used as a link for", + "in": "query", + "required": false + }, + { + "name": "includeroles", + "type": "integer", + "format": "int64", + "description": "Includes roles of the contact", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true, the response will include pagination data. Default value is false. Page starts from 0*", + "in": "query", + "required": false + } + ], + "summary": "List contacts 🔐", + "description": "Get a list of contacts", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createContacts", + "tags": [ + "contacts" + ], + "parameters": [ + { + "name": "createContactsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createContactsModel" + } + } + ], + "summary": "Create a contact 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contacts/{id}/createUser": { + "post": { + "operationId": "contactsCreateUser", + "tags": [ + "contacts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of contact", + "in": "path", + "required": true + }, + { + "name": "contactsCreateUserModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/contactsCreateUserModel" + } + } + ], + "summary": "Create a user account object from contact (external user) 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contacts/{id}/categories": { + "get": { + "operationId": "contactsRetrieveCategories", + "tags": [ + "contacts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of contact", + "in": "path", + "required": true + }, + { + "name": "sortfield", + "type": "string", + "defaultValue": "s.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + } + ], + "summary": "Get categories of a contact 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contacts/{id}/categories/{category_id}": { + "put": { + "operationId": "contactsAddCategory", + "tags": [ + "contacts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of contact", + "in": "path", + "required": true + }, + { + "name": "category_id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + } + ], + "summary": "Add a category to a contact 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Insufficient rights" + }, + "404": { + "description": "Category or contact not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "contactsRemoveCategory", + "tags": [ + "contacts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of contact", + "in": "path", + "required": true + }, + { + "name": "category_id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + } + ], + "summary": "Remove the link between a category and a contact 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Insufficient rights" + }, + "404": { + "description": "Category or contact not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contracts/{id}": { + "get": { + "operationId": "retrieveContracts", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of contract", + "in": "path", + "required": true + } + ], + "summary": "Get properties of a contract object 🔐", + "description": "Return an array with contract information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateContracts", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of contract to update", + "in": "path", + "required": true + }, + { + "name": "updateContractsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateContractsModel" + } + } + ], + "summary": "Update contract general fields (won't touch lines of contract) 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeContracts", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Contract ID", + "in": "path", + "required": true + } + ], + "summary": "Delete contract 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contracts": { + "get": { + "operationId": "listContracts", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "thirdparty_ids", + "type": "string", + "description": "Thirdparty ids to filter contracts of (example '1' or '1,2,3')", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*", + "in": "query", + "required": false + } + ], + "summary": "List contracts 🔐", + "description": "Get a list of contracts", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "404": { + "description": "Not found" + }, + "503": { + "description": "Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createContracts", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "createContractsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createContractsModel" + } + } + ], + "summary": "Create contract object 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contracts/{id}/lines": { + "get": { + "operationId": "contractsRetrieveLines", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of contract", + "in": "path", + "required": true + }, + { + "name": "sortfield", + "type": "string", + "defaultValue": "d.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*", + "in": "query", + "required": false + } + ], + "summary": "Get lines of a contract 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "404": { + "description": "Not Found" + }, + "503": { + "description": "Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "contractsCreateLine", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of contrat to update", + "in": "path", + "required": true + }, + { + "name": "contractsCreateLineModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/contractsCreateLineModel" + } + } + ], + "summary": "Add a line to given contract 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contracts/{id}/lines/{lineid}": { + "put": { + "operationId": "contractsUpdateLine", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of contrat to update", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of line to update", + "in": "path", + "required": true + }, + { + "name": "contractsUpdateLineModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/contractsUpdateLineModel" + } + } + ], + "summary": "Update a line to given contract 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "contractsRemoveLine", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of contract to update", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of line to delete", + "in": "path", + "required": true + } + ], + "summary": "Delete a line to given contract 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contracts/{id}/lines/{lineid}/activate": { + "put": { + "operationId": "contractsActivateLine", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of contract to activate", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of line to activate", + "in": "path", + "required": true + }, + { + "name": "contractsActivateLineModel", + "description": "**datestart** (required) \ndateend \ncomment \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/contractsActivateLineModel" + } + } + ], + "summary": "Activate a service line of a given contract 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contracts/{id}/lines/{lineid}/unactivate": { + "put": { + "operationId": "contractsUnactivateLine", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of contract to activate", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of line to activate", + "in": "path", + "required": true + }, + { + "name": "contractsUnactivateLineModel", + "description": "**datestart** (required) \ncomment \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/contractsUnactivateLineModel" + } + } + ], + "summary": "Unactivate a service line of a given contract 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contracts/{id}/validate": { + "post": { + "operationId": "contractsValidate", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Contract ID", + "in": "path", + "required": true + }, + { + "name": "contractsValidateModel", + "description": "notrigger \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/contractsValidateModel" + } + } + ], + "summary": "Validate a contract 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contracts/{id}/close": { + "post": { + "operationId": "contractsClose", + "tags": [ + "contracts" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Contract ID", + "in": "path", + "required": true + }, + { + "name": "contractsCloseModel", + "description": "notrigger \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/contractsCloseModel" + } + } + ], + "summary": "Close all services of a contract 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/documents/download": { + "get": { + "operationId": "listDocuments", + "tags": [ + "documents" + ], + "parameters": [ + { + "name": "modulepart", + "type": "string", + "description": "Name of module or area concerned by file download ('facture', ...)", + "in": "query", + "required": true + }, + { + "name": "original_file", + "type": "string", + "description": "Relative path with filename, relative to modulepart (for example: IN201701-999/IN201701-999.pdf)", + "in": "query", + "required": false + } + ], + "summary": "Download a document 🔐", + "description": "Note that, this API is similar to using the wrapper link \"documents.php\" to download a file (used for internal HTML links of documents into application), but with no need to have a session cookie (the token is used instead).", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for parameter modulepart or original_file" + }, + "403": { + "description": "Access denied" + }, + "404": { + "description": "File not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/documents/builddoc": { + "put": { + "operationId": "documentsBuilddoc", + "tags": [ + "documents" + ], + "parameters": [ + { + "name": "documentsBuilddocModel", + "description": "**modulepart** (required) \noriginal_file \ndoctemplate \nlangcode \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/documentsBuilddocModel" + } + } + ], + "summary": "Build a document 🔐", + "description": "Test sample 1: { \"modulepart\": \"invoice\", \"original_file\": \"FA1701-001/FA1701-001.pdf\", \"doctemplate\": \"crabe\", \"langcode\": \"fr_FR\" }. Supported modules: invoice, order, proposal, contract, supplier invoice, shipment, mrp", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for parameter modulepart or original_file" + }, + "403": { + "description": "Access denied" + }, + "404": { + "description": "Invoice, Order, Proposal, Contract or Shipment not found" + }, + "500": { + "description": "Error generating document" + }, + "501": { + "description": "File not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/documents": { + "get": { + "operationId": "documentsRetrieveDocumentsListByElement", + "tags": [ + "documents" + ], + "parameters": [ + { + "name": "modulepart", + "type": "string", + "description": "Name of module or area concerned ('thirdparty', 'member', 'proposal', 'order', 'invoice', 'supplier_invoice', 'shipment', 'project', ...)", + "in": "query", + "required": true + }, + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of element", + "in": "query", + "required": false + }, + { + "name": "ref", + "type": "string", + "description": "Ref of element", + "in": "query", + "required": false + }, + { + "name": "sortfield", + "type": "string", + "description": "Sort criteria ('','fullname','relativename','name','date','size')", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "description": "Sort order ('asc' or 'desc')", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "List limit", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "content_type", + "type": "string", + "description": "Filter on content-type (example 'application/pdf' or 'application/pdf,image/jpeg'))", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*", + "in": "query", + "required": false + } + ], + "summary": "List documents of an element 🔐", + "description": "Use element ID or Ref. Supported modules: thirdparty, user, member, proposal, order, supplier_order, shipment, invoice, supplier_invoice, product, event, expensereport, knowledgemanagement, category, contract", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for parameter modulepart, id or ref" + }, + "403": { + "description": "Access denied" + }, + "404": { + "description": "Thirdparty, User, Member, Order, Invoice or Proposal not found" + }, + "500": { + "description": "Error while fetching object" + }, + "503": { + "description": "Error when retrieve ecm list" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeDocuments", + "tags": [ + "documents" + ], + "parameters": [ + { + "name": "modulepart", + "type": "string", + "description": "Name of module or area concerned by file download ('product', ...)", + "in": "query", + "required": true + }, + { + "name": "original_file", + "type": "string", + "description": "Relative path with filename, relative to modulepart (for example: PRODUCT-REF-999/IMAGE-999.jpg)", + "in": "query", + "required": true + } + ], + "summary": "Delete a document 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for parameter original_file" + }, + "403": { + "description": "Access denied" + }, + "404": { + "description": "File not found" + }, + "500": { + "description": "Error on file operation" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/documents/upload": { + "post": { + "operationId": "createDocuments", + "tags": [ + "documents" + ], + "parameters": [ + { + "name": "createDocumentsModel", + "description": "**filename** (required) \n**modulepart** (required) \nref \nsubdir \nfilecontent \nfileencoding \noverwriteifexists \ncreatedirifnotexists \nposition \ncover \narray_options \ngenerateThumbs \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/createDocumentsModel" + } + } + ], + "summary": "Upload a document 🔐", + "description": "Test sample for invoice: { \"filename\": \"mynewfile.txt\", \"modulepart\": \"invoice\", \"ref\": \"FA1701-001\", \"subdir\": \"\", \"filecontent\": \"content text\", \"fileencoding\": \"\", \"overwriteifexists\": \"0\" }. Test sample for supplier invoice: { \"filename\": \"mynewfile.txt\", \"modulepart\": \"supplier_invoice\", \"ref\": \"FA1701-001\", \"subdir\": \"\", \"filecontent\": \"content text\", \"fileencoding\": \"\", \"overwriteifexists\": \"0\" }. Test sample for medias file: { \"filename\": \"mynewfile.txt\", \"modulepart\": \"medias\", \"ref\": \"\", \"subdir\": \"image/mywebsite\", \"filecontent\": \"Y29udGVudCB0ZXh0Cg==\", \"fileencoding\": \"base64\", \"overwriteifexists\": \"0\" }. Supported modules: invoice, order, supplier_order, task/project_task, product/service, expensereport, fichinter, member, propale, agenda, contact", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad Request" + }, + "403": { + "description": "Access denied" + }, + "404": { + "description": "Object not found" + }, + "500": { + "description": "Error on file operation" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}": { + "get": { + "operationId": "retrieveInvoices", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of invoice", + "in": "path", + "required": true + }, + { + "name": "contact_list", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "description": "0:Return array contains all properties, 1:Return array contains just id, -1: Do not return contacts/adddesses", + "in": "query", + "required": false + } + ], + "summary": "Get properties of a invoice object 🔐", + "description": "Return an array with invoice information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateInvoices", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice to update", + "in": "path", + "required": true + }, + { + "name": "updateInvoicesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateInvoicesModel" + } + } + ], + "summary": "Update invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeInvoices", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Invoice ID", + "in": "path", + "required": true + } + ], + "summary": "Delete invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/ref/{ref}": { + "get": { + "operationId": "invoicesRetrieveByRef", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "ref", + "type": "string", + "description": "Ref of object", + "in": "path", + "required": true + }, + { + "name": "contact_list", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "description": "0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id, -1: Do not return contacts/adddesses", + "in": "query", + "required": false + } + ], + "summary": "Get properties of an invoice object by ref 🔐", + "description": "Return an array with invoice information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/ref_ext/{ref_ext}": { + "get": { + "operationId": "invoicesRetrieveByRefExt", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "ref_ext", + "type": "string", + "description": "External reference of object", + "in": "path", + "required": true + }, + { + "name": "contact_list", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "description": "0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id, -1: Do not return contacts/adddesses", + "in": "query", + "required": false + } + ], + "summary": "Get properties of an invoice object by ref_ext 🔐", + "description": "Return an array with invoice information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices": { + "get": { + "operationId": "listInvoices", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "thirdparty_ids", + "type": "string", + "description": "Thirdparty ids to filter orders of (example '1' or '1,2,3')", + "in": "query", + "required": false + }, + { + "name": "status", + "type": "string", + "description": "Filter by invoice status : draft | unpaid | paid | cancelled", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0", + "in": "query", + "required": false + }, + { + "name": "loadlinkedobjects", + "type": "integer", + "format": "int64", + "description": "Load also linked object", + "in": "query", + "required": false + } + ], + "summary": "List invoices 🔐", + "description": "Get a list of invoices", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "404": { + "description": "Not found" + }, + "503": { + "description": "Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createInvoices", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "createInvoicesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createInvoicesModel" + } + } + ], + "summary": "Create invoice object 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/createfromorder/{orderid}": { + "post": { + "operationId": "invoicesCreateInvoiceFromOrder", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "orderid", + "type": "integer", + "format": "int64", + "description": "Id of the order", + "in": "path", + "required": true + } + ], + "summary": "Create an invoice using an existing order. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Access not allowed for login" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/createfromcontract/{contractid}": { + "post": { + "operationId": "invoicesCreateInvoiceFromContract", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "contractid", + "type": "integer", + "format": "int64", + "description": "Id of the contract", + "in": "path", + "required": true + } + ], + "summary": "Create an invoice using a contract. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/lines": { + "get": { + "operationId": "invoicesRetrieveLines", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice", + "in": "path", + "required": true + } + ], + "summary": "Get lines of an invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "invoicesCreateLine", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice", + "in": "path", + "required": true + }, + { + "name": "invoicesCreateLineModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/invoicesCreateLineModel" + } + } + ], + "summary": "Add a line to a given invoice 🔐", + "description": "Example of POST query : { \"desc\": \"Desc\", \"subprice\": \"1.00000000\", \"qty\": \"1\", \"tva_tx\": \"20.000\", \"localtax1_tx\": \"0.000\", \"localtax2_tx\": \"0.000\", \"fk_product\": \"1\", \"remise_percent\": \"0\", \"date_start\": \"\", \"date_end\": \"\", \"fk_code_ventilation\": 0, \"info_bits\": \"0\", \"fk_remise_except\": null, \"product_type\": \"1\", \"rang\": \"-1\", \"special_code\": \"0\", \"fk_parent_line\": null, \"fk_fournprice\": null, \"pa_ht\": \"0.00000000\", \"label\": \"\", \"array_options\": [], \"situation_percent\": \"100\", \"fk_prev_id\": null, \"fk_unit\": null }", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "304": { + "description": "Not Modified" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "400": { + "description": "Bad Request" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/lines/{lineid}": { + "put": { + "operationId": "invoicesUpdateLine", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice to update", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of line to update", + "in": "path", + "required": true + }, + { + "name": "invoicesUpdateLineModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/invoicesUpdateLineModel" + } + } + ], + "summary": "Update a line to a given invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "304": { + "description": "Not Modified" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Invoice not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "invoicesRemoveLine", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of the line to delete", + "in": "path", + "required": true + } + ], + "summary": "Deletes a line of a given invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/contact/{contactid}/{type}": { + "post": { + "operationId": "invoicesCreateContact", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice to update", + "in": "path", + "required": true + }, + { + "name": "contactid", + "type": "integer", + "format": "int64", + "description": "Id of contact to add", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of the contact (BILLING, SHIPPING, CUSTOMER)", + "in": "path", + "required": true + } + ], + "summary": "Add a contact type of given invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "invoicesRemoveContact", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice to update", + "in": "path", + "required": true + }, + { + "name": "contactid", + "type": "integer", + "format": "int64", + "description": "Row key of the contact in the array contact_ids.", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of the contact (BILLING, SHIPPING, CUSTOMER).", + "in": "path", + "required": true + } + ], + "summary": "Delete a contact type of given invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/contacts": { + "post": { + "operationId": "invoicesAddContact", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + }, + { + "name": "invoicesAddContactModel", + "description": "**fk_socpeople** (required) \n**type_contact** (required) \n**source** (required) \nnotrigger \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/invoicesAddContactModel" + } + } + ], + "summary": "Adds a contact to an invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "304": { + "description": "Not Modified" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/settodraft": { + "post": { + "operationId": "invoicesSettodraft", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + }, + { + "name": "invoicesSettodraftModel", + "description": "idwarehouse \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/invoicesSettodraftModel" + } + } + ], + "summary": "Sets an invoice as draft 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "304": { + "description": "Not Modified" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/validate": { + "post": { + "operationId": "invoicesValidate", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Invoice ID", + "in": "path", + "required": true + }, + { + "name": "invoicesValidateModel", + "description": "force_number \nidwarehouse \nnotrigger \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/invoicesValidateModel" + } + } + ], + "summary": "Validate an invoice 🔐", + "description": "If you get a bad value for param notrigger check that ou provide this in body { \"idwarehouse\": 0, \"notrigger\": 0 }", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/settopaid": { + "post": { + "operationId": "invoicesSettopaid", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + }, + { + "name": "invoicesSettopaidModel", + "description": "close_code \nclose_note \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/invoicesSettopaidModel" + } + } + ], + "summary": "Sets an invoice as paid 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "304": { + "description": "Not Modified" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/settounpaid": { + "post": { + "operationId": "invoicesSettounpaid", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + } + ], + "summary": "Sets an invoice as unpaid 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "304": { + "description": "Not Modified" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/discount": { + "get": { + "operationId": "invoicesRetrieveDiscount", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice", + "in": "path", + "required": true + } + ], + "summary": "Get discount from invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/markAsCreditAvailable": { + "post": { + "operationId": "invoicesMarkAsCreditAvailable", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Invoice ID", + "in": "path", + "required": true + } + ], + "summary": "Create a discount (credit available) for a credit note or a deposit. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "304": { + "description": "Not Modified" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/usediscount/{discountid}": { + "post": { + "operationId": "invoicesUseDiscount", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice", + "in": "path", + "required": true + }, + { + "name": "discountid", + "type": "integer", + "format": "int64", + "description": "Id of discount", + "in": "path", + "required": true + } + ], + "summary": "Add a discount line into an invoice (as an invoice line) using an existing absolute discount 🔐", + "description": "Note that this consume the discount.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/usecreditnote/{discountid}": { + "post": { + "operationId": "invoicesUseCreditNote", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice", + "in": "path", + "required": true + }, + { + "name": "discountid", + "type": "integer", + "format": "int64", + "description": "Id of a discount coming from a credit note", + "in": "path", + "required": true + } + ], + "summary": "Add an available credit note discount to payments of an existing invoice. 🔐", + "description": " Note that this consume the credit note.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/{id}/payments": { + "get": { + "operationId": "invoicesRetrievePayments", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice", + "in": "path", + "required": true + } + ], + "summary": "Get list of payments of a given invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "invoicesAddPayment", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice", + "in": "path", + "required": true + }, + { + "name": "invoicesAddPaymentModel", + "description": "**datepaye** (required) \n**paymentid** (required) \n**closepaidinvoices** (required) \n**accountid** (required) \nnum_payment \ncomment \nchqemetteur \nchqbank \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/invoicesAddPaymentModel" + } + } + ], + "summary": "Add payment line to a specific invoice with the remain to pay as amount. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/paymentsdistributed": { + "post": { + "operationId": "invoicesAddPaymentDistributed", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "invoicesAddPaymentDistributedModel", + "description": "**arrayofamounts** (required) \n**datepaye** (required) \n**paymentid** (required) \n**closepaidinvoices** (required) \n**accountid** (required) \nnum_payment \ncomment \nchqemetteur \nchqbank \nref_ext \naccepthigherpayment \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/invoicesAddPaymentDistributedModel" + } + } + ], + "summary": "Add a payment to pay partially or completely one or several invoices. 🔐", + "description": "Warning: Take care that all invoices are owned by the same customer. Example of value for parameter arrayofamounts: {\"1\": {\"amount\": \"99.99\", \"multicurrency_amount\": \"\"}, \"2\": {\"amount\": \"\", \"multicurrency_amount\": \"10\"}}", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/payments/{id}": { + "put": { + "operationId": "invoicesUpdatePayment", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of payment", + "in": "path", + "required": true + }, + { + "name": "invoicesUpdatePaymentModel", + "description": "num_payment \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/invoicesUpdatePaymentModel" + } + } + ], + "summary": "Update a payment 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad parameters" + }, + "401": { + "description": "Not allowed" + }, + "404": { + "description": "Not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/invoices/templates/{id}": { + "get": { + "operationId": "invoicesRetrieveTemplateInvoice", + "tags": [ + "invoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of template invoice", + "in": "path", + "required": true + }, + { + "name": "contact_list", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "description": "0:Return array contains all properties, 1:Return array contains just id, -1: Do not return contacts/adddesses", + "in": "query", + "required": false + } + ], + "summary": "Get properties of a template invoice object 🔐", + "description": "Return an array with invoice information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/login": { + "get": { + "operationId": "loginLoginUnsecured", + "tags": [ + "login" + ], + "parameters": [ + { + "name": "login", + "type": "string", + "description": "User login", + "in": "query", + "required": true + }, + { + "name": "password", + "type": "string", + "description": "User password", + "in": "query", + "required": true + }, + { + "name": "entity", + "type": "string", + "description": "Entity (when multicompany module is used). '' means 1=first company.", + "in": "query", + "required": false + }, + { + "name": "reset", + "type": "integer", + "format": "int64", + "description": "Reset token (0=get current token, 1=ask a new token and canceled old token. This means access using current existing API token of user will fails: new token will be required for new access)", + "in": "query", + "required": false + } + ], + "summary": "Login 🔓", + "description": "Request the API token for a couple username / password. WARNING: You should NEVER use this API, like you should never use the similar API that uses the POST method. This will expose your password. To use the APIs, you should instead set an API token to the user you want to allow to use API (This API token called DOLAPIKEY can be found/set on the user page) and use this token as credential for any API call. From the API explorer, you can enter directly the \"DOLAPIKEY\" into the field at the top right of the page to get access to any allowed APIs.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Access denied" + }, + "500": { + "description": "System error" + } + } + }, + "post": { + "operationId": "listLogin", + "tags": [ + "login" + ], + "parameters": [ + { + "name": "listLoginModel", + "description": "**login** (required) \n**password** (required) \nentity \nreset \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/listLoginModel" + } + } + ], + "summary": "Login 🔓", + "description": "Request the API token for a couple username / password. WARNING: You should NEVER use this API, like you should never use the similar API that uses the POST method. This will expose your password. To use the APIs, you should instead set an API token to the user you want to allow to use API (This API token called DOLAPIKEY can be found/set on the user page) and use this token as credential for any API call. From the API explorer, you can enter directly the \"DOLAPIKEY\" into the field at the top right of the page to get access to any allowed APIs.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Access denied" + }, + "500": { + "description": "System error" + } + } + } + }, + "/multicurrencies": { + "get": { + "operationId": "listMulticurrencies", + "tags": [ + "multicurrencies" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.product_id:=:1) and (t.date_creation:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + } + ], + "summary": "List Currencies 🔐", + "description": "Get a list of Currencies", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createMulticurrencies", + "tags": [ + "multicurrencies" + ], + "parameters": [ + { + "name": "createMulticurrenciesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createMulticurrenciesModel" + } + } + ], + "summary": "Create Currency object 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/multicurrencies/{id}": { + "get": { + "operationId": "retrieveMulticurrencies", + "tags": [ + "multicurrencies" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Currency", + "in": "path", + "required": true + } + ], + "summary": "Get properties of a Currency object 🔐", + "description": "Return an array with Currency information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateMulticurrencies", + "tags": [ + "multicurrencies" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of Currency to update", + "in": "path", + "required": true + }, + { + "name": "updateMulticurrenciesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateMulticurrenciesModel" + } + } + ], + "summary": "Update Currency 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeMulticurrencies", + "tags": [ + "multicurrencies" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Currency ID", + "in": "path", + "required": true + } + ], + "summary": "Delete Currency 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/multicurrencies/bycode/{code}": { + "get": { + "operationId": "multicurrenciesRetrieveByCode", + "tags": [ + "multicurrencies" + ], + "parameters": [ + { + "name": "code", + "type": "string", + "description": "Code of Currency (ex: EUR)", + "in": "path", + "required": true + } + ], + "summary": "Get properties of a Currency object by code 🔐", + "description": "Return an array with Currency information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/multicurrencies/{id}/rates": { + "get": { + "operationId": "multicurrenciesRetrieveRates", + "tags": [ + "multicurrencies" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Currency", + "in": "path", + "required": true + } + ], + "summary": "List Currency rates 🔐", + "description": "Get a list of Currency rates", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "multicurrenciesUpdateRate", + "tags": [ + "multicurrencies" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Currency ID", + "in": "path", + "required": true + }, + { + "name": "multicurrenciesUpdateRateModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/multicurrenciesUpdateRateModel" + } + } + ], + "summary": "Update Currency rate 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/objectlinks/{id}": { + "get": { + "operationId": "objectlinksRetrieveById", + "tags": [ + "objectlinks" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of objectlink", + "in": "path", + "required": true + } + ], + "summary": "Get properties of a ObjectLink object 🔐", + "description": "Return an array with object link information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "objectlinksRemoveById", + "tags": [ + "objectlinks" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "object link ID", + "in": "path", + "required": true + } + ], + "summary": "Delete an object link 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "Internal Server Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/objectlinks": { + "post": { + "operationId": "objectlinksCreate", + "tags": [ + "objectlinks" + ], + "parameters": [ + { + "name": "objectlinksCreateModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/objectlinksCreateModel" + } + } + ], + "summary": "Create object link 🔐", + "description": "Examples: Only set \"notrigger\": 1 because 0 is the default value. Linking subscriptions for when you sell membership as part of another sale {\"fk_source\":\"1679\",\"sourcetype\":\"propal\",\"fk_target\":\"1233\",\"targettype\":\"commande\"} {\"fk_source\":\"167\",\"sourcetype\":\"facture\",\"fk_target\":\"123\",\"targettype\":\"subscription\"}", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "304": { + "description": "Not Modified" + }, + "403": { + "description": "Forbidden" + }, + "500": { + "description": "Internal Server Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "get": { + "operationId": "objectlinksRetrieveByValues", + "tags": [ + "objectlinks" + ], + "parameters": [ + { + "name": "fk_source", + "type": "integer", + "format": "int64", + "description": "source id of object we link from", + "in": "query", + "required": true + }, + { + "name": "sourcetype", + "type": "string", + "description": "type of the source object", + "in": "query", + "required": true + }, + { + "name": "fk_target", + "type": "integer", + "format": "int64", + "description": "target id of object we link to", + "in": "query", + "required": true + }, + { + "name": "targettype", + "type": "string", + "description": "type of the target object", + "in": "query", + "required": true + }, + { + "name": "relationtype", + "type": "string", + "description": "type of the relation, usually null", + "in": "query", + "required": false + } + ], + "summary": "GET object link(s) By Values, not id 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "Internal Server Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "objectlinksRemoveByValues", + "tags": [ + "objectlinks" + ], + "parameters": [ + { + "name": "fk_source", + "type": "integer", + "format": "int64", + "description": "source id of object we link from", + "in": "query", + "required": true + }, + { + "name": "sourcetype", + "type": "string", + "description": "type of the source object", + "in": "query", + "required": true + }, + { + "name": "fk_target", + "type": "integer", + "format": "int64", + "description": "target id of object we link to", + "in": "query", + "required": true + }, + { + "name": "targettype", + "type": "string", + "description": "type of the target object", + "in": "query", + "required": true + }, + { + "name": "relationtype", + "type": "string", + "description": "type of the relation, usually null", + "in": "query", + "required": false + }, + { + "name": "notrigger", + "type": "integer", + "format": "int64", + "enum": [ + "0", + "1" + ], + "description": "1=Does not execute triggers, 0=execute triggers", + "in": "query", + "required": false + } + ], + "summary": "Delete object link By Values, not id 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "Internal Server Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}": { + "get": { + "operationId": "retrieveOrders", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of order", + "in": "path", + "required": true + }, + { + "name": "contact_list", + "type": "integer", + "format": "int64", + "defaultValue": -1, + "description": "0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id, -1: Do not return contacts/adddesses", + "in": "query", + "required": false + } + ], + "summary": "Get properties of an order object by id 🔐", + "description": "Return an array with order information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateOrders", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of order to update", + "in": "path", + "required": true + }, + { + "name": "updateOrdersModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateOrdersModel" + } + } + ], + "summary": "Update order general fields (won't touch lines of order) 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeOrders", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + } + ], + "summary": "Delete order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/ref/{ref}": { + "get": { + "operationId": "ordersRetrieveByRef", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "ref", + "type": "string", + "description": "Ref of object", + "in": "path", + "required": true + }, + { + "name": "contact_list", + "type": "integer", + "format": "int64", + "defaultValue": -1, + "description": "0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id, -1: Do not return contacts/adddesses", + "in": "query", + "required": false + } + ], + "summary": "Get properties of an order object by ref 🔐", + "description": "Return an array with order information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/ref_ext/{ref_ext}": { + "get": { + "operationId": "ordersRetrieveByRefExt", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "ref_ext", + "type": "string", + "description": "External reference of object", + "in": "path", + "required": true + }, + { + "name": "contact_list", + "type": "integer", + "format": "int64", + "defaultValue": -1, + "description": "0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id, -1: Do not return contacts/adddesses", + "in": "query", + "required": false + } + ], + "summary": "Get properties of an order object by ref_ext 🔐", + "description": "Return an array with order information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders": { + "get": { + "operationId": "listOrders", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "thirdparty_ids", + "type": "string", + "description": "Thirdparty ids to filter orders of (example '1' or '1,2,3')", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "sqlfilterlines", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(tl.fk_product:=:'17') and (tl.price:<:'250')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*", + "in": "query", + "required": false + }, + { + "name": "loadlinkedobjects", + "type": "integer", + "format": "int64", + "description": "Load also linked object", + "in": "query", + "required": false + } + ], + "summary": "List orders 🔐", + "description": "Get a list of orders", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "404": { + "description": "Not found" + }, + "503": { + "description": "Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createOrders", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "createOrdersModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createOrdersModel" + } + } + ], + "summary": "Create a sale order 🔐", + "description": "Example: { \"socid\": 2, \"date\": 1595196000, \"type\": 0, \"lines\": [{ \"fk_product\": 2, \"qty\": 1 }] }", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}/lines": { + "get": { + "operationId": "ordersRetrieveLines", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of order", + "in": "path", + "required": true + } + ], + "summary": "Get lines of an order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "ordersCreateLine", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of order to update", + "in": "path", + "required": true + }, + { + "name": "ordersCreateLineModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/ordersCreateLineModel" + } + } + ], + "summary": "Add a line to given order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}/lines/{lineid}": { + "get": { + "operationId": "ordersRetrieveLine", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of order", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of line", + "in": "path", + "required": true + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + } + ], + "summary": "Get properties of a line of an order object by id 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "ordersUpdateLine", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of order to update", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of line to update", + "in": "path", + "required": true + }, + { + "name": "ordersUpdateLineModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/ordersUpdateLineModel" + } + } + ], + "summary": "Update a line to given order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "ordersRemoveLine", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of order to update", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of line to delete", + "in": "path", + "required": true + } + ], + "summary": "Delete a line of a given order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}/contacts": { + "get": { + "operationId": "ordersRetrieveContacts", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of order", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of the contact (BILLING, SHIPPING, CUSTOMER)", + "in": "query", + "required": false + } + ], + "summary": "Get contacts of given order 🔐", + "description": "Return an array with contact information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}/contact/{contactid}/{type}": { + "post": { + "operationId": "ordersCreateContact", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of order to update", + "in": "path", + "required": true + }, + { + "name": "contactid", + "type": "integer", + "format": "int64", + "description": "Id of contact to add", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of the contact (BILLING, SHIPPING, CUSTOMER)", + "in": "path", + "required": true + } + ], + "summary": "Add a contact type of given order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "ordersRemoveContact", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of order to update", + "in": "path", + "required": true + }, + { + "name": "contactid", + "type": "integer", + "format": "int64", + "description": "Id of contact", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of the contact (BILLING, SHIPPING, CUSTOMER).", + "in": "path", + "required": true + } + ], + "summary": "Unlink a contact type of given order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}/validate": { + "post": { + "operationId": "ordersValidate", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + }, + { + "name": "ordersValidateModel", + "description": "idwarehouse \nnotrigger \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/ordersValidateModel" + } + } + ], + "summary": "Validate an order 🔐", + "description": "If you get a bad value for param notrigger check, provide this in body { \"idwarehouse\": 0, \"notrigger\": 0 }", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "304": { + "description": "Not Modified" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}/reopen": { + "post": { + "operationId": "ordersReopen", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of the order", + "in": "path", + "required": true + } + ], + "summary": "Tag the order as validated (opened) 🔐", + "description": "Function used when order is reopend after being closed.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "304": { + "description": "Not Modified" + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}/setinvoiced": { + "post": { + "operationId": "ordersSetinvoiced", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of the order", + "in": "path", + "required": true + } + ], + "summary": "Classify the order as invoiced. Could be also called setbilled 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}/close": { + "post": { + "operationId": "ordersClose", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + }, + { + "name": "ordersCloseModel", + "description": "notrigger \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/ordersCloseModel" + } + } + ], + "summary": "Close an order (Classify it as \"Delivered\") 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}/settodraft": { + "post": { + "operationId": "ordersSettodraft", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + }, + { + "name": "ordersSettodraftModel", + "description": "idwarehouse \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/ordersSettodraftModel" + } + } + ], + "summary": "Set an order to draft 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/createfromproposal/{proposalid}": { + "post": { + "operationId": "ordersCreateOrderFromProposal", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "proposalid", + "type": "integer", + "format": "int64", + "description": "Id of the proposal", + "in": "path", + "required": true + } + ], + "summary": "Create an order using an existing proposal. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}/shipment": { + "get": { + "operationId": "ordersRetrieveOrderShipments", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of the order", + "in": "path", + "required": true + } + ], + "summary": "Get the shipments of an order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/orders/{id}/shipment/{warehouse_id}": { + "post": { + "operationId": "ordersCreateOrderShipment", + "tags": [ + "orders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of the order", + "in": "path", + "required": true + }, + { + "name": "warehouse_id", + "type": "integer", + "format": "int64", + "description": "Id of a warehouse", + "in": "path", + "required": true + } + ], + "summary": "Create the shipment of an order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}": { + "get": { + "operationId": "retrieveProducts", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of product", + "in": "path", + "required": true + }, + { + "name": "includestockdata", + "type": "integer", + "format": "int64", + "description": "Load also information about stock (slower)", + "in": "query", + "required": false + }, + { + "name": "includesubproducts", + "type": "boolean", + "description": "Load information about subproducts", + "in": "query", + "required": false + }, + { + "name": "includeparentid", + "type": "boolean", + "description": "Load also ID of parent product (if product is a variant of a parent product)", + "in": "query", + "required": false + }, + { + "name": "includetrans", + "type": "boolean", + "description": "Load also the translations of product label and description", + "in": "query", + "required": false + } + ], + "summary": "Get a product 🔐", + "description": "Return an array with product information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateProducts", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of product to update", + "in": "path", + "required": true + }, + { + "name": "updateProductsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateProductsModel" + } + } + ], + "summary": "Update a product 🔐", + "description": "Price will be updated by this API only if option is set on \"One price per product\" or if PRODUIT_MULTIPRICES is set (1 price per segment) See other APIs for other price modes.", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeProducts", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Product ID", + "in": "path", + "required": true + } + ], + "summary": "Delete a product 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/ref/{ref}": { + "get": { + "operationId": "productsRetrieveByRef", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "ref", + "type": "string", + "description": "Ref of element", + "in": "path", + "required": true + }, + { + "name": "includestockdata", + "type": "integer", + "format": "int64", + "description": "Load also information about stock (slower)", + "in": "query", + "required": false + }, + { + "name": "includesubproducts", + "type": "boolean", + "description": "Load information about subproducts", + "in": "query", + "required": false + }, + { + "name": "includeparentid", + "type": "boolean", + "description": "Load also ID of parent product (if product is a variant of a parent product)", + "in": "query", + "required": false + }, + { + "name": "includetrans", + "type": "boolean", + "description": "Load also the translations of product label and description", + "in": "query", + "required": false + } + ], + "summary": "Get product by ref 🔐", + "description": "Return an array with product information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/ref_ext/{ref_ext}": { + "get": { + "operationId": "productsRetrieveByRefExt", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "ref_ext", + "type": "string", + "description": "Ref_ext of element", + "in": "path", + "required": true + }, + { + "name": "includestockdata", + "type": "integer", + "format": "int64", + "description": "Load also information about stock (slower)", + "in": "query", + "required": false + }, + { + "name": "includesubproducts", + "type": "boolean", + "description": "Load information about subproducts", + "in": "query", + "required": false + }, + { + "name": "includeparentid", + "type": "boolean", + "description": "Load also ID of parent product (if product is a variant of a parent product)", + "in": "query", + "required": false + }, + { + "name": "includetrans", + "type": "boolean", + "description": "Load also the translations of product label and description", + "in": "query", + "required": false + } + ], + "summary": "Get product by ref_ext 🔐", + "description": "Return an array with product information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/barcode/{barcode}": { + "get": { + "operationId": "productsRetrieveByBarcode", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "barcode", + "type": "string", + "description": "Barcode of element", + "in": "path", + "required": true + }, + { + "name": "includestockdata", + "type": "integer", + "format": "int64", + "description": "Load also information about stock (slower)", + "in": "query", + "required": false + }, + { + "name": "includesubproducts", + "type": "boolean", + "description": "Load information about subproducts", + "in": "query", + "required": false + }, + { + "name": "includeparentid", + "type": "boolean", + "description": "Load also ID of parent product (if product is a variant of a parent product)", + "in": "query", + "required": false + }, + { + "name": "includetrans", + "type": "boolean", + "description": "Load also the translations of product label and description", + "in": "query", + "required": false + } + ], + "summary": "Get product by barcode 🔐", + "description": "Return an array with product information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products": { + "get": { + "operationId": "listProducts", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.ref", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "mode", + "type": "integer", + "format": "int64", + "description": "Use this param to filter list (0 for all, 1 for only product, 2 for only service)", + "in": "query", + "required": false + }, + { + "name": "category", + "type": "integer", + "format": "int64", + "description": "Use this param to filter list by category", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.tobuy:=:0) and (t.tosell:=:1)\"", + "in": "query", + "required": false + }, + { + "name": "ids_only", + "type": "boolean", + "description": "Return only IDs of product instead of all properties (faster, above all if list is long)", + "in": "query", + "required": false + }, + { + "name": "variant_filter", + "type": "integer", + "format": "int64", + "description": "Use this param to filter list (0 = all, 1=products without variants, 2=parent of variants, 3=variants only)", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0", + "in": "query", + "required": false + }, + { + "name": "includestockdata", + "type": "integer", + "format": "int64", + "description": "Load also information about stock (slower)", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + } + ], + "summary": "List products 🔐", + "description": "Get a list of products", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createProducts", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "createProductsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createProductsModel" + } + } + ], + "summary": "Create a product 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}/subproducts": { + "get": { + "operationId": "productsRetrieveSubproducts", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of parent product/service", + "in": "path", + "required": true + } + ], + "summary": "Get the list of subproducts of a product 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}/subproducts/add": { + "post": { + "operationId": "productsAddSubproducts", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of parent product/service", + "in": "path", + "required": true + }, + { + "name": "productsAddSubproductsModel", + "description": "**subproduct_id** (required) \n**qty** (required) \nincdec \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/productsAddSubproductsModel" + } + } + ], + "summary": "Add a subproduct 🔐", + "description": "Link a product/service to a parent product/service", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "RestException" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}/subproducts/remove/{subproduct_id}": { + "delete": { + "operationId": "productsDelSubproducts", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of parent product/service", + "in": "path", + "required": true + }, + { + "name": "subproduct_id", + "type": "integer", + "format": "int64", + "description": "ID of child product/service", + "in": "path", + "required": true + } + ], + "summary": "Remove a subproduct 🔐", + "description": "Unlink a product/service from a parent product/service", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}/categories": { + "get": { + "operationId": "productsRetrieveCategories", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of product", + "in": "path", + "required": true + }, + { + "name": "sortfield", + "type": "string", + "defaultValue": "s.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + } + ], + "summary": "Get categories for a product 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}/selling_multiprices/per_segment": { + "get": { + "operationId": "productsRetrieveCustomerPricesPerSegment", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of product", + "in": "path", + "required": true + } + ], + "summary": "Get prices per segment for a product 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}/selling_multiprices/per_customer": { + "get": { + "operationId": "productsRetrieveCustomerPricesPerCustomer", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of product", + "in": "path", + "required": true + }, + { + "name": "thirdparty_id", + "type": "string", + "description": "Thirdparty id to filter orders of (example '1')", + "in": "query", + "required": false + } + ], + "summary": "Get prices per customer for a product 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}/selling_multiprices/per_quantity": { + "get": { + "operationId": "productsRetrieveCustomerPricesPerQuantity", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of product", + "in": "path", + "required": true + } + ], + "summary": "Get prices per quantity for a product 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}/purchase_prices": { + "post": { + "operationId": "productsAddPurchasePrice", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Product", + "in": "path", + "required": true + }, + { + "name": "productsAddPurchasePriceModel", + "description": "**qty** (required) \n**buyprice** (required) \n**price_base_type** (required) \n**fourn_id** (required) \n**availability** (required) \n**ref_fourn** (required) \n**tva_tx** (required) \ncharges \nremise_percent \nremise \nnewnpr \ndelivery_time_days \nsupplier_reputation \nlocaltaxes_array \nnewdefaultvatcode \nmulticurrency_buyprice \nmulticurrency_price_base_type \nmulticurrency_tx \nmulticurrency_code \ndesc_fourn \nbarcode \nfk_barcode_type \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/productsAddPurchasePriceModel" + } + } + ], + "summary": "Add/Update purchase prices for a product 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "get": { + "operationId": "productsRetrievePurchasePrices", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of product", + "in": "path", + "required": true + }, + { + "name": "ref", + "type": "string", + "description": "Ref of element", + "in": "query", + "required": false + }, + { + "name": "ref_ext", + "type": "string", + "description": "Ref ext of element", + "in": "query", + "required": false + }, + { + "name": "barcode", + "type": "string", + "description": "Barcode of element", + "in": "query", + "required": false + } + ], + "summary": "Get purchase prices for a product 🔐", + "description": "Return an array with product information. TODO implement getting a product by ref or by $ref_ext", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}/purchase_prices/{priceid}": { + "delete": { + "operationId": "productsRemovePurchasePrice", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Product ID", + "in": "path", + "required": true + }, + { + "name": "priceid", + "type": "integer", + "format": "int64", + "description": "purchase price ID", + "in": "path", + "required": true + } + ], + "summary": "Delete a purchase price for a product 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/purchase_prices": { + "get": { + "operationId": "productsRetrieveSupplierProducts", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.ref", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "mode", + "type": "integer", + "format": "int64", + "description": "Use this param to filter list (0 for all, 1 for only product, 2 for only service)", + "in": "query", + "required": false + }, + { + "name": "category", + "type": "integer", + "format": "int64", + "description": "Use this param to filter list by category of product", + "in": "query", + "required": false + }, + { + "name": "supplier", + "type": "integer", + "format": "int64", + "description": "Use this param to filter list by supplier", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.tobuy:=:0) and (t.tosell:=:1)\"", + "in": "query", + "required": false + } + ], + "summary": "Get a list of all purchase prices of products 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/attributes": { + "get": { + "operationId": "productsRetrieveAttributes", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.ref", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:color)\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + } + ], + "summary": "Get attributes 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "503": { + "description": "Service Unavailable" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "productsAddAttributes", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "productsAddAttributesModel", + "description": "**ref** (required) \n**label** (required) \nref_ext \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/productsAddAttributesModel" + } + } + ], + "summary": "Add attributes 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/attributes/{id}": { + "get": { + "operationId": "productsRetrieveAttributeById", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Attribute", + "in": "path", + "required": true + } + ], + "summary": "Get attribute by ID 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "productsUpdateAttributes", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Attribute", + "in": "path", + "required": true + }, + { + "name": "productsUpdateAttributesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/productsUpdateAttributesModel" + } + } + ], + "summary": "Update attributes by ID 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "productsRemoveAttributes", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Attribute", + "in": "path", + "required": true + } + ], + "summary": "Delete attributes by ID 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/attributes/ref/{ref}": { + "get": { + "operationId": "productsRetrieveAttributesByRef", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "ref", + "type": "string", + "description": "Reference of Attribute", + "in": "path", + "required": true + } + ], + "summary": "Get attributes by ref 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/attributes/ref_ext/{ref_ext}": { + "get": { + "operationId": "productsRetrieveAttributesByRefExt", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "ref_ext", + "type": "string", + "description": "External reference of Attribute", + "in": "path", + "required": true + } + ], + "summary": "Get attributes by ref_ext 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/attributes/values/{id}": { + "get": { + "operationId": "productsRetrieveAttributeValueById", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Attribute value", + "in": "path", + "required": true + } + ], + "summary": "Get attribute value by ID 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "productsUpdateAttributeValue", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Attribute", + "in": "path", + "required": true + }, + { + "name": "productsUpdateAttributeValueModel", + "description": "**request_data** (required) \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/productsUpdateAttributeValueModel" + } + } + ], + "summary": "Update attribute value 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "productsRemoveAttributeValueById", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Attribute value", + "in": "path", + "required": true + } + ], + "summary": "Delete attribute value by ID 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/attributes/{id}/values/ref/{ref}": { + "get": { + "operationId": "productsRetrieveAttributeValueByRef", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Attribute value", + "in": "path", + "required": true + }, + { + "name": "ref", + "type": "string", + "description": "Ref of Attribute value", + "in": "path", + "required": true + } + ], + "summary": "Get attribute value by ref 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "productsRemoveAttributeValueByRef", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Attribute", + "in": "path", + "required": true + }, + { + "name": "ref", + "type": "string", + "description": "Ref of Attribute value", + "in": "path", + "required": true + } + ], + "summary": "Delete attribute value by ref 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/attributes/{id}/values": { + "get": { + "operationId": "productsRetrieveAttributeValues", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of an Attribute", + "in": "path", + "required": true + } + ], + "summary": "Get all values for an attribute ID 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "productsAddAttributeValue", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Attribute", + "in": "path", + "required": true + }, + { + "name": "productsAddAttributeValueModel", + "description": "**ref** (required) \n**value** (required) \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/productsAddAttributeValueModel" + } + } + ], + "summary": "Add attribute value 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/attributes/ref/{ref}/values": { + "get": { + "operationId": "productsRetrieveAttributeValuesByRef", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "ref", + "type": "string", + "description": "Ref of an Attribute", + "in": "path", + "required": true + } + ], + "summary": "Get all values for an attribute ref 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}/variants": { + "get": { + "operationId": "productsRetrieveVariants", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Product", + "in": "path", + "required": true + }, + { + "name": "includestock", + "type": "integer", + "format": "int64", + "description": "Default value 0. If parameter is set to 1 the response will contain stock data of each variant", + "in": "query", + "required": false + } + ], + "summary": "Get product variants 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "productsAddVariant", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Product", + "in": "path", + "required": true + }, + { + "name": "productsAddVariantModel", + "description": "**weight_impact** (required) \n**price_impact** (required) \n**price_impact_is_percent** (required) \n**features** (required) \nreference \nref_ext \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/productsAddVariantModel" + } + } + ], + "summary": "Add variant 🔐", + "description": "\"features\" is a list of attributes pairs id_attribute=>id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...)", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/ref/{ref}/variants": { + "get": { + "operationId": "productsRetrieveVariantsByProdRef", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "ref", + "type": "string", + "description": "Ref of Product", + "in": "path", + "required": true + } + ], + "summary": "Get product variants by Product ref 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "productsAddVariantByProductRef", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "ref", + "type": "string", + "description": "Ref of Product", + "in": "path", + "required": true + }, + { + "name": "productsAddVariantByProductRefModel", + "description": "**weight_impact** (required) \n**price_impact** (required) \n**price_impact_is_percent** (required) \n**features** (required) \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/productsAddVariantByProductRefModel" + } + } + ], + "summary": "Add variant by product ref 🔐", + "description": "\"features\" is a list of attributes pairs id_attribute=>id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...)", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/variants/{id}": { + "put": { + "operationId": "productsUpdateVariant", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Variant", + "in": "path", + "required": true + }, + { + "name": "productsUpdateVariantModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/productsUpdateVariantModel" + } + } + ], + "summary": "Update product variants 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "productsRemoveVariant", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Variant", + "in": "path", + "required": true + } + ], + "summary": "Delete product variants 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "System error" + }, + "401": { + "description": "Unauthorized" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/products/{id}/stock": { + "get": { + "operationId": "productsRetrieveStock", + "tags": [ + "products" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of Product", + "in": "path", + "required": true + }, + { + "name": "selected_warehouse_id", + "type": "integer", + "format": "int64", + "description": "ID of warehouse", + "in": "query", + "required": false + } + ], + "summary": "Get stock data for a product 🔐", + "description": "Optionally with $selected_warehouse_id parameter user can get stock of a specific warehouse", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "System error" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/{id}": { + "get": { + "operationId": "retrieveProposals", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of commercial proposal", + "in": "path", + "required": true + }, + { + "name": "contact_list", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "description": "0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id", + "in": "query", + "required": false + } + ], + "summary": "Get a commercial proposal 🔐", + "description": "Return an array with commercial proposal information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateProposals", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of commercial proposal to update", + "in": "path", + "required": true + }, + { + "name": "updateProposalsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateProposalsModel" + } + } + ], + "summary": "Update a commercial proposal general fields (won't change lines of commercial proposal) 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeProposals", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Commercial proposal ID", + "in": "path", + "required": true + } + ], + "summary": "Delete a commercial proposal 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/ref/{ref}": { + "get": { + "operationId": "proposalsRetrieveByRef", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "ref", + "type": "string", + "description": "Ref of object", + "in": "path", + "required": true + }, + { + "name": "contact_list", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "description": "0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id", + "in": "query", + "required": false + } + ], + "summary": "Get a commercial proposal by ref 🔐", + "description": "Return an array with proposal information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/ref_ext/{ref_ext}": { + "get": { + "operationId": "proposalsRetrieveByRefExt", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "ref_ext", + "type": "string", + "description": "External reference of object", + "in": "path", + "required": true + }, + { + "name": "contact_list", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "description": "0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id", + "in": "query", + "required": false + } + ], + "summary": "Get a commercial proposal by ref_ext 🔐", + "description": "Return an array with proposal information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals": { + "get": { + "operationId": "listProposals", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "thirdparty_ids", + "type": "string", + "description": "Thirdparty ids to filter commercial proposals (example '1' or '1,2,3')", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.datec:<:'2016-01-01')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*", + "in": "query", + "required": false + }, + { + "name": "loadlinkedobjects", + "type": "integer", + "format": "int64", + "description": "Load also linked object", + "in": "query", + "required": false + } + ], + "summary": "List commercial proposals 🔐", + "description": "Get a list of commercial proposals", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createProposals", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "createProposalsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createProposalsModel" + } + } + ], + "summary": "Create a commercial proposal 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/{id}/lines": { + "get": { + "operationId": "proposalsRetrieveLines", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of commercial proposal", + "in": "path", + "required": true + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. d is the alias for proposal lines table, p is the alias for product table. \"Syntax example \"(p.ref:like:'SO-%') AND (d.date_start:<:'20220101')\"", + "in": "query", + "required": false + } + ], + "summary": "Get lines of a commercial proposal 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "proposalsCreateLines", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of commercial proposal to update", + "in": "path", + "required": true + }, + { + "name": "proposalsCreateLinesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/proposalsCreateLinesModel" + } + } + ], + "summary": "Add lines to a commercial proposal 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/{id}/line": { + "post": { + "operationId": "proposalsCreateLine", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of commercial proposal to update", + "in": "path", + "required": true + }, + { + "name": "proposalsCreateLineModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/proposalsCreateLineModel" + } + } + ], + "summary": "Add a line to a commercial proposal 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/{id}/lines/{lineid}": { + "put": { + "operationId": "proposalsUpdateLine", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of commercial proposal to update", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of line to update", + "in": "path", + "required": true + }, + { + "name": "proposalsUpdateLineModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/proposalsUpdateLineModel" + } + } + ], + "summary": "Update a line of a commercial proposal 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "proposalsRemoveLine", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of commercial proposal to update", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of line to delete", + "in": "path", + "required": true + } + ], + "summary": "Delete a line of a commercial proposal 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/{id}/contact/{contactid}/{type}/{source}": { + "post": { + "operationId": "proposalsCreateContact", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of commercial proposal to update", + "in": "path", + "required": true + }, + { + "name": "contactid", + "type": "integer", + "format": "int64", + "description": "Id of external or internal contact to add", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of the external contact (BILLING, SHIPPING, CUSTOMER), internal contact (SALESREPFOLL)", + "in": "path", + "required": true + }, + { + "name": "source", + "type": "string", + "defaultValue": "external", + "description": "Source of the contact (internal, external)", + "in": "path", + "required": false + } + ], + "summary": "Add (link) a contact to a commercial proposal 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/{id}/contact/{contactid}/{type}": { + "delete": { + "operationId": "proposalsRemoveContact", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of commercial proposal to update", + "in": "path", + "required": true + }, + { + "name": "contactid", + "type": "integer", + "format": "int64", + "description": "Row key of the contact in the array contact_ids.", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of the contact (BILLING, SHIPPING, CUSTOMER).", + "in": "path", + "required": true + } + ], + "summary": "Remove (unlink) a contact from commercial proposal 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/{id}/settodraft": { + "post": { + "operationId": "proposalsSettodraft", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + } + ], + "summary": "Set a commercial proposal to draft 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/{id}/validate": { + "post": { + "operationId": "proposalsValidate", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Commercial proposal ID", + "in": "path", + "required": true + }, + { + "name": "proposalsValidateModel", + "description": "notrigger \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/proposalsValidateModel" + } + } + ], + "summary": "Validate a commercial proposal 🔐", + "description": "If you get a bad value for param notrigger check that ou provide this in body { \"notrigger\": 0 }", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "304": { + "description": "Not Modified" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/{id}/close": { + "post": { + "operationId": "proposalsClose", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Commercial proposal ID", + "in": "path", + "required": true + }, + { + "name": "proposalsCloseModel", + "description": "**status** (required) \nnote_private \nnotrigger \nnote_public \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/proposalsCloseModel" + } + } + ], + "summary": "Close (accept or refuse) a commercial proposal 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/proposals/{id}/setinvoiced": { + "post": { + "operationId": "proposalsSetinvoiced", + "tags": [ + "proposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Commercial proposal ID", + "in": "path", + "required": true + } + ], + "summary": "Set a commercial proposal to billed 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/actiontriggers": { + "get": { + "operationId": "setupRetrieveListOfActionTriggers", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "elementtype", + "type": "string", + "description": "Type of element ('adherent', 'commande', 'thirdparty', 'facture', 'propal', 'product', ...)", + "in": "query", + "required": false + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the label of the type must be translated to", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.label:like:'SO-%')\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of Action Triggers. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of action triggers" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/ordering_methods": { + "get": { + "operationId": "setupRetrieveOrderingMethods", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Payment type is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "SQL criteria to filter with. Syntax example \"(t.code:=:'OrderByWWW')\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of ordering methods. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "403": { + "description": "Access denied" + }, + "503": { + "description": "Error retrieving list of ordering methods" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/ordering_origins": { + "get": { + "operationId": "setupRetrieveOrderingOrigins", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Payment type is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "SQL criteria to filter with. Syntax example \"(t.code:=:'OrderByWWW')\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of ordering origins. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "403": { + "description": "Access denied" + }, + "503": { + "description": "Error retrieving list of ordering origins" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/payment_types": { + "get": { + "operationId": "setupRetrievePaymentTypes", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Payment type is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "SQL criteria to filter with. Syntax example \"(t.code:=:'CHQ')\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of payments types. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "403": { + "description": "Access denied" + }, + "503": { + "description": "Error retrieving list of payment types" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/regions": { + "get": { + "operationId": "setupRetrieveListOfRegions", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code_region", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "country", + "type": "integer", + "format": "int64", + "description": "To filter on country", + "in": "query", + "required": false + }, + { + "name": "filter", + "type": "string", + "description": "To filter the regions by name", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of regions. 🔐", + "description": " The returned list is sorted by region ID.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error retrieving list of regions" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/regions/{id}": { + "get": { + "operationId": "setupRetrieveRegionByID", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of region", + "in": "path", + "required": true + } + ], + "summary": "Get region by ID. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "404": { + "description": "Region not found" + }, + "503": { + "description": "Error retrieving region" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/regions/byCode/{code}": { + "get": { + "operationId": "setupRetrieveRegionByCode", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "code", + "type": "string", + "description": "Code of region", + "in": "path", + "required": true + } + ], + "summary": "Get region by Code. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "404": { + "description": "Region not found" + }, + "503": { + "description": "Error when retrieving region" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/states": { + "get": { + "operationId": "setupRetrieveListOfStates", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code_departement", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "country", + "type": "integer", + "format": "int64", + "description": "To filter on country", + "in": "query", + "required": false + }, + { + "name": "filter", + "type": "string", + "description": "To filter the states by name", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of states/provinces. 🔐", + "description": " The names of the states will be translated to the given language if the $lang parameter is provided. The value of $lang must be a language code supported by Dolibarr, for example 'en_US' or 'fr_FR'. The returned list is sorted by state ID.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error retrieving list of states" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/states/{id}": { + "get": { + "operationId": "setupRetrieveStateByID", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of state", + "in": "path", + "required": true + } + ], + "summary": "Get state by ID. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "404": { + "description": "State not found" + }, + "503": { + "description": "Error retrieving state" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/states/byCode/{code}": { + "get": { + "operationId": "setupRetrieveStateByCode", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "code", + "type": "string", + "description": "Code of state", + "in": "path", + "required": true + } + ], + "summary": "Get state by Code. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "404": { + "description": "State not found" + }, + "503": { + "description": "Error retrieving state" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/countries": { + "get": { + "operationId": "setupRetrieveListOfCountries", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "filter", + "type": "string", + "description": "To filter the countries by name", + "in": "query", + "required": false + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the label of the countries must be translated to", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of countries. 🔐", + "description": " The names of the countries will be translated to the given language if the $lang parameter is provided. The value of $lang must be a language code supported by Dolibarr, for example 'en_US' or 'fr_FR'. The returned list is sorted by country ID.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error retrieving list of countries" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/countries/{id}": { + "get": { + "operationId": "setupRetrieveCountryByID", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of country", + "in": "path", + "required": true + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the name of the country must be translated to", + "in": "query", + "required": false + } + ], + "summary": "Get country by ID. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "404": { + "description": "Country not found" + }, + "503": { + "description": "Error retrieving country" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/countries/byCode/{code}": { + "get": { + "operationId": "setupRetrieveCountryByCode", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "code", + "type": "string", + "description": "Code of country (2 characters)", + "in": "path", + "required": true + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the name of the country must be translated to", + "in": "query", + "required": false + } + ], + "summary": "Get country by Code. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "404": { + "description": "Country not found" + }, + "503": { + "description": "Error retrieving country" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/countries/byISO/{iso}": { + "get": { + "operationId": "setupRetrieveCountryByISO", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "iso", + "type": "string", + "description": "ISO of country (3 characters)", + "in": "path", + "required": true + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the name of the country must be translated to", + "in": "query", + "required": false + } + ], + "summary": "Get country by Iso. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "404": { + "description": "Country not found" + }, + "503": { + "description": "Error retrieving country" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/availability": { + "get": { + "operationId": "setupRetrieveAvailability", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Delivery times is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "SQL criteria to filter with.", + "in": "query", + "required": false + } + ], + "summary": "Get the list of delivery times. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "403": { + "description": "Access denied" + }, + "503": { + "description": "Error when retrieving list of availabilities" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/event_types": { + "get": { + "operationId": "setupRetrieveListOfEventTypes", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "type", + "type": "string", + "description": "To filter on type of event", + "in": "query", + "required": false + }, + { + "name": "module", + "type": "string", + "description": "To filter on module events", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Event's type is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of events types. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of events types" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/expensereport_types": { + "get": { + "operationId": "setupRetrieveListOfExpenseReportsTypes", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "module", + "type": "string", + "description": "To filter on module", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Event's type is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of Expense Report types. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of expense report types" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/contact_types": { + "get": { + "operationId": "setupRetrieveListOfContactTypes", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "type", + "type": "string", + "description": "To filter on type of contact", + "in": "query", + "required": false + }, + { + "name": "module", + "type": "string", + "description": "To filter on module contacts", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Contact's type is active or not", + "in": "query", + "required": false + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the label of the civility must be translated to", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of contacts types. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of contacts types" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/civilities": { + "get": { + "operationId": "setupRetrieveListOfCivilities", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "module", + "type": "string", + "description": "To filter on module events", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Civility is active or not", + "in": "query", + "required": false + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the label of the civility must be translated to", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of civilities. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of civilities" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/currencies": { + "get": { + "operationId": "setupRetrieveListOfCurrencies", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "multicurrency", + "type": "integer", + "format": "int64", + "maximum": 2, + "description": "Multicurrency rates (0: no multicurrency, 1: last rate, 2: all rates)", + "in": "query", + "required": false + }, + { + "name": "sortfield", + "type": "string", + "defaultValue": "code_iso", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Payment term is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of currencies. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of currencies" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/extrafields": { + "get": { + "operationId": "setupRetrieveListOfExtrafields", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.pos", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "elementtype", + "type": "string", + "description": "Type of element ('adherent', 'commande', 'thirdparty', 'facture', 'propal', 'product', ...)", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.label:like:'SO-%')\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of extra fields. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of extra fields" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/extrafields/{elementtype}/{attrname}": { + "delete": { + "operationId": "setupRemoveExtrafieldsFromNames", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "attrname", + "type": "string", + "description": "extrafield attrname", + "in": "path", + "required": true + }, + { + "name": "elementtype", + "type": "string", + "description": "extrafield elementtype", + "in": "path", + "required": true + } + ], + "summary": "Delete extrafield 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "get": { + "operationId": "setupRetrieveExtrafields", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "attrname", + "type": "string", + "description": "extrafield attrname", + "in": "path", + "required": true + }, + { + "name": "elementtype", + "type": "string", + "description": "extrafield elementtype", + "in": "path", + "required": true + } + ], + "summary": " 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "setupCreateExtrafields", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "attrname", + "type": "string", + "description": "extrafield attrname", + "in": "path", + "required": true + }, + { + "name": "elementtype", + "type": "string", + "description": "extrafield elementtype", + "in": "path", + "required": true + }, + { + "name": "setupCreateExtrafieldsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/setupCreateExtrafieldsModel" + } + } + ], + "summary": "Create Extrafield object 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "setupUpdateExtrafields", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "attrname", + "type": "string", + "description": "extrafield attrname", + "in": "path", + "required": true + }, + { + "name": "elementtype", + "type": "string", + "description": "extrafield elementtype", + "in": "path", + "required": true + }, + { + "name": "setupUpdateExtrafieldsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/setupUpdateExtrafieldsModel" + } + } + ], + "summary": "Update Extrafield object 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/towns": { + "get": { + "operationId": "setupRetrieveListOfTowns", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "zip,town", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "zipcode", + "type": "string", + "description": "To filter on zipcode", + "in": "query", + "required": false + }, + { + "name": "town", + "type": "string", + "description": "To filter on city name", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Town is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of towns. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of towns" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/payment_terms": { + "get": { + "operationId": "setupRetrievePaymentTerms", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "sortorder", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Payment term is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "SQL criteria to filter. Syntax example \"(t.code:=:'CHQ')\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of payments terms. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "403": { + "description": "Access denied" + }, + "503": { + "description": "Error when retrieving list of payments terms" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/shipping_methods": { + "get": { + "operationId": "setupRetrieveShippingModes", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Shipping methodsm is active or not", + "in": "query", + "required": false + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the label of the method must be translated to", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "SQL criteria to filter. Syntax example \"(t.code:=:'CHQ')\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of shipping methods. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of shipping modes" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/units": { + "get": { + "operationId": "setupRetrieveListOfMeasuringUnits", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Measuring unit is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of measuring units. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of measuring units" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/legal_form": { + "get": { + "operationId": "setupRetrieveListOfLegalForm", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "country", + "type": "integer", + "format": "int64", + "description": "To filter on country", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Lega form is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of legal form of business. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of legal form" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/staff": { + "get": { + "operationId": "setupRetrieveListOfStaff", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "id", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Staff is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of staff. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of staff" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/socialnetworks": { + "get": { + "operationId": "setupRetrieveListOfsocialNetworks", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Social network is active or not", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of social networks. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of social networks" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/ticket_categories": { + "get": { + "operationId": "setupRetrieveTicketsCategories", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Payment term is active or not", + "in": "query", + "required": false + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the label of the category must be translated to", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of tickets categories. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of tickets categories" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/ticket_severities": { + "get": { + "operationId": "setupRetrieveTicketsSeverities", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Payment term is active or not", + "in": "query", + "required": false + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the label of the severity must be translated to", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of tickets severity. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of tickets severities" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/ticket_types": { + "get": { + "operationId": "setupRetrieveTicketsTypes", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Payment term is active or not", + "in": "query", + "required": false + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the label of the type must be translated to", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of tickets types. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad value for sqlfilters" + }, + "503": { + "description": "Error when retrieving list of tickets types" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/dictionary/incoterms": { + "get": { + "operationId": "setupRetrieveListOfIncoterms", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "code", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Number of items per page", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number (starting from zero)", + "in": "query", + "required": false + }, + { + "name": "active", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "maximum": 1, + "description": "Payment term is active or not", + "in": "query", + "required": false + }, + { + "name": "lang", + "type": "string", + "description": "Code of the language the label of the type must be translated to", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.code:like:'A%') and (t.active:>=:0)\"", + "in": "query", + "required": false + } + ], + "summary": "Get the list of incoterms. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "503": { + "description": "Error when retrieving list of incoterms types" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/company": { + "get": { + "operationId": "setupRetrieveCompany", + "tags": [ + "setup" + ], + "parameters": [], + "summary": "Get properties of company 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/establishments": { + "get": { + "operationId": "setupRetrieveEstablishments", + "tags": [ + "setup" + ], + "parameters": [], + "summary": "Get the list of establishments. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "503": { + "description": "Error when retrieving list of establishments" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/establishments/{id}": { + "get": { + "operationId": "setupRetrieveEtablishmentByID", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of establishment", + "in": "path", + "required": true + } + ], + "summary": "Get establishment by ID. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "404": { + "description": "Establishment not found" + }, + "503": { + "description": "Error when retrieving establishment" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/conf/{constantname}": { + "get": { + "operationId": "setupRetrieveConf", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "constantname", + "type": "string", + "description": "Name of conf variable to get", + "in": "path", + "required": true + } + ], + "summary": "Get value of a setup variables 🔐", + "description": "Note that conf variables that stores security key or password hashes can't be loaded with API.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Error Bad or unknown value for constantname" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/conf": { + "get": { + "operationId": "setupRetrieveConfs", + "tags": [ + "setup" + ], + "parameters": [], + "summary": "Get all setup variables 🔐", + "description": "Note that conf variables that stores security key or password hashes can't be loaded with API.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Error Bad or unknown value for constantname" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/checkintegrity": { + "get": { + "operationId": "setupRetrieveCheckIntegrity", + "tags": [ + "setup" + ], + "parameters": [ + { + "name": "target", + "type": "string", + "description": "Can be 'local' or 'default' or Url of the signatures file to use for the test. Must be reachable by the tested Dolibarr.", + "in": "query", + "required": true + } + ], + "summary": "Do a test of integrity for files and setup. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Signature file not found" + }, + "500": { + "description": "Technical error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/setup/modules": { + "get": { + "operationId": "setupRetrieveModules", + "tags": [ + "setup" + ], + "parameters": [], + "summary": "Get list of enabled modules 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/status": { + "get": { + "operationId": "listStatus", + "tags": [ + "status" + ], + "parameters": [], + "summary": "Get status (Dolibarr version) 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierinvoices/{id}": { + "get": { + "operationId": "retrieveSupplierinvoices", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of supplier invoice", + "in": "path", + "required": true + } + ], + "summary": "Get properties of a supplier invoice object 🔐", + "description": "Return an array with supplier invoice information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "404" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateSupplierinvoices", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of supplier invoice to update", + "in": "path", + "required": true + }, + { + "name": "updateSupplierinvoicesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateSupplierinvoicesModel" + } + } + ], + "summary": "Update supplier invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeSupplierinvoices", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Supplier invoice ID", + "in": "path", + "required": true + } + ], + "summary": "Delete supplier invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierinvoices": { + "get": { + "operationId": "listSupplierinvoices", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "thirdparty_ids", + "type": "string", + "description": "Thirdparty ids to filter invoices of (example '1' or '1,2,3')", + "in": "query", + "required": false + }, + { + "name": "status", + "type": "string", + "description": "Filter by invoice status : draft | unpaid | paid | cancelled", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.datec:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*", + "in": "query", + "required": false + } + ], + "summary": "List invoices 🔐", + "description": "Get a list of supplier invoices", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createSupplierinvoices", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "createSupplierinvoicesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createSupplierinvoicesModel" + } + } + ], + "summary": "Create supplier invoice object 🔐", + "description": "Note: soc_id = dolibarr_order_id Example: {'ref': 'auto', 'ref_supplier': '7985630', 'socid': 1, 'note': 'Inserted with Python', 'order_supplier': 1, 'date': '2021-07-28'}", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "403": { + "description": "Forbidden" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierinvoices/{id}/validate": { + "post": { + "operationId": "supplierinvoicesValidate", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Invoice ID", + "in": "path", + "required": true + }, + { + "name": "supplierinvoicesValidateModel", + "description": "idwarehouse \nnotrigger \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/supplierinvoicesValidateModel" + } + } + ], + "summary": "Validate an invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "304": { + "description": "Not Modified" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierinvoices/{id}/settodraft": { + "post": { + "operationId": "supplierinvoicesSettodraft", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of supplier invoice", + "in": "path", + "required": true + }, + { + "name": "supplierinvoicesSettodraftModel", + "description": "idwarehouse \nnotrigger \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/supplierinvoicesSettodraftModel" + } + } + ], + "summary": "Sets an invoice as draft 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "304": { + "description": "Not Modified" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierinvoices/{id}/payments": { + "get": { + "operationId": "supplierinvoicesRetrievePayments", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of SupplierInvoice", + "in": "path", + "required": true + } + ], + "summary": "Get list of payments of a given supplier invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "supplierinvoicesAddPayment", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of invoice", + "in": "path", + "required": true + }, + { + "name": "supplierinvoicesAddPaymentModel", + "description": "**datepaye** (required) \n**payment_mode_id** (required) \n**closepaidinvoices** (required) \n**accountid** (required) \nnum_payment \ncomment \nchqemetteur \nchqbank \namount \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/supplierinvoicesAddPaymentModel" + } + } + ], + "summary": "Add payment line to a specific supplier invoice with the remain to pay as amount. 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "400": { + "description": "Bad Request" + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierinvoices/{id}/lines": { + "get": { + "operationId": "supplierinvoicesRetrieveLines", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of supplier invoice", + "in": "path", + "required": true + } + ], + "summary": "Get lines of a supplier invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "supplierinvoicesCreateLine", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of supplier invoice to update", + "in": "path", + "required": true + }, + { + "name": "supplierinvoicesCreateLineModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/supplierinvoicesCreateLineModel" + } + } + ], + "summary": "Add a line to given supplier invoice 🔐", + "description": "Note: socid = dolibarr_order_id, pu_ht = net price, remise = discount Example: {'socid': 1, 'qty': 1, 'pu_ht': 21.0, 'tva_tx': 25.0, 'fk_product': '1189', 'product_type': 0, 'remise_percent': 1.0, 'vat_src_code': None}", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Forbidden" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierinvoices/{id}/lines/{lineid}": { + "put": { + "operationId": "supplierinvoicesUpdateLine", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of supplier invoice to update", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of line to update", + "in": "path", + "required": true + }, + { + "name": "supplierinvoicesUpdateLineModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/supplierinvoicesUpdateLineModel" + } + } + ], + "summary": "Update a line to a given supplier invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Not allowed" + }, + "404": { + "description": "Not found" + }, + "304": { + "description": "Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "supplierinvoicesRemoveLine", + "tags": [ + "supplierinvoices" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of supplier invoice", + "in": "path", + "required": true + }, + { + "name": "lineid", + "type": "integer", + "format": "int64", + "description": "Id of the line to delete", + "in": "path", + "required": true + } + ], + "summary": "Deletes a line of a given supplier invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad parameters" + }, + "403": { + "description": "Not allowed" + }, + "404": { + "description": "Not found" + }, + "405": { + "description": "Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierorders/{id}": { + "get": { + "operationId": "retrieveSupplierorders", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of supplier order", + "in": "path", + "required": true + } + ], + "summary": "Get properties of a supplier order object 🔐", + "description": "Return an array with supplier order information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateSupplierorders", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of supplier order to update", + "in": "path", + "required": true + }, + { + "name": "updateSupplierordersModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateSupplierordersModel" + } + } + ], + "summary": "Update supplier order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeSupplierorders", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Supplier order ID", + "in": "path", + "required": true + } + ], + "summary": "Delete supplier order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierorders": { + "get": { + "operationId": "listSupplierorders", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "thirdparty_ids", + "type": "string", + "description": "Thirdparty ids to filter orders of (example '1' or '1,2,3')", + "in": "query", + "required": false + }, + { + "name": "product_ids", + "type": "string", + "description": "Product ids to filter orders of (example '1' or '1,2,3')", + "in": "query", + "required": false + }, + { + "name": "status", + "type": "string", + "description": "Filter by order status : draft | validated | approved | running | received_start | received_end | cancelled | refused", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.datec:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "sqlfilterlines", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(tl.fk_product:=:'17') and (tl.price:<:'250')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*", + "in": "query", + "required": false + } + ], + "summary": "List orders 🔐", + "description": "Get a list of supplier orders", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createSupplierorders", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "createSupplierordersModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createSupplierordersModel" + } + } + ], + "summary": "Create supplier order object 🔐", + "description": "Example: {\"ref\": \"auto\", \"ref_supplier\": \"1234\", \"socid\": \"1\", \"multicurrency_code\": \"SEK\", \"multicurrency_tx\": 1, \"tva_tx\": 25, \"note\": \"Imported via the REST API\"}", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierorders/{id}/contacts": { + "get": { + "operationId": "supplierordersRetrieveContacts", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of supplier order", + "in": "path", + "required": true + }, + { + "name": "source", + "type": "string", + "description": "Source of the contact (internal, external, all).", + "in": "query", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of the contact (BILLING, SHIPPING, CUSTOMER, SALESREPFOLL, ...)", + "in": "query", + "required": false + } + ], + "summary": "Get contacts of given supplier order 🔐", + "description": "Return an array with contact information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierorders/{id}/contact/{contactid}/{type}/{source}": { + "post": { + "operationId": "supplierordersCreateContact", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of supplier order to update", + "in": "path", + "required": true + }, + { + "name": "contactid", + "type": "integer", + "format": "int64", + "description": "Id of contact/user to add", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of the contact (BILLING, SHIPPING, CUSTOMER, SALESREPFOLL, ...)", + "in": "path", + "required": true + }, + { + "name": "source", + "type": "string", + "description": "Source of the contact (external, internal)", + "in": "path", + "required": true + } + ], + "summary": "Add a contact type of given supplier order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "supplierordersRemoveContact", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of supplier order to update", + "in": "path", + "required": true + }, + { + "name": "contactid", + "type": "integer", + "format": "int64", + "description": "Id of contact/user to add", + "in": "path", + "required": true + }, + { + "name": "type", + "type": "string", + "description": "Type of the contact (BILLING, SHIPPING, CUSTOMER, SALESREPFOLL, ...).", + "in": "path", + "required": true + }, + { + "name": "source", + "type": "string", + "description": "Source of the contact (internal, external).", + "in": "path", + "required": true + } + ], + "summary": "Unlink a contact type of given supplier order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierorders/{id}/validate": { + "post": { + "operationId": "supplierordersValidate", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + }, + { + "name": "supplierordersValidateModel", + "description": "idwarehouse \nnotrigger \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/supplierordersValidateModel" + } + } + ], + "summary": "Validate an order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierorders/{id}/approve": { + "post": { + "operationId": "supplierordersApprove", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + }, + { + "name": "supplierordersApproveModel", + "description": "idwarehouse \nsecondlevel \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/supplierordersApproveModel" + } + } + ], + "summary": "Approve an order 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierorders/{id}/makeorder": { + "post": { + "operationId": "supplierordersMakeOrder", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + }, + { + "name": "supplierordersMakeOrderModel", + "description": "**date** (required) \n**method** (required) \ncomment \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/supplierordersMakeOrderModel" + } + } + ], + "summary": "Sends an order to the vendor 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierorders/{id}/receive": { + "post": { + "operationId": "supplierordersReceiveOrder", + "tags": [ + "supplierorders" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Order ID", + "in": "path", + "required": true + }, + { + "name": "supplierordersReceiveOrderModel", + "description": "**closeopenorder** (required) \n**comment** (required) \n**lines** (required) \n", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/supplierordersReceiveOrderModel" + } + } + ], + "summary": "Receives the order, dispatches products. 🔐", + "description": " Example: { \"closeopenorder\": 1, \"comment\": \"\", \"lines\": [{ \"id\": 14, \"fk_product\": 112, \"qty\": 18, \"warehouse\": 1, \"price\": 114, \"comment\": \"\", \"eatby\": 0, \"sellby\": 0, \"batch\": 0, \"notrigger\": 0 }] }", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierproposals/{id}": { + "delete": { + "operationId": "removeSupplierproposals", + "tags": [ + "supplierproposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Supplier proposal ID", + "in": "path", + "required": true + } + ], + "summary": "Delete commercial proposal 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "get": { + "operationId": "retrieveSupplierproposals", + "tags": [ + "supplierproposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of supplier proposal", + "in": "path", + "required": true + } + ], + "summary": "Get properties of a supplier proposal (price request) object 🔐", + "description": "Return an array with supplier proposal information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateSupplierproposals", + "tags": [ + "supplierproposals" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of supplier proposal to update", + "in": "path", + "required": true + }, + { + "name": "updateSupplierproposalsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateSupplierproposalsModel" + } + } + ], + "summary": "Update supplier proposal general fields (won't touch lines of supplier proposal) 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/supplierproposals": { + "post": { + "operationId": "createSupplierproposals", + "tags": [ + "supplierproposals" + ], + "parameters": [ + { + "name": "createSupplierproposalsModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createSupplierproposalsModel" + } + } + ], + "summary": "Create supplier proposal (price request) object 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "get": { + "operationId": "listSupplierproposals", + "tags": [ + "supplierproposals" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "thirdparty_ids", + "type": "string", + "description": "Thirdparty ids to filter supplier proposals (example '1' or '1,2,3')", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.datec:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*", + "in": "query", + "required": false + } + ], + "summary": "List supplier proposals 🔐", + "description": "Get a list of supplier proposals", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}": { + "get": { + "operationId": "retrieveThirdparties", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party to load", + "in": "path", + "required": true + } + ], + "summary": "Get a third party 🔐", + "description": "Return the third party object", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateThirdparties", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of thirdparty to update", + "in": "path", + "required": true + }, + { + "name": "updateThirdpartiesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateThirdpartiesModel" + } + } + ], + "summary": "Update third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "500": { + "description": "Internal Server Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeThirdparties", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + } + ], + "summary": "Delete a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/email/{email}": { + "get": { + "operationId": "thirdpartiesRetrieveByEmail", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "email", + "type": "string", + "description": "Email of the third party to load", + "in": "path", + "required": true + } + ], + "summary": "Get properties of a third party by email. 🔐", + "description": " Return an array with third party information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/barcode/{barcode}": { + "get": { + "operationId": "thirdpartiesRetrieveByBarcode", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "barcode", + "type": "string", + "description": "Barcode of the third party", + "in": "path", + "required": true + } + ], + "summary": "Get a third party by barcode. 🔐", + "description": " Return an array with third party information", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties": { + "get": { + "operationId": "listThirdparties", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "S ort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "List limit", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "mode", + "type": "integer", + "format": "int64", + "description": "Set to 0 to show all third parties, Set to 1 to show only customers, 2 for prospects, 3 for neither customer or prospect, 4 for suppliers", + "in": "query", + "required": false + }, + { + "name": "category", + "type": "integer", + "format": "int64", + "description": "Use this param to filter the list by category", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"((t.nom:like:'TheCompany%') or (t.name_alias:like:'TheCompany%')) and (t.datec:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + }, + { + "name": "pagination_data", + "type": "boolean", + "description": "If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*", + "in": "query", + "required": false + } + ], + "summary": "List third parties 🔐", + "description": "Get a list of third parties", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createThirdparties", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "createThirdpartiesModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createThirdpartiesModel" + } + } + ], + "summary": "Create a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/merge/{idtodelete}": { + "put": { + "operationId": "thirdpartiesMerge", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of thirdparty to keep (the target third party)", + "in": "path", + "required": true + }, + { + "name": "idtodelete", + "type": "integer", + "format": "int64", + "description": "ID of thirdparty to remove (the third party to delete), once data has been merged into the target third party.", + "in": "path", + "required": true + } + ], + "summary": "Merge a third party into another third party 🔐", + "description": "Merge content (properties, notes) and objects (like invoices, events, orders, proposals, ...) of a third party into a target third party, then delete the merged third party. If a property has a defined value both in the third party to delete and the third party to keep, the value of the third party to delete will be ignored, the value of the target third party will remain, except for notes (content is concatenated).", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/setpricelevel/{priceLevel}": { + "put": { + "operationId": "thirdpartiesSetThirdpartyPriceLevel", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of thirdparty", + "in": "path", + "required": true + }, + { + "name": "priceLevel", + "type": "integer", + "format": "int64", + "description": "Price level to apply to thirdparty", + "in": "path", + "required": true + } + ], + "summary": "Set a new price level for the given third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "400": { + "description": "Price level out of bounds" + }, + "401": { + "description": "Access not allowed for your login" + }, + "404": { + "description": "Third party not found" + }, + "500": { + "description": "Error fetching/setting price level" + }, + "501": { + "description": "Request needs modules \"Thirdparties\" and \"Products\" and setting Multiprices activated" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/representative/{representative_id}": { + "post": { + "operationId": "thirdpartiesAddRepresentative", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "representative_id", + "type": "integer", + "format": "int64", + "description": "ID of representative", + "in": "path", + "required": true + } + ], + "summary": "Add a customer representative to a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "401": { + "description": "Access not allowed for your login" + }, + "404": { + "description": "User or Third party not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "thirdpartiesRemoveRepresentative", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "representative_id", + "type": "integer", + "format": "int64", + "description": "ID of representative", + "in": "path", + "required": true + } + ], + "summary": "Remove the link between a customer representative and a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "401": { + "description": "Access not allowed for your login" + }, + "404": { + "description": "User or Third party not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/categories": { + "get": { + "operationId": "thirdpartiesRetrieveCategories", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "sortfield", + "type": "string", + "defaultValue": "s.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "description": "List limit", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + } + ], + "summary": "Get customer categories for a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/categories/{category_id}": { + "put": { + "operationId": "thirdpartiesAddCategory", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "category_id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + } + ], + "summary": "Add a customer category to a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "thirdpartiesRemoveCategory", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "category_id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + } + ], + "summary": "Remove the link between a customer category and the third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/supplier_categories": { + "get": { + "operationId": "thirdpartiesRetrieveSupplierCategories", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "sortfield", + "type": "string", + "defaultValue": "s.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "description": "List limit", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + } + ], + "summary": "Get supplier categories for a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/supplier_categories/{category_id}": { + "put": { + "operationId": "thirdpartiesAddSupplierCategory", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "category_id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + } + ], + "summary": "Add a supplier category to a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "thirdpartiesRemoveSupplierCategory", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "category_id", + "type": "integer", + "format": "int64", + "description": "ID of category", + "in": "path", + "required": true + } + ], + "summary": "Remove the link between a category and the third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/outstandingproposals": { + "get": { + "operationId": "thirdpartiesRetrieveOutStandingProposals", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "mode", + "type": "string", + "defaultValue": "customer", + "description": "'customer' or 'supplier'", + "in": "query", + "required": false + } + ], + "summary": "Get outstanding proposals for a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/outstandingorders": { + "get": { + "operationId": "thirdpartiesRetrieveOutStandingOrder", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "mode", + "type": "string", + "defaultValue": "customer", + "description": "'customer' or 'supplier'", + "in": "query", + "required": false + } + ], + "summary": "Get outstanding orders for a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/outstandinginvoices": { + "get": { + "operationId": "thirdpartiesRetrieveOutStandingInvoices", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "mode", + "type": "string", + "defaultValue": "customer", + "description": "'customer' or 'supplier'", + "in": "query", + "required": false + } + ], + "summary": "Get outstanding invoices for a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/representatives": { + "get": { + "operationId": "thirdpartiesRetrieveSalesRepresentatives", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "mode", + "type": "integer", + "format": "int64", + "description": "0=Array with properties, 1=Array of id.", + "in": "query", + "required": false + } + ], + "summary": "Get representatives of a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/fixedamountdiscounts": { + "get": { + "operationId": "thirdpartiesRetrieveFixedAmountDiscounts", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "filter", + "type": "string", + "defaultValue": "none", + "enum": [ + "none", + "available", + "used" + ], + "description": "Filter exceptional discount. \"none\" will return every discount, \"available\" returns unapplied discounts, \"used\" returns applied discounts", + "in": "query", + "required": false + }, + { + "name": "sortfield", + "type": "string", + "defaultValue": "f.type", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + } + ], + "summary": "Get fixed amount discount of a third party 🔐", + "description": "all sources: deposit, credit note, commercial offers, etc.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "503": { + "description": "Service Unavailable" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/getinvoicesqualifiedforreplacement": { + "get": { + "operationId": "thirdpartiesRetrieveInvoicesQualifiedForReplacement", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of a third party", + "in": "path", + "required": true + } + ], + "summary": "Return invoices qualified to be replaced by another invoice 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/getinvoicesqualifiedforcreditnote": { + "get": { + "operationId": "thirdpartiesRetrieveInvoicesQualifiedForCreditNote", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of a third party", + "in": "path", + "required": true + } + ], + "summary": "Return invoices qualified to be corrected by a credit note 🔐", + "description": "Invoices matching the following rules are returned (validated + payment on process) or classified (paid completely or paid partially) + not already replaced + not already a credit note", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Not Found" + }, + "405": { + "description": "Method Not Allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/notifications": { + "get": { + "operationId": "thirdpartiesRetrieveCompanyNotification", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + } + ], + "summary": "Get company notifications for a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "thirdpartiesCreateCompanyNotification", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "thirdpartiesCreateCompanyNotificationModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/thirdpartiesCreateCompanyNotificationModel" + } + } + ], + "summary": "Create a company notification for a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/notificationsbycode/{code}": { + "post": { + "operationId": "thirdpartiesCreateCompanyNotificationByCode", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "code", + "type": "string", + "description": "Action Trigger code", + "in": "path", + "required": true + }, + { + "name": "thirdpartiesCreateCompanyNotificationByCodeModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/thirdpartiesCreateCompanyNotificationByCodeModel" + } + } + ], + "summary": "Create a company notification for a third party using action trigger code 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/notifications/{notification_id}": { + "delete": { + "operationId": "thirdpartiesRemoveCompanyNotification", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "notification_id", + "type": "integer", + "format": "int64", + "description": "ID of CompanyNotification", + "in": "path", + "required": true + } + ], + "summary": "Delete a company notification attached to a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "thirdpartiesUpdateCompanyNotification", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "notification_id", + "type": "integer", + "format": "int64", + "description": "ID of CompanyNotification", + "in": "path", + "required": true + }, + { + "name": "thirdpartiesUpdateCompanyNotificationModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/thirdpartiesUpdateCompanyNotificationModel" + } + } + ], + "summary": "Update a company notification for a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/bankaccounts": { + "get": { + "operationId": "thirdpartiesRetrieveCompanyBankAccount", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + } + ], + "summary": "Get company bank accounts of a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "thirdpartiesCreateCompanyBankAccount", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "thirdpartiesCreateCompanyBankAccountModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/thirdpartiesCreateCompanyBankAccountModel" + } + } + ], + "summary": "Create a company bank account for a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/bankaccounts/{bankaccount_id}": { + "put": { + "operationId": "thirdpartiesUpdateCompanyBankAccount", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "bankaccount_id", + "type": "integer", + "format": "int64", + "description": "ID of CompanyBankAccount", + "in": "path", + "required": true + }, + { + "name": "thirdpartiesUpdateCompanyBankAccountModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/thirdpartiesUpdateCompanyBankAccountModel" + } + } + ], + "summary": "Update a company bank account of a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "thirdpartiesRemoveCompanyBankAccount", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "bankaccount_id", + "type": "integer", + "format": "int64", + "description": "ID of CompanyBankAccount", + "in": "path", + "required": true + } + ], + "summary": "Delete a bank account attached to a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/generateBankAccountDocument/{companybankid}/{model}": { + "get": { + "operationId": "thirdpartiesGenerateBankAccountDocument", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "companybankid", + "type": "integer", + "format": "int64", + "description": "ID of company bank", + "in": "path", + "required": false + }, + { + "name": "model", + "type": "string", + "defaultValue": "sepamandate", + "description": "Model of document to generate", + "in": "path", + "required": false + } + ], + "summary": "Generate a document from a bank account record 🔐", + "description": "Like SEPA mandate", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/accounts": { + "get": { + "operationId": "thirdpartiesRetrieveSocieteAccounts", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "site", + "type": "string", + "description": "Site key", + "in": "query", + "required": false + } + ], + "summary": "Get a specific account attached to a third party 🔐", + "description": "Specify the site key", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized: User does not have permission to read thirdparties" + }, + "404": { + "description": "Not Found: Specified thirdparty ID does not belongs to an existing thirdparty" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "thirdpartiesCreateSocieteAccount", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "thirdpartiesCreateSocieteAccountModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/thirdpartiesCreateSocieteAccountModel" + } + } + ], + "summary": "Create and attach a new account to an existing third party 🔐", + "description": "Possible fields for request_data (request body) are specified in llx_societe_account table.
See Table llx_societe_account wiki page for more information

Example body payload :
{\"key_account\": \"cus_DAVkLSs1LYyYI\", \"site\": \"stripe\"}
", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized: User does not have permission to read thirdparties" + }, + "409": { + "description": "Conflict: An Account already exists for this company and site." + }, + "500": { + "description": "Internal Server Error: Error creating SocieteAccount account" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "thirdpartiesRemoveSocieteAccounts", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + } + ], + "summary": "Delete all accounts attached to a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized: User does not have permission to delete thirdparties accounts" + }, + "404": { + "description": "Not Found: Specified thirdparty ID does not belongs to an existing thirdparty" + }, + "500": { + "description": "Internal Server Error: Error deleting SocieteAccount entity" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/accounts/{site}/{key_account}": { + "get": { + "operationId": "thirdpartiesRetrieveSocieteByAccounts", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "site", + "type": "string", + "description": "Site key", + "in": "path", + "required": true + }, + { + "name": "key_account", + "type": "string", + "description": "Key of the account", + "in": "path", + "required": true + } + ], + "summary": "Get a specific third party by account 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized: User does not have permission to read thirdparties" + }, + "404": { + "description": "Not Found: Specified thirdparty ID does not belongs to an existing thirdparty" + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/thirdparties/{id}/accounts/{site}": { + "post": { + "operationId": "thirdpartiesCreateSocieteAccount", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "site", + "type": "string", + "description": "Site key", + "in": "path", + "required": true + }, + { + "name": "thirdpartiesCreateSocieteAccountModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/thirdpartiesCreateSocieteAccountModel" + } + } + ], + "summary": "Create and attach a new (or replace an existing) specific site account for a third party 🔐", + "description": "You MUST pass all values to keep (otherwise, they will be deleted) !
If you just need to update specific fields prefer PUT /thirdparties/{id}/accounts/{site} endpoint.

When a SocieteAccount entity does not exist for the id and site supplied, a new one will be created. In that case fk_soc and site members form request body payload will be ignored and id and site query strings parameters will be used instead.", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized: User does not have permission to read thirdparties" + }, + "500": { + "description": "Internal Server Error: Error updating SocieteAccount entity" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "thirdpartiesUpdateSocieteAccount", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "site", + "type": "string", + "description": "Site key", + "in": "path", + "required": true + }, + { + "name": "thirdpartiesUpdateSocieteAccountModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/thirdpartiesUpdateSocieteAccountModel" + } + } + ], + "summary": "Update specified values of a specific account attached to a third party 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized: User does not have permission to read thirdparties" + }, + "404": { + "description": "Not Found: Specified thirdparty ID does not belongs to an existing thirdparty" + }, + "409": { + "description": "Conflict: Another SocieteAccount entity already exists for this thirdparty with this site key." + }, + "500": { + "description": "Internal Server Error: Error updating SocieteAccount entity" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "thirdpartiesRemoveSocieteAccount", + "tags": [ + "thirdparties" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the third party", + "in": "path", + "required": true + }, + { + "name": "site", + "type": "string", + "description": "Site key", + "in": "path", + "required": true + } + ], + "summary": "Delete a specific site account attached to a third party 🔐", + "description": "by account id", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized: User does not have permission to delete thirdparties accounts" + }, + "404": { + "description": "Not Found: Specified thirdparty ID does not belongs to an existing thirdparty" + }, + "500": { + "description": "Internal Server Error: Error deleting SocieteAccount entity" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users": { + "get": { + "operationId": "listUsers", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "user_ids", + "type": "string", + "description": "User ids filter field. Example: '1' or '1,2,3'", + "in": "query", + "required": false + }, + { + "name": "category", + "type": "integer", + "format": "int64", + "description": "Use this param to filter list by category", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + } + ], + "summary": "List users 🔐", + "description": "Get a list of Users", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "createUsers", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "createUsersModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/createUsersModel" + } + } + ], + "summary": "Create a user 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "401": { + "description": "Not allowed" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/{id}": { + "get": { + "operationId": "retrieveUsers", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of user", + "in": "path", + "required": true + }, + { + "name": "includepermissions", + "type": "integer", + "format": "int64", + "description": "Set this to 1 to have the array of permissions loaded (not done by default for performance purpose)", + "in": "query", + "required": false + } + ], + "summary": "Get a user 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Insufficient rights" + }, + "404": { + "description": "User or group not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "updateUsers", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of account to update", + "in": "path", + "required": true + }, + { + "name": "updateUsersModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/updateUsersModel" + } + } + ], + "summary": "Update a user 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "403": { + "description": "Not allowed" + }, + "404": { + "description": "Not found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "operationId": "removeUsers", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Account ID", + "in": "path", + "required": true + } + ], + "summary": "Delete a user 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Not allowed" + }, + "404": { + "description": "User not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/login/{login}": { + "get": { + "operationId": "usersRetrieveByLogin", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "login", + "type": "string", + "description": "Login of user", + "in": "path", + "required": true + }, + { + "name": "includepermissions", + "type": "integer", + "format": "int64", + "description": "Set this to 1 to have the array of permissions loaded (not done by default for performance purpose)", + "in": "query", + "required": false + } + ], + "summary": "Get a user by login 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Insufficient rights" + }, + "404": { + "description": "User or group not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/email/{email}": { + "get": { + "operationId": "usersRetrieveByEmail", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "email", + "type": "string", + "description": "Email of user", + "in": "path", + "required": true + }, + { + "name": "includepermissions", + "type": "integer", + "format": "int64", + "description": "Set this to 1 to have the array of permissions loaded (not done by default for performance purpose)", + "in": "query", + "required": false + } + ], + "summary": "Get a user by email 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Insufficient rights" + }, + "404": { + "description": "User or group not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/info": { + "get": { + "operationId": "usersRetrieveInfo", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "includepermissions", + "type": "integer", + "format": "int64", + "description": "Set this to 1 to have the array of permissions loaded (not done by default for performance purpose)", + "in": "query", + "required": false + } + ], + "summary": "Get more properties of a user 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Insufficient rights" + }, + "404": { + "description": "User or group not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/{id}/setPassword": { + "get": { + "operationId": "usersSetPassword", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "User ID", + "in": "path", + "required": true + }, + { + "name": "send_password", + "type": "boolean", + "description": "Only if set to true, the new password will send to the user", + "in": "query", + "required": false + } + ], + "summary": "Update a user password 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "403": { + "description": "Not allowed" + }, + "404": { + "description": "User not found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/{id}/groups": { + "get": { + "operationId": "usersRetrieveGroups", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "Id of user", + "in": "path", + "required": true + } + ], + "summary": "List the groups of a user 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Not allowed" + }, + "404": { + "description": "Not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/{id}/setGroup/{group}": { + "get": { + "operationId": "usersSetGroup", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "User ID", + "in": "path", + "required": true + }, + { + "name": "group", + "type": "integer", + "format": "int64", + "description": "Group ID", + "in": "path", + "required": true + }, + { + "name": "entity", + "type": "integer", + "format": "int64", + "defaultValue": 1, + "description": "Entity ID (valid only for superadmin in multicompany transverse mode)", + "in": "query", + "required": false + } + ], + "summary": "Add a user to a group 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "403": { + "description": "Not allowed" + }, + "404": { + "description": "User not found" + }, + "500": { + "description": "System error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/groups": { + "get": { + "operationId": "usersListGroups", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "sortfield", + "type": "string", + "defaultValue": "t.rowid", + "description": "Sort field", + "in": "query", + "required": false + }, + { + "name": "sortorder", + "type": "string", + "defaultValue": "ASC", + "description": "Sort order", + "in": "query", + "required": false + }, + { + "name": "limit", + "type": "integer", + "format": "int64", + "defaultValue": 100, + "description": "Limit for list", + "in": "query", + "required": false + }, + { + "name": "page", + "type": "integer", + "format": "int64", + "description": "Page number", + "in": "query", + "required": false + }, + { + "name": "group_ids", + "type": "string", + "description": "Groups ids filter field. Example: '1' or '1,2,3'", + "in": "query", + "required": false + }, + { + "name": "sqlfilters", + "type": "string", + "description": "Other criteria to filter answers separated by a comma. Syntax example \"(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')\"", + "in": "query", + "required": false + }, + { + "name": "properties", + "type": "string", + "description": "Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names", + "in": "query", + "required": false + } + ], + "summary": "List groups 🔐", + "description": "Return an array with a list of Groups", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "403": { + "description": "Not allowed" + }, + "404": { + "description": "User not found" + }, + "503": { + "description": "Error" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/groups/{group}": { + "get": { + "operationId": "usersInfoGroups", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "group", + "type": "integer", + "format": "int64", + "description": "ID of group", + "in": "path", + "required": true + }, + { + "name": "load_members", + "type": "integer", + "format": "int64", + "maximum": 1, + "description": "Load members list or not", + "in": "query", + "required": false + } + ], + "summary": "Get properties of a user group 🔐", + "description": "Return an array with group information", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/Obj" + } + }, + "403": { + "description": "Not allowed" + }, + "404": { + "description": "User not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/{id}/notifications": { + "get": { + "operationId": "usersRetrieveUserNotification", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the user", + "in": "path", + "required": true + } + ], + "summary": "Get notifications for a user 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "operationId": "usersCreateUserNotification", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the user", + "in": "path", + "required": true + }, + { + "name": "usersCreateUserNotificationModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/usersCreateUserNotificationModel" + } + } + ], + "summary": "Create a notification for a user 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/{id}/notificationsbycode/{code}": { + "post": { + "operationId": "usersCreateUserNotificationByCode", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the user", + "in": "path", + "required": true + }, + { + "name": "code", + "type": "string", + "description": "Action Trigger code", + "in": "path", + "required": true + }, + { + "name": "usersCreateUserNotificationByCodeModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/usersCreateUserNotificationByCodeModel" + } + } + ], + "summary": "Create a notification for a user using action trigger code 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/users/{id}/notifications/{notification_id}": { + "delete": { + "operationId": "usersRemoveUserNotification", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the user", + "in": "path", + "required": true + }, + { + "name": "notification_id", + "type": "integer", + "format": "int64", + "description": "ID of UserNotification", + "in": "path", + "required": true + } + ], + "summary": "Delete a notification attached to a user 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "integer", + "format": "int64" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "put": { + "operationId": "usersUpdateUserNotification", + "tags": [ + "users" + ], + "parameters": [ + { + "name": "id", + "type": "integer", + "format": "int64", + "description": "ID of the User", + "in": "path", + "required": true + }, + { + "name": "notification_id", + "type": "integer", + "format": "int64", + "description": "ID of UserNotification", + "in": "path", + "required": true + }, + { + "name": "usersUpdateUserNotificationModel", + "description": "request_data \n", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/usersUpdateUserNotificationModel" + } + } + ], + "summary": "Update a notification for a user 🔐", + "description": "", + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "RestException" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + } + }, + "definitions": { + "createBankaccountsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "Obj": { + "properties": { + "stringEncoderFunction": { + "type": "string", + "description": "" + }, + "numberEncoderFunction": { + "type": "string", + "description": "" + }, + "fix": { + "type": "array", + "items": { + "type": "string" + }, + "description": "key value pairs for fixing value types using functions. For example 'id'=>'intval' will make sure all values of the id properties will be converted to integers intval function 'password'=> null will remove all the password entries" + }, + "separatorChar": { + "type": "string", + "description": "character that is used to identify sub objects For example when Object::$separatorChar = '.'; array('my.object'=>true) will result in array( 'my'=>array('object'=>true) );" + }, + "removeEmpty": { + "type": "boolean", + "description": "set it to true when empty arrays, blank strings, null values to be automatically removed from response" + }, + "removeNull": { + "type": "boolean", + "description": "set it to true to remove all null values from the result" + } + }, + "required": [ + "stringEncoderFunction", + "numberEncoderFunction", + "fix", + "separatorChar", + "removeEmpty", + "removeNull" + ] + }, + "updateBankaccountsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "data" + } + } + }, + "bankaccountsTransferModel": { + "properties": { + "bankaccount_from_id": { + "type": "integer", + "format": "int64", + "description": "BankAccount ID to use as the source of the internal wire transfer" + }, + "bankaccount_to_id": { + "type": "integer", + "format": "int64", + "description": "BankAccount ID to use as the destination of the internal wire transfer" + }, + "date": { + "type": "string", + "description": "Date of the internal wire transfer (UNIX timestamp)" + }, + "description": { + "type": "string", + "description": "Description of the internal wire transfer" + }, + "amount": { + "type": "number", + "format": "double", + "description": "Amount to transfer from the source to the destination BankAccount" + }, + "amount_to": { + "type": "number", + "format": "double", + "description": "Amount to transfer to the destination BankAccount (only when accounts does not share the same currency)" + }, + "cheque_number": { + "type": "string", + "description": "Cheque numero" + } + }, + "required": [ + "bankaccount_from_id", + "bankaccount_to_id", + "date", + "description", + "amount" + ] + }, + "bankaccountsAddLineModel": { + "properties": { + "date": { + "type": "string", + "description": "Payment date (timestamp)" + }, + "type": { + "type": "string", + "description": "Payment mode (TYP,VIR,PRE,LIQ,VAD,CB,CHQ...)" + }, + "label": { + "type": "string", + "description": "Label" + }, + "amount": { + "type": "number", + "format": "double", + "description": "Amount (may be 0)" + }, + "category": { + "type": "integer", + "format": "int64", + "description": "Category" + }, + "cheque_number": { + "type": "string", + "description": "Cheque numero" + }, + "cheque_writer": { + "type": "string", + "description": "Name of cheque writer" + }, + "cheque_bank": { + "type": "string", + "description": "Bank of cheque writer" + }, + "accountancycode": { + "type": "string", + "description": "Accountancy code" + }, + "datev": { + "type": "string", + "description": "Payment date value (timestamp)" + }, + "num_releve": { + "type": "string", + "description": "Bank statement numero" + } + }, + "required": [ + "date", + "type", + "label", + "amount" + ] + }, + "bankaccountsAddLinkModel": { + "properties": { + "url_id": { + "type": "integer", + "format": "int64", + "description": "ID to set in the URL" + }, + "url": { + "type": "string", + "description": "URL of the link" + }, + "label": { + "type": "string", + "description": "Label" + }, + "type": { + "type": "string", + "description": "Type of link ('payment', 'company', 'member', ...)" + } + }, + "required": [ + "url_id", + "url", + "label", + "type" + ] + }, + "bankaccountsUpdateLineModel": { + "properties": { + "label": { + "type": "string", + "description": "Label" + } + }, + "required": [ + "label" + ] + }, + "updateCategoriesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + } + }, + "createCategoriesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "updateContactsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "createContactsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "contactsCreateUserModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "updateContractsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + } + }, + "createContractsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "contractsCreateLineModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Contractline data" + } + } + }, + "contractsUpdateLineModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Contractline data" + } + } + }, + "contractsActivateLineModel": { + "properties": { + "datestart": { + "type": "string", + "description": "Date start" + }, + "dateend": { + "type": "string", + "description": "Date end" + }, + "comment": { + "type": "string", + "description": "Comment" + } + }, + "required": [ + "datestart" + ] + }, + "contractsUnactivateLineModel": { + "properties": { + "datestart": { + "type": "string", + "description": "Date start" + }, + "comment": { + "type": "string", + "description": "Comment" + } + }, + "required": [ + "datestart" + ] + }, + "contractsValidateModel": { + "properties": { + "notrigger": { + "type": "integer", + "format": "int64", + "description": "1=Does not execute triggers, 0= execute triggers" + } + } + }, + "contractsCloseModel": { + "properties": { + "notrigger": { + "type": "integer", + "format": "int64", + "description": "1=Does not execute triggers, 0= execute triggers" + } + } + }, + "documentsBuilddocModel": { + "properties": { + "modulepart": { + "type": "string", + "description": "Name of module or area concerned by file download ('thirdparty', 'member', 'proposal', 'supplier_proposal', 'order', 'supplier_order', 'invoice', 'supplier_invoice', 'shipment', 'project', ...)" + }, + "original_file": { + "type": "string", + "description": "Relative path with filename, relative to modulepart (for example: IN201701-999/IN201701-999.pdf)." + }, + "doctemplate": { + "type": "string", + "description": "Set here the doc template to use for document generation (If not set, use the default template)." + }, + "langcode": { + "type": "string", + "description": "Language code like 'en_US', 'fr_FR', 'es_ES', ... (If not set, use the default language)." + } + }, + "required": [ + "modulepart" + ] + }, + "createDocumentsModel": { + "properties": { + "filename": { + "type": "string", + "description": "Name of file to create ('FA1705-0123.txt')" + }, + "modulepart": { + "type": "string", + "description": "Name of module or area concerned by file upload ('product', 'service', 'invoice', 'proposal', 'project', 'project_task', 'supplier_invoice', 'expensereport', 'member', ...)" + }, + "ref": { + "type": "string", + "description": "Reference of object (This will define subdir automatically and store submitted file into it)" + }, + "subdir": { + "type": "string", + "description": "Subdirectory (Only if $ref is not provided)" + }, + "filecontent": { + "type": "string", + "description": "File content (string with file content. An empty file will be created if this parameter is not provided)" + }, + "fileencoding": { + "type": "string", + "description": "File encoding (''=no encoding, 'base64'=Base 64)" + }, + "overwriteifexists": { + "type": "integer", + "format": "int64", + "description": "Overwrite file if exists (1 by default)" + }, + "createdirifnotexists": { + "type": "integer", + "format": "int64", + "description": "Create subdirectories if the doesn't exists (1 by default)", + "defaultValue": 1 + }, + "position": { + "type": "integer", + "format": "int64", + "description": "Position" + }, + "cover": { + "type": "string", + "description": "Cover info" + }, + "array_options": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array for extrafields of ECM index table" + }, + "generateThumbs": { + "type": "integer", + "format": "int64", + "description": "1=Will generate the small and mini thumbs if applicable" + } + }, + "required": [ + "filename", + "modulepart" + ] + }, + "updateInvoicesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Datas" + } + } + }, + "createInvoicesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "invoicesCreateLineModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "InvoiceLine data" + } + } + }, + "invoicesUpdateLineModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "InvoiceLine data" + } + } + }, + "invoicesAddContactModel": { + "properties": { + "fk_socpeople": { + "type": "integer", + "format": "int64", + "description": "Id of thirdparty contact (if source = 'external') or id of user (if source = 'internal') to link" + }, + "type_contact": { + "type": "string", + "description": "Type of contact (code). Must a code found into table llx_c_type_contact. For example: BILLING" + }, + "source": { + "type": "string", + "description": "external=Contact extern (llx_socpeople), internal=Contact intern (llx_user)" + }, + "notrigger": { + "type": "integer", + "format": "int64", + "description": "Disable all triggers" + } + }, + "required": [ + "fk_socpeople", + "type_contact", + "source" + ] + }, + "invoicesSettodraftModel": { + "properties": { + "idwarehouse": { + "type": "integer", + "format": "int64", + "description": "Warehouse ID", + "defaultValue": -1 + } + } + }, + "invoicesValidateModel": { + "properties": { + "force_number": { + "type": "string", + "description": "force ref invoice" + }, + "idwarehouse": { + "type": "integer", + "format": "int64", + "description": "Warehouse ID" + }, + "notrigger": { + "type": "integer", + "format": "int64", + "description": "1=Does not execute triggers, 0= execute triggers" + } + } + }, + "invoicesSettopaidModel": { + "properties": { + "close_code": { + "type": "string", + "description": "Code filled if we classify to 'Paid completely' when payment is not complete (for escompte for example)" + }, + "close_note": { + "type": "string", + "description": "Comment defined if we classify to 'Paid' when payment is not complete (for escompte for example)" + } + } + }, + "invoicesAddPaymentModel": { + "properties": { + "datepaye": { + "type": "string", + "description": "Payment date" + }, + "paymentid": { + "type": "integer", + "format": "int64", + "description": "Payment mode Id", + "minimum": 1 + }, + "closepaidinvoices": { + "type": "string", + "description": "Close paid invoices", + "enum": [ + "yes", + "no" + ] + }, + "accountid": { + "type": "integer", + "format": "int64", + "description": "Account Id", + "minimum": 1 + }, + "num_payment": { + "type": "string", + "description": "Payment number (optional)" + }, + "comment": { + "type": "string", + "description": "Note private (optional)" + }, + "chqemetteur": { + "type": "string", + "description": "Payment issuer (mandatory if paymentcode = 'CHQ')" + }, + "chqbank": { + "type": "string", + "description": "Issuer bank name (optional)" + } + }, + "required": [ + "datepaye", + "paymentid", + "closepaidinvoices", + "accountid" + ] + }, + "invoicesAddPaymentDistributedModel": { + "properties": { + "arrayofamounts": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array with id of invoices with amount to pay for each invoice" + }, + "datepaye": { + "type": "string", + "description": "Payment date" + }, + "paymentid": { + "type": "integer", + "format": "int64", + "description": "Payment mode Id", + "minimum": 1 + }, + "closepaidinvoices": { + "type": "string", + "description": "Close paid invoices", + "enum": [ + "yes", + "no" + ] + }, + "accountid": { + "type": "integer", + "format": "int64", + "description": "Account Id", + "minimum": 1 + }, + "num_payment": { + "type": "string", + "description": "Payment number (optional)" + }, + "comment": { + "type": "string", + "description": "Note private (optional)" + }, + "chqemetteur": { + "type": "string", + "description": "Payment issuer (mandatory if paiementcode = 'CHQ')" + }, + "chqbank": { + "type": "string", + "description": "Issuer bank name (optional)" + }, + "ref_ext": { + "type": "string", + "description": "External reference (optional)" + }, + "accepthigherpayment": { + "type": "boolean", + "description": "Accept higher payments that it remains to be paid (optional)" + } + }, + "required": [ + "arrayofamounts", + "datepaye", + "paymentid", + "closepaidinvoices", + "accountid" + ] + }, + "invoicesUpdatePaymentModel": { + "properties": { + "num_payment": { + "type": "string", + "description": "Payment number" + } + } + }, + "listLoginModel": { + "properties": { + "login": { + "type": "string", + "description": "User login" + }, + "password": { + "type": "string", + "description": "User password" + }, + "entity": { + "type": "string", + "description": "Entity (when multicompany module is used). '' means 1=first company." + }, + "reset": { + "type": "integer", + "format": "int64", + "description": "Reset token (0=get current token, 1=ask a new token and canceled old token. This means access using current existing API token of user will fails: new token will be required for new access)" + } + }, + "required": [ + "login", + "password" + ] + }, + "createMulticurrenciesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "updateMulticurrenciesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + } + }, + "multicurrenciesUpdateRateModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "objectlinksCreateModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data, see Example above for required parameters. Currently unused is relationtype. notrigger is default 0, which means to trigger, else set notrigger: 1" + } + } + }, + "updateOrdersModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + } + }, + "createOrdersModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "ordersCreateLineModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "OrderLine data" + } + } + }, + "ordersUpdateLineModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "OrderLine data" + } + } + }, + "ordersValidateModel": { + "properties": { + "idwarehouse": { + "type": "integer", + "format": "int64", + "description": "Warehouse ID" + }, + "notrigger": { + "type": "integer", + "format": "int64", + "description": "1=Does not execute triggers, 0= execute triggers" + } + } + }, + "ordersCloseModel": { + "properties": { + "notrigger": { + "type": "integer", + "format": "int64", + "description": "Disabled triggers" + } + } + }, + "ordersSettodraftModel": { + "properties": { + "idwarehouse": { + "type": "integer", + "format": "int64", + "description": "Warehouse ID to use for stock change (Used only if option STOCK_CALCULATE_ON_VALIDATE_ORDER is on)", + "defaultValue": -1 + } + } + }, + "updateProductsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + } + }, + "createProductsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "productsAddSubproductsModel": { + "properties": { + "subproduct_id": { + "type": "integer", + "format": "int64", + "description": "ID of child product/service" + }, + "qty": { + "type": "number", + "format": "double", + "description": "Quantity" + }, + "incdec": { + "type": "integer", + "format": "int64", + "description": "1=Increase/decrease stock of child when parent stock increases/decreases", + "defaultValue": 1 + } + }, + "required": [ + "subproduct_id", + "qty" + ] + }, + "productsAddPurchasePriceModel": { + "properties": { + "qty": { + "type": "number", + "format": "double", + "description": "Min quantity for which price is valid" + }, + "buyprice": { + "type": "number", + "format": "double", + "description": "Purchase price for the quantity min" + }, + "price_base_type": { + "type": "string", + "description": "HT or TTC" + }, + "fourn_id": { + "type": "integer", + "format": "int64", + "description": "Supplier ID" + }, + "availability": { + "type": "integer", + "format": "int64", + "description": "Product availability" + }, + "ref_fourn": { + "type": "string", + "description": "Supplier ref" + }, + "tva_tx": { + "type": "number", + "format": "double", + "description": "New VAT Rate (For example 8.5. Should not be a string)" + }, + "charges": { + "type": "number", + "format": "double", + "description": "costs affering to product" + }, + "remise_percent": { + "type": "number", + "format": "double", + "description": "Discount regarding qty (percent)" + }, + "remise": { + "type": "number", + "format": "double", + "description": "Discount regarding qty (amount)" + }, + "newnpr": { + "type": "integer", + "format": "int64", + "description": "Set NPR or not" + }, + "delivery_time_days": { + "type": "integer", + "format": "int64", + "description": "Delay in days for delivery (max). May be '' if not defined." + }, + "supplier_reputation": { + "type": "string", + "description": "Reputation with this product to the defined supplier (empty, FAVORITE, DONOTORDER)" + }, + "localtaxes_array": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array with localtaxes info array('0'=>type1,'1'=>rate1,'2'=>type2,'3'=>rate2) (loaded by getLocalTaxesFromRate(vatrate, 0, ...) function)." + }, + "newdefaultvatcode": { + "type": "string", + "description": "Default vat code" + }, + "multicurrency_buyprice": { + "type": "number", + "format": "double", + "description": "Purchase price for the quantity min in currency" + }, + "multicurrency_price_base_type": { + "type": "string", + "description": "HT or TTC in currency", + "defaultValue": "HT" + }, + "multicurrency_tx": { + "type": "number", + "format": "double", + "description": "Rate currency", + "defaultValue": 1 + }, + "multicurrency_code": { + "type": "string", + "description": "Currency code" + }, + "desc_fourn": { + "type": "string", + "description": "Custom description for product_fourn_price" + }, + "barcode": { + "type": "string", + "description": "Barcode" + }, + "fk_barcode_type": { + "type": "integer", + "format": "int64", + "description": "Barcode type" + } + }, + "required": [ + "qty", + "buyprice", + "price_base_type", + "fourn_id", + "availability", + "ref_fourn", + "tva_tx" + ] + }, + "productsAddAttributesModel": { + "properties": { + "ref": { + "type": "string", + "description": "Reference of Attribute" + }, + "label": { + "type": "string", + "description": "Label of Attribute" + }, + "ref_ext": { + "type": "string", + "description": "Reference of Attribute" + } + }, + "required": [ + "ref", + "label" + ] + }, + "productsUpdateAttributesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + } + }, + "productsUpdateAttributeValueModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + }, + "required": [ + "request_data" + ] + }, + "productsAddAttributeValueModel": { + "properties": { + "ref": { + "type": "string", + "description": "Reference of Attribute value" + }, + "value": { + "type": "string", + "description": "Value of Attribute value" + } + }, + "required": [ + "ref", + "value" + ] + }, + "productsAddVariantModel": { + "properties": { + "weight_impact": { + "type": "number", + "format": "double", + "description": "Weight impact of variant" + }, + "price_impact": { + "type": "number", + "format": "double", + "description": "Price impact of variant" + }, + "price_impact_is_percent": { + "type": "boolean", + "description": "Price impact in percent (true or false)" + }, + "features": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of attributes pairs id_attribute->id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...)" + }, + "reference": { + "type": "string", + "description": "Customized reference of variant" + }, + "ref_ext": { + "type": "string", + "description": "External reference of variant" + } + }, + "required": [ + "weight_impact", + "price_impact", + "price_impact_is_percent", + "features" + ] + }, + "productsAddVariantByProductRefModel": { + "properties": { + "weight_impact": { + "type": "number", + "format": "double", + "description": "Weight impact of variant" + }, + "price_impact": { + "type": "number", + "format": "double", + "description": "Price impact of variant" + }, + "price_impact_is_percent": { + "type": "boolean", + "description": "Price impact in percent (true or false)" + }, + "features": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of attributes pairs id_attribute->id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...)" + } + }, + "required": [ + "weight_impact", + "price_impact", + "price_impact_is_percent", + "features" + ] + }, + "productsUpdateVariantModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + } + }, + "updateProposalsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Datas" + } + } + }, + "createProposalsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "proposalsCreateLinesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Commercial proposal line data" + } + } + }, + "proposalsCreateLineModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Commercial proposal line data" + } + } + }, + "proposalsUpdateLineModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Commercial proposal line data" + } + } + }, + "proposalsValidateModel": { + "properties": { + "notrigger": { + "type": "integer", + "format": "int64", + "description": "1=Does not execute triggers, 0= execute triggers" + } + } + }, + "proposalsCloseModel": { + "properties": { + "status": { + "type": "integer", + "format": "int64", + "description": "Must be 2 (accepted) or 3 (refused)", + "minimum": 2, + "maximum": 3 + }, + "note_private": { + "type": "string", + "description": "Add this mention at end of private note" + }, + "notrigger": { + "type": "integer", + "format": "int64", + "description": "Disabled triggers" + }, + "note_public": { + "type": "string", + "description": "Add this mention at end of public note" + } + }, + "required": [ + "status" + ] + }, + "setupCreateExtrafieldsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "setupUpdateExtrafieldsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "updateSupplierinvoicesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + } + }, + "createSupplierinvoicesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "supplierinvoicesValidateModel": { + "properties": { + "idwarehouse": { + "type": "integer", + "format": "int64", + "description": "Warehouse ID" + }, + "notrigger": { + "type": "integer", + "format": "int64", + "description": "1=Does not execute triggers, 0= execute triggers" + } + } + }, + "supplierinvoicesSettodraftModel": { + "properties": { + "idwarehouse": { + "type": "integer", + "format": "int64", + "description": "Warehouse ID", + "defaultValue": -1 + }, + "notrigger": { + "type": "integer", + "format": "int64", + "description": "1=Does not execute triggers, 0= execute triggers" + } + } + }, + "supplierinvoicesAddPaymentModel": { + "properties": { + "datepaye": { + "type": "string", + "description": "Payment date" + }, + "payment_mode_id": { + "type": "integer", + "format": "int64", + "description": "Payment mode ID (look it up via REST GET to /setup/dictionary/payment_types)", + "minimum": 1 + }, + "closepaidinvoices": { + "type": "string", + "description": "Close paid invoices", + "enum": [ + "yes", + "no" + ] + }, + "accountid": { + "type": "integer", + "format": "int64", + "description": "Bank account ID (look it up via REST GET to /bankaccounts)", + "minimum": 1 + }, + "num_payment": { + "type": "string", + "description": "Payment number (optional)" + }, + "comment": { + "type": "string", + "description": "Note (optional)" + }, + "chqemetteur": { + "type": "string", + "description": "Payment issuer (mandatory if payment_mode_id corresponds to 'CHQ'-payment type)" + }, + "chqbank": { + "type": "string", + "description": "Issuer bank name (optional)" + }, + "amount": { + "type": "number", + "format": "double", + "description": "Amount of payment if we don't want to use the remain to pay" + } + }, + "required": [ + "datepaye", + "payment_mode_id", + "closepaidinvoices", + "accountid" + ] + }, + "supplierinvoicesCreateLineModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "supplier invoice line data" + } + } + }, + "supplierinvoicesUpdateLineModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "InvoiceLine data" + } + } + }, + "updateSupplierordersModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + } + }, + "createSupplierordersModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "supplierordersValidateModel": { + "properties": { + "idwarehouse": { + "type": "integer", + "format": "int64", + "description": "Warehouse ID" + }, + "notrigger": { + "type": "integer", + "format": "int64", + "description": "1=Does not execute triggers, 0= execute triggers" + } + } + }, + "supplierordersApproveModel": { + "properties": { + "idwarehouse": { + "type": "integer", + "format": "int64", + "description": "Warehouse ID" + }, + "secondlevel": { + "type": "integer", + "format": "int64", + "description": "1=Does not execute triggers, 0= execute triggers" + } + } + }, + "supplierordersMakeOrderModel": { + "properties": { + "date": { + "type": "integer", + "format": "int64", + "description": "Date (unix timestamp in sec)" + }, + "method": { + "type": "integer", + "format": "int64", + "description": "Method" + }, + "comment": { + "type": "string", + "description": "Comment" + } + }, + "required": [ + "date", + "method" + ] + }, + "supplierordersReceiveOrderModel": { + "properties": { + "closeopenorder": { + "type": "integer", + "format": "int64", + "description": "Close order if everything is received" + }, + "comment": { + "type": "string", + "description": "Comment" + }, + "lines": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of product dispatches" + } + }, + "required": [ + "lines" + ] + }, + "updateSupplierproposalsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + } + }, + "createSupplierproposalsModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "updateThirdpartiesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Data" + } + } + }, + "createThirdpartiesModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "thirdpartiesCreateCompanyNotificationModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "thirdpartiesCreateCompanyNotificationByCodeModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "thirdpartiesUpdateCompanyNotificationModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "thirdpartiesCreateCompanyBankAccountModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "thirdpartiesUpdateCompanyBankAccountModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "thirdpartiesCreateSocieteAccountModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "thirdpartiesUpdateSocieteAccountModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "createUsersModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "New user data" + } + } + }, + "updateUsersModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Datas" + } + } + }, + "usersCreateUserNotificationModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "usersCreateUserNotificationByCodeModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + }, + "usersUpdateUserNotificationModel": { + "properties": { + "request_data": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request data" + } + } + } + }, + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "query" + } + }, + "info": { + "version": "1", + "title": "Restler API Explorer", + "description": "Live API Documentation", + "contact": { + "name": "Restler Support", + "url": "luracast.com/products/restler", + "email": "arul@luracast.com" + }, + "license": { + "name": "LGPL-2.1", + "url": "https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html" + } + } +} \ No newline at end of file diff --git a/docs/reconciliation_plan.md b/docs/reconciliation_plan.md new file mode 100644 index 0000000..7794798 --- /dev/null +++ b/docs/reconciliation_plan.md @@ -0,0 +1,269 @@ +# Invoice Reconciliation — Design & Implementation Plan + +## Context + +**Stack:** Ruby (Rails or standalone script) +**Purpose:** Reconcile GoCardless payments, Shine bank statements, and Dolibarr invoices to ensure all three systems are in sync. +**Billing flow:** Customers are billed manually via GoCardless direct debit. Invoices are managed in Dolibarr. Cash lands in a Shine business bank account. + +--- + +## The Problem + +Three systems hold overlapping financial data but are not automatically linked: + +``` +Shine bank ◄─── GoCardless payouts ◄─── GoCardless payments ◄─── Dolibarr invoices +``` + +Discrepancies arise when: +- A GoCardless payment is collected but Dolibarr is not marked as paid +- A Dolibarr invoice is marked paid but no GoCardless payment exists +- A GoCardless payout (batch) never landed in the Shine account + +--- + +## Data Sources + +| Source | What it contains | How to export | +|--------|-----------------|---------------| +| **Dolibarr API** | Invoices, payment status, customer info | Fetched live via REST API (`/invoices`) | +| **GoCardless payments CSV** | Individual payment ID, amount, date, status, customer | Dashboard → Payments → Export CSV | +| **GoCardless payouts CSV** | Payout ID, total amount, arrival date (batched bank transfers) | Dashboard → Payouts → Export CSV | +| **Shine bank CSV** | Bank transactions: date, description, amount, balance | App → Comptes → Exporter le relevé | + +--- + +## Architecture + +``` +lib/tasks/reconcile.rake ← CLI entry point (rake task) +app/services/reconciliation/ + ├── dolibarr_fetcher.rb ← Fetch invoices + payment records via Dolibarr API + ├── gocardless_parser.rb ← Parse GoCardless payments CSV + ├── gocardless_payout_parser.rb ← Parse GoCardless payouts CSV + ├── shine_parser.rb ← Parse Shine bank statement CSV + ├── engine.rb ← Core matching logic (3 passes) + └── reporter.rb ← Terminal summary + CSV output +``` + +--- + +## Reconciliation Passes + +### Pass 1 — Dolibarr open invoice audit + +- Fetch all Dolibarr invoices with `status=1` (validated/open) for the date range +- Flag any that are past their due date: these should have a GoCardless payment but don't +- Output: list of overdue open invoices needing action + +### Pass 2 — GoCardless ↔ Dolibarr matching + +For each GoCardless payment in the CSV: + +**Matching strategy (in order of confidence):** +1. **Strong match**: `num_payment` field in Dolibarr payment record == GoCardless payment ID +2. **Soft match**: `amount_ttc` + `customer_name` + date within ±5 days + +**Flags:** +- `GC_PAID_DOLIBARR_OPEN` — GoCardless collected payment, Dolibarr invoice still open → needs `mark_as_paid` call +- `DOLIBARR_PAID_NO_GC` — Dolibarr marked paid but no GoCardless payment found → manual payment, verify +- `GC_FAILED` — GoCardless payment failed, check if Dolibarr invoice is still open +- `MATCHED` — Both sides agree, no action needed + +### Pass 3 — Shine bank ↔ GoCardless payout verification + +- GoCardless batches individual payments into payouts and deposits them as a single bank transfer +- Each GoCardless payout should appear as a credit in Shine (description contains "GOCARDLESS" or similar) +- Match by: payout arrival date ±2 days + amount + +**Flags:** +- `PAYOUT_MISSING` — GoCardless payout not found in Shine bank statement +- `AMOUNT_MISMATCH` — Payout found but amounts differ (possible fee deduction issue) +- `VERIFIED` — Payout confirmed in bank account + +--- + +## Dolibarr API Endpoints Used + +``` +GET /invoices?status=1&limit=500 # Open/validated invoices +GET /invoices?status=2&limit=500 # Paid invoices +GET /invoices/{id} # Single invoice with payment history +GET /invoices/{id}/payments # Payment records for an invoice +POST /invoices/paymentsdistributed # Record a payment (for --fix mode) +``` + +**Key Dolibarr invoice fields:** +- `ref` — Invoice reference (e.g., `FA2601-0034`) +- `total_ttc` — Total amount including tax (euros, float) +- `paye` — Payment flag: `1` = paid, `0` = unpaid +- `sumpayed` — Total amount already paid +- `remaintopay` — Remaining balance due +- `socid` — Customer (third-party) ID +- `status` — `0`=draft, `1`=validated, `2`=paid, `3`=cancelled + +**Dolibarr mark-as-paid payload:** +```json +{ + "arrayofamounts": { + "{INVOICE_ID}": { + "amount": 19.99, + "multicurrency_amount": null + } + }, + "datepaye": 1748524447, + "paymentid": 6, + "closepaidinvoices": "yes", + "accountid": 1, + "num_payment": "PM01234567", + "comment": "GoCardless payment — auto-reconciled" +} +``` + +(`paymentid: 6` = GoCardless payment method ID in Dolibarr — verify this value in your instance) + +--- + +## GoCardless CSV Format + +GoCardless payment export columns (verify against your actual export): + +``` +id, amount, currency, status, charge_date, description, reference, +customer_id, customer_name, mandate_id, payout_id +``` + +Relevant statuses: `paid_out`, `confirmed`, `failed`, `cancelled`, `pending_submission` + +GoCardless payout export columns: + +``` +id, amount, currency, status, arrival_date, reference +``` + +--- + +## Shine CSV Format + +Shine bank export columns (verify against your actual export): + +``` +Date, Libellé, Montant, Catégorie, Notes, Solde +``` + +GoCardless payouts typically appear with `Libellé` containing `GOCARDLESS` or `GC`. + +**Note:** Column names may vary by export language/version. Make the parser configurable. + +--- + +## CLI Interface + +```bash +# Dry run — report only, no changes +bin/rails reconcile:run \ + FROM=2026-01-01 \ + TO=2026-01-31 \ + GC=tmp/gocardless_payments.csv \ + GC_PAYOUTS=tmp/gocardless_payouts.csv \ + SHINE=tmp/shine_january.csv + +# Auto-fix — mark Dolibarr invoices as paid where GC payment is confirmed +bin/rails reconcile:run \ + FROM=2026-01-01 \ + TO=2026-01-31 \ + GC=tmp/gocardless_payments.csv \ + GC_PAYOUTS=tmp/gocardless_payouts.csv \ + SHINE=tmp/shine_january.csv \ + FIX=true +``` + +--- + +## Expected Report Output + +``` +=== RECONCILIATION REPORT: 2026-01-01 to 2026-01-31 === + +DOLIBARR SUMMARY + Total invoices validated: 47 + Total invoices paid: 43 + Open and overdue: 4 ← ACTION NEEDED + +GOCARDLESS ↔ DOLIBARR + Matched (no action): 43 ✓ + GC paid / Dolibarr open: 3 ← Dolibarr needs marking as paid + Dolibarr paid / no GC: 1 ← Verify manual payment + GC failed: 0 + +SHINE ↔ GOCARDLESS PAYOUTS + Payouts expected: 8 + Payouts found in Shine: 8 ✓ + Total amount expected: €842.58 + Total amount received: €842.58 + Difference: €0.00 ✓ + +ACTIONS NEEDED: + 1. [GC_PAID_DOLIBARR_OPEN] FA2601-0034 €19.99 DUPONT Jean GC: PM01234567 2026-01-05 + 2. [GC_PAID_DOLIBARR_OPEN] FA2601-0041 €29.99 MARTIN Paul GC: PM05678901 2026-01-12 + 3. [GC_PAID_DOLIBARR_OPEN] FA2601-0052 €19.99 DURAND Marie GC: PM09012345 2026-01-19 + 4. [DOLIBARR_PAID_NO_GC] FA2601-0023 €19.99 LEROY Claude Paid: 2026-01-08 (no GC match) + +Report saved to: tmp/reconciliation_2026-01-31.csv +``` + +--- + +## Output CSV Format + +```csv +invoice_ref,customer_name,amount_ttc,invoice_date,dolibarr_status,gc_payment_id,gc_status,gc_charge_date,match_status,action +FA2601-0034,DUPONT Jean,19.99,2026-01-01,open,PM01234567,paid_out,2026-01-05,GC_PAID_DOLIBARR_OPEN,mark_dolibarr_paid +FA2601-0041,MARTIN Paul,29.99,2026-01-08,open,PM05678901,paid_out,2026-01-12,GC_PAID_DOLIBARR_OPEN,mark_dolibarr_paid +FA2601-0023,LEROY Claude,19.99,2026-01-07,paid,,,,DOLIBARR_PAID_NO_GC,verify_manually +FA2601-0012,DUPONT Jean,19.99,2025-12-01,paid,PM98765432,paid_out,2025-12-05,MATCHED,none +``` + +--- + +## Implementation Notes + +### Matching tolerance + +- **Amount**: exact match (compare in cents to avoid float issues — multiply Dolibarr's euro amounts by 100) +- **Date**: ±5 days between GoCardless `charge_date` and Dolibarr invoice `date` +- **Customer**: normalize names before comparing (strip accents, lowercase, trim) + +### Dolibarr client setup + +The `Dolibarr::Client` requires: +``` +DOLIBARR_URL=https://your-dolibarr.example.com/api/index.php +DOLIBARR_API_KEY=your_api_key +``` + +### Edge cases to handle + +- One GoCardless payment covering multiple invoices (rare but possible) +- Credit notes in Dolibarr offsetting invoice balances +- GoCardless payment retried after initial failure (same invoice, multiple GC payment IDs) +- Shine CSV encoding (often ISO-8859-1, convert to UTF-8) +- GoCardless fees: payouts may be slightly less than sum of payments due to GC fees + +### Dolibarr payment method ID + +When calling `paymentsdistributed`, `paymentid` must match the Dolibarr payment method ID for GoCardless in your instance. Check: +``` +GET /setup/dictionary/payment_types +``` +Find the entry for GoCardless (often named "Prélèvement GoCardless" or similar). + +--- + +## Future Enhancements + +- **Scheduled run**: Run monthly via cron, email report to admin +- **Web interface**: Upload CSVs via admin UI, view reconciliation in browser +- **Stripe support**: Same engine, add a `StripeParser` for Stripe payouts +- **Webhook-driven**: Instead of CSV imports, consume GoCardless webhooks in real time to auto-reconcile as payments land diff --git a/lib/boot.rb b/lib/boot.rb new file mode 100644 index 0000000..3c4897a --- /dev/null +++ b/lib/boot.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require "bundler/setup" +require "dotenv/load" + +require_relative "dolibarr/client" +require_relative "reconciliation/dolibarr_fetcher" +require_relative "reconciliation/gocardless_parser" +require_relative "reconciliation/shine_parser" +require_relative "reconciliation/engine" +require_relative "reconciliation/reporter" +require_relative "reconciliation/fixer" diff --git a/lib/dolibarr/client.rb b/lib/dolibarr/client.rb new file mode 100644 index 0000000..64550e0 --- /dev/null +++ b/lib/dolibarr/client.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +require "httparty" +require "json" + +module Dolibarr + class Client + include HTTParty + + class NotFoundError < StandardError; end + class ValidationError < StandardError; end + class Error < StandardError; end + + def initialize( + base_url: ENV.fetch("DOLIBARR_URL"), + api_key: ENV.fetch("DOLIBARR_API_KEY") + ) + @base_url = base_url + @headers = { + "DOLAPIKEY" => api_key, + "Content-Type" => "application/json", + "Accept" => "application/json" + } + end + + def get(path, params = {}) + perform_request(:get, path, params) + end + + def post(path, data = {}) + perform_request(:post, path, data) + end + + def put(path, data = {}) + perform_request(:put, path, data) + end + + private + + def perform_request(method, path, data = {}) + url = "#{@base_url}#{path}" + opts = { headers: @headers } + + case method + when :get + opts[:query] = data unless data.empty? + response = self.class.get(url, opts) + when :post + opts[:body] = data.to_json + response = self.class.post(url, opts) + when :put + opts[:body] = data.to_json + response = self.class.put(url, opts) + end + + handle_response(response) + rescue => e + raise Error, "Connection error: #{e.message}" + end + + def handle_response(response) + return nil if response.body.nil? || response.body.strip.empty? + + code = response.code.to_i + case code + when 200..299 + response.parsed_response + when 404 + raise NotFoundError, "Not found (404)" + when 400 + raise ValidationError, "Validation error: #{response.body}" + when 401 + raise Error, "Authentication failed (401) — check DOLIBARR_API_KEY" + when 500..599 + raise Error, "Dolibarr server error (#{code}): #{response.body}" + else + raise Error, "Unexpected status #{code}: #{response.body}" + end + rescue JSON::ParserError => e + raise Error, "JSON parse error: #{e.message}" + end + end +end diff --git a/lib/reconciliation/dolibarr_fetcher.rb b/lib/reconciliation/dolibarr_fetcher.rb new file mode 100644 index 0000000..8fd8bb3 --- /dev/null +++ b/lib/reconciliation/dolibarr_fetcher.rb @@ -0,0 +1,115 @@ +# frozen_string_literal: true + +require "date" + +module Reconciliation + class DolibarrFetcher + # Dolibarr invoice statuses + STATUS_DRAFT = 0 + STATUS_VALIDATED = 1 + STATUS_PAID = 2 + STATUS_CANCELLED = 3 + + Invoice = Struct.new( + :id, # Dolibarr internal ID + :ref, # Invoice reference, e.g. "FA2407-0003" + :status, # 0=draft, 1=validated/open, 2=paid, 3=cancelled + :total_ttc, # Total amount TTC (euros, float) + :amount_cents, # total_ttc * 100, rounded (integer) + :paye, # 0=unpaid, 1=paid + :sumpayed, # Amount already paid (euros) + :remain_to_pay, # Remaining balance (euros) + :date, # Invoice date (Date) + :due_date, # Due date (Date) + :customer_id, # socid + :customer_name, # nom of third party if present + keyword_init: true + ) + + def initialize(client, from:, to:) + @client = client + @from = from + @to = to + end + + # Fetches all validated invoices and resolves customer names. + # Note: querying status=1 returns all non-draft invoices in Dolibarr (open, paid, cancelled). + # Cancelled invoices are filtered out here. + def fetch_invoices + $stderr.puts "[DolibarrFetcher] Fetching thirdparty names..." + name_by_id = fetch_thirdparty_names + + $stderr.puts "[DolibarrFetcher] Fetching invoices..." + raw_invoices = fetch_all(status: STATUS_VALIDATED) + + invoices = raw_invoices + .map { |raw| parse_invoice(raw, name_by_id) } + .reject { |inv| inv.status == STATUS_CANCELLED } + + open_count = invoices.count { |inv| inv.status == STATUS_VALIDATED } + paid_count = invoices.count { |inv| inv.status == STATUS_PAID } + $stderr.puts "[DolibarrFetcher] Total: #{invoices.size} invoices (#{open_count} open, #{paid_count} paid)" + invoices + rescue Dolibarr::Client::Error => e + $stderr.puts "[DolibarrFetcher] Error: #{e.message}" + raise + end + + private + + def fetch_all(status:, sqlfilters: nil) + invoices = [] + page = 0 + loop do + params = { status: status, limit: 100, page: page } + params[:sqlfilters] = sqlfilters if sqlfilters + batch = @client.get("/invoices", params) + break if batch.nil? || !batch.is_a?(Array) || batch.empty? + + invoices.concat(batch) + break if batch.size < 100 + + page += 1 + end + invoices + end + + def parse_invoice(raw, name_by_id = {}) + customer_id = raw["socid"].to_i + Invoice.new( + id: raw["id"].to_i, + ref: raw["ref"].to_s.strip, + status: raw["statut"].to_i, + total_ttc: raw["total_ttc"].to_f, + amount_cents: (raw["total_ttc"].to_f * 100).round, + paye: raw["paye"].to_i, + sumpayed: raw["sumpayed"].to_f, + remain_to_pay: raw["remaintopay"].to_f, + date: parse_unix_date(raw["datef"] || raw["date"]), + due_date: parse_unix_date(raw["date_lim_reglement"]), + customer_id: customer_id, + customer_name: name_by_id[customer_id] || raw.dig("thirdparty", "name").to_s.strip + ) + end + + def fetch_thirdparty_names + result = {} + page = 0 + loop do + batch = @client.get("/thirdparties", limit: 100, page: page) + break if batch.nil? || !batch.is_a?(Array) || batch.empty? + batch.each { |tp| result[tp["id"].to_i] = tp["name"].to_s.strip } + break if batch.size < 100 + page += 1 + end + result + end + + def parse_unix_date(value) + return nil if value.nil? || value.to_s.strip.empty? || value.to_i.zero? + Time.at(value.to_i).utc.to_date + rescue + nil + end + end +end diff --git a/lib/reconciliation/engine.rb b/lib/reconciliation/engine.rb new file mode 100644 index 0000000..92f7a76 --- /dev/null +++ b/lib/reconciliation/engine.rb @@ -0,0 +1,243 @@ +# frozen_string_literal: true + +require "date" + +module Reconciliation + class Engine + # Match flags + MATCHED = :matched # GC paid + Dolibarr paid — all good + GC_PAID_DOLIBARR_OPEN = :gc_paid_dolibarr_open # GC collected, Dolibarr still open — FIX NEEDED + GC_FAILED = :gc_failed # GC payment failed + GC_CANCELLED = :gc_cancelled # GC payment cancelled (no action needed) + GC_NO_INVOICE = :gc_no_invoice # GC payment with no Dolibarr invoice found + DOLIBARR_PAID_NO_GC = :dolibarr_paid_no_gc # Dolibarr paid, no GC match — verify manually + DOLIBARR_OPEN_NO_GC = :dolibarr_open_no_gc # Dolibarr open, no GC payment found (overdue) + + # Payout flags + PAYOUT_VERIFIED = :payout_verified + PAYOUT_MISSING = :payout_missing + PAYOUT_AMOUNT_MISMATCH = :payout_amount_mismatch + + DATE_TOLERANCE = 7 # days for GC charge_date ↔ Dolibarr invoice date soft match + PAYOUT_DATE_TOLERANCE = 2 # days for GC payout_date ↔ Shine credit date + + # Result structs + Match = Struct.new( + :flag, + :invoice, # DolibarrFetcher::Invoice or nil + :payment, # GocardlessParser::Payment or nil + :match_type, # :strong, :soft, or nil + keyword_init: true + ) + + PayoutMatch = Struct.new( + :flag, + :payout_id, + :payout_date, + :expected_amount_cents, + :shine_transaction, # ShineParser::Transaction or nil + :actual_amount_cents, + :gc_payment_ids, + keyword_init: true + ) + + def initialize(dolibarr_invoices:, gc_payments:, shine_transactions:, from:, to:) + @invoices = dolibarr_invoices + @gc_payments = gc_payments + @shine = shine_transactions + @from = from + @to = to + end + + def run + matches = pass1_gc_vs_dolibarr + overdue = pass2_overdue_open_invoices(matches) + payout_matches = pass3_payouts_vs_shine + + { + matches: matches, + matched: matches.select { |m| m.flag == MATCHED }, + gc_paid_dolibarr_open: matches.select { |m| m.flag == GC_PAID_DOLIBARR_OPEN }, + gc_failed: matches.select { |m| m.flag == GC_FAILED }, + gc_cancelled: matches.select { |m| m.flag == GC_CANCELLED }, + gc_no_invoice: matches.select { |m| m.flag == GC_NO_INVOICE }, + dolibarr_paid_no_gc: matches.select { |m| m.flag == DOLIBARR_PAID_NO_GC }, + dolibarr_open_no_gc: overdue, + payout_matches: payout_matches + } + end + + private + + # ------------------------------------------------------------------------- + # Pass 1 — Match each GoCardless payment to a Dolibarr invoice + # ------------------------------------------------------------------------- + def pass1_gc_vs_dolibarr + matched_invoice_ids = [] + results = [] + + @gc_payments.each do |payment| + invoice, match_type = find_invoice(payment) + + if invoice + matched_invoice_ids << invoice.id + end + + flag = determine_flag(payment, invoice) + results << Match.new(flag: flag, invoice: invoice, payment: payment, match_type: match_type) + end + + # Dolibarr paid invoices in the date range with no GC match. + # Scoped to the date range to avoid flagging every historical paid invoice. + matched_set = matched_invoice_ids.to_set + @invoices.each do |inv| + next if matched_set.include?(inv.id) + next unless inv.status == DolibarrFetcher::STATUS_PAID + # Only flag paid invoices whose date falls within the reconciliation window + next if inv.date && (inv.date < @from || inv.date > @to) + + results << Match.new( + flag: DOLIBARR_PAID_NO_GC, + invoice: inv, + payment: nil, + match_type: nil + ) + end + + results + end + + # ------------------------------------------------------------------------- + # Pass 2 — Flag open Dolibarr invoices with no GC match that are overdue + # ------------------------------------------------------------------------- + def pass2_overdue_open_invoices(matches) + matched_invoice_ids = matches.filter_map { |m| m.invoice&.id }.to_set + + @invoices.select do |inv| + inv.status == DolibarrFetcher::STATUS_VALIDATED && + !matched_invoice_ids.include?(inv.id) + end + end + + # ------------------------------------------------------------------------- + # Pass 3 — Match GoCardless payouts to Shine bank credits + # ------------------------------------------------------------------------- + def pass3_payouts_vs_shine + return [] if @shine.empty? + + gc_credits = ShineParser.gocardless_credits(@shine) + + # Group paid_out payments by payout_id. + # Only paid_out payments are included in a payout; failed/cancelled are not. + by_payout = @gc_payments + .select { |p| p.status == "paid_out" && p.payout_id && !p.payout_id.empty? && p.payout_date } + .group_by(&:payout_id) + + used_shine_ids = [] + + by_payout.filter_map do |payout_id, payments| + payout_date = payments.map(&:payout_date).compact.max + expected_cents = payments.sum(&:amount_cents) + + shine_tx = gc_credits.find do |tx| + !used_shine_ids.include?(tx.id) && + (tx.date - payout_date).abs <= PAYOUT_DATE_TOLERANCE && + tx.credit_cents == expected_cents + end + + if shine_tx + used_shine_ids << shine_tx.id + flag = PAYOUT_VERIFIED + actual = shine_tx.credit_cents + else + # Try date match only (amount mismatch — possible GC fees) + shine_tx = gc_credits.find do |tx| + !used_shine_ids.include?(tx.id) && + (tx.date - payout_date).abs <= PAYOUT_DATE_TOLERANCE + end + + if shine_tx + used_shine_ids << shine_tx.id + flag = PAYOUT_AMOUNT_MISMATCH + actual = shine_tx.credit_cents + else + flag = PAYOUT_MISSING + actual = 0 + end + end + + PayoutMatch.new( + flag: flag, + payout_id: payout_id, + payout_date: payout_date, + expected_amount_cents: expected_cents, + shine_transaction: shine_tx, + actual_amount_cents: actual, + gc_payment_ids: payments.map(&:id) + ) + end + end + + # ------------------------------------------------------------------------- + # Invoice lookup + # ------------------------------------------------------------------------- + def find_invoice(payment) + # 1. Strong match: GC description == Dolibarr invoice ref + # Applies when the user puts the invoice ref in the GC payment description. + invoice = @invoices.find do |inv| + !payment.description.empty? && + inv.ref.casecmp(payment.description) == 0 + end + return [invoice, :strong] if invoice + + # 2. Soft match: same amount + customer name + date within tolerance. + # The user creates invoices after GC payment succeeds, so the invoice date + # should be close to the GC charge_date. Since multiple customers pay the + # same amount, customer name matching is required to avoid false positives. + invoice = @invoices.find do |inv| + inv.amount_cents == payment.amount_cents && + inv.date && + (inv.date - payment.charge_date).abs <= DATE_TOLERANCE && + names_match?(inv.customer_name, payment.customer_name) + end + return [invoice, :soft] if invoice + + [nil, nil] + end + + # Normalise a name for comparison: remove accents, lowercase, collapse spaces. + def normalize_name(name) + name.to_s + .unicode_normalize(:nfd) + .gsub(/\p{Mn}/, "") # strip combining diacritical marks + .downcase + .gsub(/[^a-z0-9 ]/, "") + .split + .sort + .join(" ") + end + + def names_match?(dolibarr_name, gc_name) + return false if dolibarr_name.to_s.strip.empty? || gc_name.to_s.strip.empty? + # Both names normalised and compared as sorted word sets so + # "DUPONT Jean" matches "Jean DUPONT" and accent variants. + normalize_name(dolibarr_name) == normalize_name(gc_name) + end + + def determine_flag(payment, invoice) + if GocardlessParser::COLLECTED_STATUSES.include?(payment.status) + if invoice.nil? + GC_NO_INVOICE + elsif invoice.status == DolibarrFetcher::STATUS_PAID + MATCHED + else + GC_PAID_DOLIBARR_OPEN + end + elsif GocardlessParser::FAILED_STATUSES.include?(payment.status) + GC_FAILED + else + GC_CANCELLED + end + end + end +end diff --git a/lib/reconciliation/fixer.rb b/lib/reconciliation/fixer.rb new file mode 100644 index 0000000..1a4fe4e --- /dev/null +++ b/lib/reconciliation/fixer.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module Reconciliation + # Applies fixes to Dolibarr: marks invoices as paid using GoCardless payment data. + class Fixer + def initialize(client) + @client = client + end + + # Accepts an array of Engine::Match objects with flag GC_PAID_DOLIBARR_OPEN + def apply(matches) + return if matches.empty? + + gc_payment_id = ENV.fetch("DOLIBARR_GC_PAYMENT_ID", nil)&.to_i + bank_id = ENV.fetch("DOLIBARR_BANK_ACCOUNT_ID", "1").to_i + + if gc_payment_id.nil? + warn "[Fixer] DOLIBARR_GC_PAYMENT_ID not set in .env — cannot fix. " \ + "Run: GET /setup/dictionary/payment_types to find the GoCardless payment type ID." + return + end + + puts "" + puts "APPLYING FIXES (#{matches.size} invoices)..." + + matches.each do |m| + inv = m.invoice + pay = m.payment + + payload = { + arrayofamounts: { + inv.id.to_s => { + amount: "%.2f" % (inv.amount_cents / 100.0), + multicurrency_amount: nil + } + }, + datepaye: pay.charge_date.to_time.to_i, + paymentid: gc_payment_id, + closepaidinvoices: "yes", + accountid: bank_id, + num_payment: pay.id, + comment: "GoCardless payment — auto-reconciled (#{pay.charge_date})" + } + + begin + @client.post("/invoices/paymentsdistributed", payload) + puts " ✓ Marked #{inv.ref} as paid (GC: #{pay.id})" + rescue Dolibarr::Client::ValidationError => e + puts " ✗ #{inv.ref} — validation error: #{e.message}" + rescue Dolibarr::Client::Error => e + puts " ✗ #{inv.ref} — API error: #{e.message}" + end + end + end + end +end diff --git a/lib/reconciliation/gocardless_parser.rb b/lib/reconciliation/gocardless_parser.rb new file mode 100644 index 0000000..0c2fffd --- /dev/null +++ b/lib/reconciliation/gocardless_parser.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +require "csv" +require "date" + +module Reconciliation + class GocardlessParser + Payment = Struct.new( + :id, # e.g. "PM014J7X4PY98T" + :charge_date, # Date + :amount_cents, # Integer (euros * 100) + :description, # Free text — often the Dolibarr invoice ref + :status, # "paid_out", "failed", "cancelled", etc. + :payout_id, # e.g. "PO0010R1ARR0QZ" + :payout_date, # Date or nil + :customer_name, # "Jean DUPONT" + :customer_email, + keyword_init: true + ) + + # Statuses that represent a successful collection from the customer. + COLLECTED_STATUSES = %w[paid_out confirmed].freeze + FAILED_STATUSES = %w[failed].freeze + + def self.parse(csv_path, from: nil, to: nil) + rows = CSV.read(csv_path, headers: true, encoding: "UTF-8") + + payments = rows.filter_map do |row| + charge_date = safe_parse_date(row["charge_date"]) + next if charge_date.nil? + next if from && charge_date < from + next if to && charge_date > to + + payout_date = safe_parse_date(row["payout_date"]) + + Payment.new( + id: row["id"].to_s.strip, + charge_date: charge_date, + amount_cents: (row["amount"].to_f * 100).round, + description: row["description"].to_s.strip, + status: row["status"].to_s.strip, + payout_id: row["links.payout"].to_s.strip.then { |v| v.empty? ? nil : v }, + payout_date: payout_date, + customer_name: build_name(row["customers.given_name"], row["customers.family_name"]), + customer_email: row["customers.email"].to_s.strip + ) + end + + $stderr.puts "[GocardlessParser] Loaded #{payments.size} payments from #{csv_path}" + payments + end + + private_class_method def self.safe_parse_date(str) + return nil if str.nil? || str.strip.empty? + Date.parse(str.strip) + rescue Date::Error, ArgumentError + nil + end + + private_class_method def self.build_name(given, family) + [given.to_s.strip, family.to_s.strip].reject(&:empty?).join(" ") + end + end +end diff --git a/lib/reconciliation/reporter.rb b/lib/reconciliation/reporter.rb new file mode 100644 index 0000000..3b06406 --- /dev/null +++ b/lib/reconciliation/reporter.rb @@ -0,0 +1,203 @@ +# frozen_string_literal: true + +require "csv" +require "date" + +module Reconciliation + class Reporter + def initialize(result, from:, to:) + @result = result + @from = from + @to = to + end + + def print_summary + r = @result + puts "" + puts "=" * 60 + puts " RECONCILIATION REPORT: #{@from} to #{@to}" + puts "=" * 60 + + # --- Dolibarr overview --- + total_invoices = r[:matches].filter_map(&:invoice).uniq(&:id).size + + r[:dolibarr_open_no_gc].size + open_count = r[:dolibarr_open_no_gc].size + + r[:gc_paid_dolibarr_open].size + puts "" + puts "DOLIBARR" + puts " Total invoices in scope: #{total_invoices}" + puts " Open (no GC match): #{r[:dolibarr_open_no_gc].size}#{r[:dolibarr_open_no_gc].any? ? ' ← needs attention' : ''}" + puts " Paid (GC matched): #{r[:matched].size}" + + # --- GoCardless ↔ Dolibarr --- + puts "" + puts "GOCARDLESS ↔ DOLIBARR" + puts " Matched (paid both sides): #{r[:matched].size} #{'✓' if r[:matched].any?}" + puts " GC paid / Dolibarr open: #{r[:gc_paid_dolibarr_open].size}#{r[:gc_paid_dolibarr_open].any? ? ' ← FIX with --fix' : ''}" + puts " Dolibarr paid / no GC: #{r[:dolibarr_paid_no_gc].size}#{r[:dolibarr_paid_no_gc].any? ? ' ← verify manually' : ''}" + puts " GC failed: #{r[:gc_failed].size}" + puts " GC cancelled: #{r[:gc_cancelled].size}" + puts " GC payment / no invoice: #{r[:gc_no_invoice].size}#{r[:gc_no_invoice].any? ? ' ← investigate' : ''}" + + # --- Shine ↔ GoCardless Payouts --- + unless @result[:payout_matches].empty? + pm = r[:payout_matches] + verified = pm.count { |p| p.flag == Engine::PAYOUT_VERIFIED } + mismatch = pm.count { |p| p.flag == Engine::PAYOUT_AMOUNT_MISMATCH } + missing = pm.count { |p| p.flag == Engine::PAYOUT_MISSING } + expected = pm.sum(&:expected_amount_cents) + actual = pm.sum(&:actual_amount_cents) + diff = actual - expected + + puts "" + puts "SHINE ↔ GOCARDLESS PAYOUTS" + puts " Payouts expected: #{pm.size}" + puts " Verified: #{verified}#{verified == pm.size ? ' ✓' : ''}" + puts " Amount mismatch: #{mismatch}#{mismatch > 0 ? ' ← check GC fees' : ''}" + puts " Missing in Shine: #{missing}#{missing > 0 ? ' ← investigate' : ''}" + puts " Expected total: #{format_eur(expected)}" + puts " Actual total: #{format_eur(actual)}" + puts " Difference: #{format_eur(diff)}#{diff.zero? ? ' ✓' : ' ← investigate'}" + end + + # --- Action items --- + actions = r[:gc_paid_dolibarr_open] + + r[:dolibarr_paid_no_gc] + + r[:dolibarr_open_no_gc] + + r[:gc_no_invoice] + + if actions.any? + puts "" + puts "ACTIONS NEEDED (#{actions.size})" + puts "-" * 60 + + r[:gc_paid_dolibarr_open].each_with_index do |m, i| + puts " #{i + 1}. [GC_PAID_DOLIBARR_OPEN] " \ + "#{m.invoice.ref.ljust(16)} " \ + "#{format_eur(m.invoice.amount_cents)} " \ + "#{display_name(m.invoice).ljust(20)} " \ + "GC: #{m.payment.id} #{m.payment.charge_date} (#{m.match_type})" + end + + r[:dolibarr_paid_no_gc].each_with_index do |m, i| + n = r[:gc_paid_dolibarr_open].size + i + 1 + puts " #{n}. [DOLIBARR_PAID_NO_GC] " \ + "#{m.invoice.ref.ljust(16)} " \ + "#{format_eur(m.invoice.amount_cents)} " \ + "#{display_name(m.invoice).ljust(20)} " \ + "No GoCardless payment found" + end + + base = r[:gc_paid_dolibarr_open].size + r[:dolibarr_paid_no_gc].size + r[:dolibarr_open_no_gc].each_with_index do |inv, i| + n = base + i + 1 + overdue = inv.due_date && inv.due_date < Date.today ? " (overdue since #{inv.due_date})" : "" + puts " #{n}. [DOLIBARR_OPEN_NO_GC] " \ + "#{inv.ref.ljust(16)} " \ + "#{format_eur(inv.amount_cents)} " \ + "#{display_name(inv).ljust(20)} " \ + "Open, no GC payment#{overdue}" + end + + base2 = base + r[:dolibarr_open_no_gc].size + r[:gc_no_invoice].each_with_index do |m, i| + n = base2 + i + 1 + puts " #{n}. [GC_NO_INVOICE] " \ + "GC: #{m.payment.id} #{format_eur(m.payment.amount_cents)} " \ + "\"#{m.payment.description}\" #{m.payment.customer_name} #{m.payment.charge_date}" + end + + r[:payout_matches].select { |p| p.flag == Engine::PAYOUT_MISSING }.each do |pm| + n = base2 + r[:gc_no_invoice].size + 1 + puts " #{n}. [PAYOUT_MISSING] " \ + "Payout #{pm.payout_id} #{format_eur(pm.expected_amount_cents)} " \ + "expected #{pm.payout_date}" + end + else + puts "" + puts " All clear — no actions needed." + end + + puts "" + puts "=" * 60 + + csv_path = write_csv + puts " Report saved to: #{csv_path}" + puts "" + end + + def write_csv + dir = "tmp" + Dir.mkdir(dir) unless Dir.exist?(dir) + path = "#{dir}/reconciliation_#{@to}.csv" + + CSV.open(path, "w", encoding: "UTF-8") do |csv| + csv << %w[ + invoice_ref customer_name amount_eur invoice_date due_date + dolibarr_status gc_payment_id gc_status gc_charge_date + match_type flag action + ] + + @result[:matches].each do |m| + inv = m.invoice + pay = m.payment + csv << [ + inv&.ref, + inv&.customer_name, + inv ? "%.2f" % (inv.amount_cents / 100.0) : nil, + inv&.date, + inv&.due_date, + inv ? status_label(inv.status) : nil, + pay&.id, + pay&.status, + pay&.charge_date, + m.match_type, + m.flag, + action_label(m.flag) + ] + end + + @result[:dolibarr_open_no_gc].each do |inv| + csv << [ + inv.ref, inv.customer_name, + "%.2f" % (inv.amount_cents / 100.0), + inv.date, inv.due_date, + status_label(inv.status), + nil, nil, nil, nil, + Engine::DOLIBARR_OPEN_NO_GC, + action_label(Engine::DOLIBARR_OPEN_NO_GC) + ] + end + end + + path + end + + private + + def display_name(inv) + name = inv.customer_name.to_s.strip + name.empty? ? "client_id:#{inv.customer_id}" : name + end + + def format_eur(cents) + "€#{"%.2f" % (cents / 100.0)}" + end + + def status_label(status) + { 0 => "draft", 1 => "open", 2 => "paid", 3 => "cancelled" }[status] || status.to_s + end + + def action_label(flag) + { + Engine::MATCHED => "none", + Engine::GC_PAID_DOLIBARR_OPEN => "mark_dolibarr_paid", + Engine::GC_FAILED => "verify", + Engine::GC_CANCELLED => "none", + Engine::GC_NO_INVOICE => "investigate", + Engine::DOLIBARR_PAID_NO_GC => "verify_manually", + Engine::DOLIBARR_OPEN_NO_GC => "follow_up" + }[flag] || flag.to_s + end + end +end diff --git a/lib/reconciliation/shine_parser.rb b/lib/reconciliation/shine_parser.rb new file mode 100644 index 0000000..c60ee98 --- /dev/null +++ b/lib/reconciliation/shine_parser.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +require "csv" +require "date" + +module Reconciliation + class ShineParser + Transaction = Struct.new( + :id, + :date, + :credit_cents, # Integer, > 0 for incoming money + :debit_cents, # Integer, > 0 for outgoing money + :label, # Libellé + :counterparty, # Nom de la contrepartie + keyword_init: true + ) + + def self.parse(csv_path) + content = File.read(csv_path, encoding: "UTF-8") + # Normalise Windows CRLF + content = content.gsub("\r\n", "\n").gsub("\r", "\n") + + rows = CSV.parse(content, headers: true, col_sep: ";") + + transactions = rows.filter_map do |row| + date = safe_parse_date(row["Date de la valeur"]) + next unless date + + Transaction.new( + id: row["Transaction ID"].to_s.strip, + date: date, + credit_cents: parse_french_amount(row["Crédit"]), + debit_cents: parse_french_amount(row["Débit"]), + label: row["Libellé"].to_s.strip, + counterparty: row["Nom de la contrepartie"].to_s.strip + ) + end + + $stderr.puts "[ShineParser] Loaded #{transactions.size} transactions from #{csv_path}" + transactions + end + + # Returns all GoCardless credit transactions (incoming payouts from GC) + def self.gocardless_credits(transactions) + transactions.select do |t| + t.credit_cents > 0 && + t.counterparty.upcase.include?("GOCARDLESS") + end + end + + private_class_method def self.safe_parse_date(str) + return nil if str.nil? || str.strip.empty? + Date.strptime(str.strip, "%d/%m/%Y") + rescue Date::Error, ArgumentError + nil + end + + # French decimal format: "51,10" → 5110 (cents) + private_class_method def self.parse_french_amount(str) + return 0 if str.nil? || str.strip.empty? + (str.strip.gsub(/\s/, "").gsub(",", ".").to_f * 100).round + end + end +end