---
title: "Intercompany transactions automation that books the other side for you"
description: "Automate intercompany transactions: a sale posted in one company creates the matching purchase in another, with account maps, formulas and dry-run tests."
canonical: https://ledgeriano.com/workflows
language: en
publisher: "Ledgeriano"
updated: 2026-11-05
---

# Intercompany transactions automation that books the other side for you

> Automate intercompany transactions: a sale posted in one company creates the matching purchase in another, with account maps, formulas and dry-run tests.

Intercompany transactions automation in Ledgeriano works like this: when a qualifying entry is posted in one business, a workflow creates the matching entry in another business right away, in the background, with the right accounts, amounts and counterparty. No re-keying, no month-end hunt for missing invoices.

## The same transaction, typed twice, in two sets of books

In a group, every intercompany sale is also an intercompany purchase. When two people record the two sides by hand, the books drift apart.

### Double work

A wholesaler that invoices its own retail shop 150 times a month creates 150 extra entries for someone in the shop to type again.

### Amounts that disagree

A typo of 36,000 as 63,000 on one side stays hidden until the intercompany balances refuse to match.

### Timing gaps

The seller posts on the 30th, the buyer on the 3rd of next month, and the month-end balances no longer eliminate.

### Painful consolidation

Eliminating intercompany sales, receivables and payables only works when both sides were recorded the same way.

## Trigger, conditions, actions

A workflow belongs to your account, watches one source business and can write to any business where you have permission to record entries.

### Trigger

Choose the event in the source business: an entry is **created**, **posted** or **reversed**. Most intercompany flows use the posted event, so only approved entries travel.

### Conditions

Filter by voucher type, entry kind, total, description, reference, tag, source, currency, account (has, debit or credit on a code prefix), party, or a free expression. Match **all** or **any**.

### Actions

Run one or more actions in order: build an entry from a template, mirror the entry through an account map, or call a webhook URL. Each action reports its own result.

## Pick the action that matches the transaction

### Create entry from a template

You define the target lines: account code, side, and an amount expression such as `credit("4101")` or `percent(total, 9)`. Descriptions and references accept tags like `{{entry.number}}`. Negative results flip to the other side automatically, and zero lines can be skipped.

Best for intercompany sale to purchase, management fees and recharges.

### Mirror the entry

Copy every line of the source entry into the target, translating account codes through a map. Exact codes win, then the longest prefix wildcard such as `41*`. Unmapped lines go to a default account, are skipped, or stop the action. Swap sides, apply a multiplier, keep parties or merge lines per account.

Best for consolidation mirrors and branch reporting.

### Call a webhook

POST a JSON summary of the entry (number, date, lines, totals) to any URL, with the workflow id in the `X-Webhook-Workflow` header. The run records the HTTP status so failures are visible.

Best for notifying an ERP, a data warehouse or a chat channel.

| Expression | What it returns | In the worked example |
| --- | --- | --- |
| `total` | Total debits of the source entry (equal to total credits) | 60,000.00 |
| `debit("41")` | Sum of debit amounts on accounts starting with 41 | 0.00 |
| `credit("4101")` | Sum of credit amounts on accounts starting with 4101 | 36,000.00 |
| `net("11")` | Debits minus credits on accounts starting with 11 | 12,000.00 |
| `round(x, 2)` | x rounded to 2 decimals (any precision you pass) | `round(total / 3, 2)` = 20,000.00 |
| `percent(total, 9)` | 9% of the value, rounded to 2 decimals | 5,400.00 |
| `abs(x)`, `min(a, b)`, `max(a, b)` | Absolute value, smaller and larger of values | `min(total, 50000)` = 50,000.00 |
| `entry.currency_code == "USD"` | A condition on entry fields, combined with `and` / `or` | true |

## B2B wholesaler to B2C retailer, both sides in one step

Alpha Wholesale LLC sells stock to its sister company Beta Retail Store, which sells to consumers. Both use the IFRS chart template. In Alpha, Beta is customer `C001`; in Beta, Alpha is supplier `S001`.

1. Alpha posts sales invoice INV-1001

2. The workflow posts the purchase in Beta

The workflow triggers on **entry posted**, requires voucher type `SAL` and party `C001`, and uses `credit("4101")` for both target lines. That picks up the 36,000.00 of revenue and ignores the 24,000.00 cost of sales, which is Alpha's internal cost and means nothing to Beta. Using `total` here would have been wrong: it is 60,000.00.

Beta's entry carries the reference `ALPHA-42` and metadata that points back to Alpha's entry, so either accountant can trace one side to the other. At consolidation, Alpha's 36,000.00 revenue and Beta's 36,000.00 inventory purchase eliminate cleanly, along with the matching receivable and payable.

workflow configuration (simplified)

{
  "trigger": "entry.posted",
  "source_business": "Alpha Wholesale LLC",
  "conditions": [
    { "field": "voucher_type", "operator": "eq",  "value": "SAL" },
    { "field": "party",        "operator": "has", "value": "C001" }
  ],
  "actions": [{
    "type": "create_entry",
    "target_business": "Beta Retail Store",
    "voucher_type": "PUR",
    "status": "posted",
    "reference": "ALPHA-{{entry.number}}",
    "description": "Purchase from {{source.business}}, invoice {{entry.reference}}",
    "lines": [
      { "account_code": "1124", "side": "debit",  "amount": "credit(\"4101\")" },
      { "account_code": "2111", "side": "credit", "amount": "credit(\"4101\")", "party_code": "S001" }
    ]
  }]
}

### Entry 42 · Sales

Alpha Wholesale LLC (B2B)

1111

Trade receivables

C001 Beta Retail

36,000.00

4101

Sales of goods

5101

Cost of goods sold

24,000.00

1124

Merchandise inventory

60,000.00

Posted

### Entry 17 · Purchases

Beta Retail Store (B2C)

2111

Trade payables

S001 Alpha Wholesale

Created by workflow

Mirror action with prefix wildcards

For a consolidation business, a mirror action copies each posted entry and maps codes: `4101` goes to `4190`, anything else starting with `41` goes to `4100`, all assets starting with `1` go to `1999`, and the rest falls back to `9999`.

{
  "type": "mirror_entry",
  "target_business": "Group Consolidation",
  "account_map": [
    { "from": "4101", "to": "4190" },
    { "from": "41*",  "to": "4100" },
    { "from": "1*",   "to": "1999" }
  ],
  "default_account": "9999",
  "swap_sides": false,
  "merge_lines": true
}

## Automation that cannot run away with your books

### Loop protection

Entries created by a workflow do not trigger other workflows unless you allow chaining, and a workflow never fires on its own output.

### Maximum depth of 3

Even with chaining on, a chain of workflow-created entries stops at depth 3 and the run is recorded as skipped.

### Dry-run test

Pick any existing entry and see which conditions pass and the exact entries each action would create, without writing anything.

### Run history

Every run is logged with status (success, partial, failed or skipped), duration, the entries it created and any error message.

### Permissions at run time

At every run Ledgeriano checks that you can still view the source and create entries in the target. Without posting rights, entries arrive as drafts.

### No duplicates

Each action writes with an idempotency key built from the workflow, action, entry and event, so a retry never books the same entry twice.

## What a workflow run costs

Workflows use the same credits as the rest of Ledgeriano. At the default prices a run costs **2 credits** (`workflow.run`), plus the normal cost of each entry it creates (**3 credits** for `entry.create`). The sale and purchase in the example above cost 5 credits for the automated side. Entries that do not match the conditions cost nothing. Administrators can change these costs, and the current ones are always listed in your account.

Workflow run

2

Entry created in the target

3

Conditions not met

0

credits

## Where groups use workflows

### Intercompany sale and purchase

Seller's revenue becomes the buyer's inventory or expense, with the payable to the right sister company.

### Management fees and recharges

When the holding company posts a management fee, the subsidiary records the expense and payable. Use `percent(total, 5)` for a fee charged as a share.

### Consolidation mirror

Mirror every posted entry into a consolidation business with a compact account map and merged lines.

### Notify your ERP

Send a webhook when an entry tagged `invoice` is posted, so your ERP or warehouse updates without polling.

## How to set up an intercompany workflow

Set up an intercompany workflow in Ledgeriano

### Prepare both businesses

Make sure you can record entries in both companies, and create each company as a party in the other: Beta as customer C001 in Alpha, Alpha as supplier S001 in Beta.

### Create the workflow

Choose the source business (Alpha) and the trigger. Use entry posted so only approved entries are copied.

### Add conditions

Require voucher type SAL and party C001, so sales to outside customers are left alone.

### Add the action

Pick Create entry, choose Beta as the target and add the lines: debit 1124 and credit 2111 with party S001, both with the amount credit("4101").

### Test on a real entry

Run the dry-run test on an existing sale and check the conditions and the entry it would create. Nothing is written.

### Activate and monitor

Switch the workflow on and review the run history after the first few sales.

## Intercompany workflow questions

### What is intercompany transactions automation?

It is recording the second side of a transaction between two related companies automatically. In Ledgeriano, a posted entry in one business triggers a workflow that creates the matching entry in the other business.

### Do both companies need the same chart of accounts?

No. Template actions name the target accounts directly, and mirror actions translate codes through an account map with exact codes and prefix wildcards such as `41*`.

### What happens if the source entry is reversed?

Reversal is its own trigger. Add a workflow on **entry reversed** to create the counter entry in the target, or reverse the target entry by hand. Nothing changes silently.

### Can a workflow post entries in a company where I am only a bookkeeper?

It can create them, but a role without posting rights means the entry arrives as a draft for someone with the right permission to review and post.

### Can two workflows trigger each other forever?

No. Workflow-created entries only trigger other workflows when chaining is allowed, a workflow never fires on its own output, and chains stop at depth 3.

### Can I automate intercompany entries through the API instead?

Yes. You can post both sides yourself with the [accounting API](https://ledgeriano.com/developers) and idempotency keys. Workflows save you from writing that code.
