acumatica-cli 0.34.0__tar.gz → 0.35.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/PKG-INFO +58 -66
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/README.md +57 -65
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/pyproject.toml +1 -1
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/pyproject.toml.orig +1 -1
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/bootstrap.py +17 -18
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/cli.py +133 -185
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/config.py +120 -68
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/extract.py +12 -12
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/reconcile.py +0 -2
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/seed_catalog.yaml +49 -49
- acumatica_cli-0.35.0/src/acumatica_cli/templates/README.md +60 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/templates/overlays/README.md +13 -21
- acumatica_cli-0.35.0/src/acumatica_cli/templates/overlays/default-24.200.001/README.md +17 -0
- acumatica_cli-0.34.0/src/acumatica_cli/templates/README.md +0 -62
- acumatica_cli-0.34.0/src/acumatica_cli/templates/overlays/default-24.200.001/README.md +0 -12
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/__init__.py +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/bootstrap_plugin.cs +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/bootstrap_project.xml +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/client.py +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/firstlogin.py +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/inventory.py +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/models.py +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/output.py +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/run.py +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/seed.py +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/snapshot_map.yaml +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/state.py +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/baseline/10-subaccounts.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/baseline/20-accounts.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/baseline/40-ledger.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/baseline/50-gl-preferences.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/baseline/60-ledger-company.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/baseline/90-uoms.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/baseline/91-company-packaging.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/bootstrap/company.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/bootstrap/credit-terms.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/bootstrap/features.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/bootstrap/segmented-key.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/05-numbering-sequences.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/10-reason-codes.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/20-in-preferences.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/30-availability-rules.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/40-posting-classes.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/50-warehouse.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/51-warehouse-locations.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/52-warehouse-defaults.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/53-tax-categories.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/54-item-classes.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/56-so-preferences.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/57-po-preferences.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/58-order-types.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/60-ar-preferences.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/61-ap-preferences.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/62-ca-preferences.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/63-cash-account.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/64-payment-methods.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/65-statement-cycles.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/70-vendor-classes.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/71-customer-classes.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/75-vendors.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/76-customers.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/80-stock-items-parts.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/82-stock-items-kits.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/85-kit-specifications.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/90-roles.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/91-users.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/master/92-role-users.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/setup/10-financial-year.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/setup/20-master-calendar.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/setup/30-open-periods.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/config → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-config}/views/10-trial-balance.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/scenario → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-scenario}/10-seed-capital.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/scenario → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-scenario}/20-buy.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/scenario → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-scenario}/30-build.yaml +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/scenario → acumatica_cli-0.35.0/src/acumatica_cli/templates/acu-scenario}/40-sell.yaml +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/templates/env +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/templates/gitignore +0 -0
- {acumatica_cli-0.34.0/src/acumatica_cli/templates/overlays/default-24.200.001/scenario → acumatica_cli-0.35.0/src/acumatica_cli/templates/overlays/default-24.200.001/acu-scenario}/30-build.yaml +0 -0
- {acumatica_cli-0.34.0 → acumatica_cli-0.35.0}/src/acumatica_cli/tenant.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: acumatica-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.35.0
|
|
4
4
|
Summary: Acumatica ERP Config-as-Code: tenant provisioning, baseline config, and reference data
|
|
5
5
|
Author: Konstantin Borovik
|
|
6
6
|
Author-email: Konstantin Borovik <kb@lab5.ca>
|
|
@@ -38,18 +38,18 @@ YAML in git is the source of truth; the live tenant is the target. `apply` is th
|
|
|
38
38
|
|
|
39
39
|
| You can | Command | Effect |
|
|
40
40
|
| ------- | ------- | ------ |
|
|
41
|
-
| Seed a tenant from YAML | `apply` | Idempotent PUT of `config/` into the live tenant |
|
|
41
|
+
| Seed a tenant from YAML | `apply` | Idempotent PUT of `acu-config/` into the live tenant |
|
|
42
42
|
| Detect drift | `diff` | Compare seed YAML to live (exit 2 when they diverge) |
|
|
43
|
-
| Pull live config into YAML | `survey extract` | Inverse of `apply` — GET into `config/{bootstrap,baseline,setup,master}/` |
|
|
44
|
-
| Run transaction scripts | `run` | Forward documents from `scenario/` (capital, buy, build, sell) |
|
|
43
|
+
| Pull live config into YAML | `survey extract` | Inverse of `apply` — GET into `acu-config/{bootstrap,baseline,setup,master}/` |
|
|
44
|
+
| Run transaction scripts | `run` | Forward documents from `acu-scenario/` (capital, buy, build, sell) |
|
|
45
45
|
| Capture derived balances | `state` | Inquire trial-balance etc. into `state/` (not seed) |
|
|
46
46
|
| Create and destroy tenants | `tenant` | SSH control plane: list / create / delete / recycle |
|
|
47
47
|
| Publish the Bootstrap contract | `bootstrap` | REST publish of AcuBootstrap (or `--export` zip for the UI) |
|
|
48
48
|
| Prove a cold rebuild | `tenant create` then `apply` then `run` then `diff` | Compose on a fresh tenant. No wrap command. |
|
|
49
49
|
| Snapshot a site offline | `survey inventory` | SM203520 XML ZIP or `ac.exe export xml` writes `inventory/` |
|
|
50
|
-
| Cross-check snapshot vs seed | `survey reconcile` | `inventory/` plus optional `
|
|
50
|
+
| Cross-check snapshot vs seed | `survey reconcile` | `inventory/` plus optional `--config` writes `findings/` only |
|
|
51
51
|
| Dump the contract schema | `schema` | OpenAPI `swagger.json` for the pinned endpoint |
|
|
52
|
-
| Scaffold a data repo | `config init` | Full `config/`, `scenario/`, `.env` tree |
|
|
52
|
+
| Scaffold a data repo | `config init` | Full `acu-config/`, `acu-scenario/`, `.env` tree |
|
|
53
53
|
| Preflight a target | `config check` | Discovery, secrets, REST, endpoints, SSH |
|
|
54
54
|
|
|
55
55
|
Seed YAML covers features, company, credit terms, subaccounts, chart of accounts, ledger, UOMs, financial year / calendar / periods, numbering sequences, inventory and distribution masters, roles, and users.
|
|
@@ -72,13 +72,13 @@ cd my-erp # edit .env: ACU_PASSWORD, ACU_TENANT
|
|
|
72
72
|
acu config check # read-only preflight
|
|
73
73
|
acu tenant create --login DEV # create + bootstrap (SSH; --id optional)
|
|
74
74
|
# or hosted: acu --tenant DEV bootstrap
|
|
75
|
-
acu --tenant DEV apply config
|
|
76
|
-
acu --tenant DEV run scenario
|
|
77
|
-
acu --tenant DEV diff config
|
|
78
|
-
acu --tenant DEV state
|
|
75
|
+
acu --tenant DEV apply acu-config # seed acu-config/{bootstrap,baseline,setup,master}/
|
|
76
|
+
acu --tenant DEV run acu-scenario # once capital → buy → build → sell
|
|
77
|
+
acu --tenant DEV diff acu-config # prove zero drift (exit 2 on drift)
|
|
78
|
+
acu --tenant DEV state acu-config/views # capture state/ trial-balance
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
apply / diff / run / state require an explicit data path.
|
|
82
82
|
|
|
83
83
|
**Hosted Acumatica (no SSH):** the tenant already exists; set a blank `ACU_SSH=` in `.env`.
|
|
84
84
|
The scaffold omits the key — without it, acu defaults to `Administrator@<ACU_BASE_URL host>` for SSH boxes.
|
|
@@ -88,8 +88,8 @@ acu config init --host customer.acumatica.com my-erp
|
|
|
88
88
|
cd my-erp # edit .env: ACU_TENANT, ACU_PASSWORD; add ACU_SSH=
|
|
89
89
|
acu config check # REST preflight; ssh probe is skipped
|
|
90
90
|
acu --tenant DEV bootstrap # publish AcuBootstrap via REST only
|
|
91
|
-
acu --tenant DEV apply config
|
|
92
|
-
acu --tenant DEV diff config
|
|
91
|
+
acu --tenant DEV apply acu-config
|
|
92
|
+
acu --tenant DEV diff acu-config
|
|
93
93
|
# offline UI fallback when REST publish is blocked:
|
|
94
94
|
acu bootstrap --export AcuBootstrap.zip # import + publish on SM204505
|
|
95
95
|
```
|
|
@@ -110,43 +110,41 @@ acu [--tenant NAME] [--url URL] [--ssh USER@HOST] [--api-version V]
|
|
|
110
110
|
│ └── recycle [--yes] restart site app pool (tenant map + free API slots)
|
|
111
111
|
│
|
|
112
112
|
├── bootstrap [--export PATH] publish AcuBootstrap (REST); --export = offline zip
|
|
113
|
-
├── apply [--dry-run]
|
|
114
|
-
├── diff
|
|
115
|
-
├── run [--dry-run]
|
|
116
|
-
├── state [--out DIR] [--diff] [--assert-unchanged] [--dry-run]
|
|
113
|
+
├── apply [--dry-run] <FILES...> push YAML via REST (idempotent PUT upserts)
|
|
114
|
+
├── diff <FILES...> drift check vs the live tenant (exit 2 on drift)
|
|
115
|
+
├── run [--dry-run] <FILES...> execute transaction scenario YAML (exit 1 on any miss)
|
|
116
|
+
├── state [--out DIR] [--diff] [--assert-unchanged] [--dry-run] <FILES...>
|
|
117
117
|
│ capture derived state into state/ (not seed)
|
|
118
118
|
├── survey existing-tenant dual-reader (never L1 extract/inventory/reconcile)
|
|
119
119
|
│ ├── extract [--out DIR] [--only NAME]... [--force] [--dry-run]
|
|
120
|
-
│ │ inverse of apply into config/{bootstrap,baseline,setup,master}/
|
|
120
|
+
│ │ inverse of apply into acu-config/{bootstrap,baseline,setup,master}/
|
|
121
121
|
│ ├── inventory [--out DIR] [--force] [--dry-run] ARTIFACT
|
|
122
122
|
│ │ offline snapshot artifact → inventory/ (not seed)
|
|
123
123
|
│ └── reconcile [--inventory DIR] [--config DIR] [--out DIR] [--force] [--dry-run]
|
|
124
|
-
│ inventory/ + optional config
|
|
124
|
+
│ inventory/ + optional --config DIR → findings/ only
|
|
125
125
|
├── schema [--out DIR] dump the endpoint's OpenAPI schema (swagger.json)
|
|
126
126
|
│
|
|
127
127
|
└── config configuration ops
|
|
128
|
-
├── init [--host HOST] [DIR] scaffold full data repo (config/, scenario/, .env)
|
|
128
|
+
├── init [--host HOST] [DIR] scaffold full data repo (acu-config/, acu-scenario/, .env)
|
|
129
129
|
├── show print the resolved config as a complete .env
|
|
130
130
|
└── check preflight: discovery, secrets, REST, endpoints, SSH
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
`apply` / `diff` / `run` / `state` require an explicit data path. Zero args print that command's help and do not call HTTP.
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
- `run` defaults to `scenario/`.
|
|
139
|
-
- `state` defaults to `config/views/`; writes go to `state/` (`--out`).
|
|
135
|
+
A dir with SEED_DIRS children (`bootstrap|baseline|setup|master`) expands those subdirs in that order. Typed path is used as given (`acu apply acu-config`, or `acu apply config/` if that dir exists).
|
|
136
|
+
|
|
137
|
+
`--out` defaults: `state` → `state/`; `survey extract` → `acu-config/` (SEED_DIRS into that root); `survey inventory` → `inventory/`; `survey reconcile` → `findings/`; `schema` → `schemas/`.
|
|
140
138
|
|
|
141
139
|
Scenario YAML may use `${current_period}` (host-local `MMyyyy`) on steps, expect params, and `once.present` params.
|
|
142
|
-
`config/views` and `state` keep Period pinned.
|
|
140
|
+
`acu-config/views` and `state` keep Period pinned.
|
|
143
141
|
|
|
144
|
-
`survey extract`
|
|
142
|
+
`survey extract` writes SEED_DIRS into `--out` (default `acu-config/`).
|
|
145
143
|
|
|
146
144
|
`survey inventory` and `survey reconcile` are offline (no REST, SSH, or password).
|
|
147
145
|
`survey inventory` turns an SM203520 Settings XML ZIP or `ac.exe export xml` folder into `inventory/`.
|
|
148
146
|
|
|
149
|
-
`survey reconcile` compares `inventory/` to optional
|
|
147
|
+
`survey reconcile` compares `inventory/` to optional `--config DIR` and writes `findings/` only.
|
|
150
148
|
It never writes seed.
|
|
151
149
|
|
|
152
150
|
Optional `snapshot_map.yaml` (data-repo root, or package defaults) maps DAC tables to catalog entities.
|
|
@@ -166,11 +164,11 @@ Do not confuse them with each other or with `state`:
|
|
|
166
164
|
|
|
167
165
|
| Command | Plane | Input | Writes | Role |
|
|
168
166
|
| ------- | ----- | ----- | ------ | ---- |
|
|
169
|
-
| `survey extract` | REST (live) | tenant via contract API | `config/{bootstrap,baseline,setup,master}/` | Inverse of `apply` — seed YAML |
|
|
167
|
+
| `survey extract` | REST (live) | tenant via contract API | `acu-config/{bootstrap,baseline,setup,master}/` | Inverse of `apply` — seed YAML |
|
|
170
168
|
| `survey inventory` | Offline | SM203520 Settings XML ZIP or `ac.exe export xml` folder | `inventory/` (`summary.yaml` + `tables/`) | Full-table snapshot IR — not seed |
|
|
171
|
-
| `survey reconcile` | Offline | `inventory/` + optional
|
|
172
|
-
| `state` | REST (live) | `config/views/` | `state/` | Derived balances/totals — not seed, not inventory |
|
|
173
|
-
| `apply` | REST (live) | seed YAML under `config/` | tenant | **Sole** tenant writer (keyed PUT) |
|
|
169
|
+
| `survey reconcile` | Offline | `inventory/` + optional `--config DIR` | `findings/` only | Cross-check gaps/deltas — never mutates seed or tenant |
|
|
170
|
+
| `state` | REST (live) | `acu-config/views/` | `state/` | Derived balances/totals — not seed, not inventory |
|
|
171
|
+
| `apply` | REST (live) | seed YAML under `acu-config/` | tenant | **Sole** tenant writer (keyed PUT) |
|
|
174
172
|
|
|
175
173
|
`inventory/` and `findings/` are engagement outputs: not SEED_DIRS, never loaded by `apply`/`diff`, not scaffolded by `config init`.
|
|
176
174
|
Binary `.adb` snapshots are rejected (XML only).
|
|
@@ -178,7 +176,9 @@ Binary `.adb` snapshots are rejected (XML only).
|
|
|
178
176
|
## The data repo
|
|
179
177
|
|
|
180
178
|
Your configuration lives in its own git repo.
|
|
181
|
-
`acu config init` scaffolds a **single full seed** under `config/` (features, company, credit terms, expanded COA, masters) plus lifecycle `scenario/`, observer `config/views/`, and README.
|
|
179
|
+
`acu config init` scaffolds a **single full seed** under `acu-config/` (features, company, credit terms, expanded COA, masters) plus lifecycle `acu-scenario/`, observer `acu-config/views/`, and README.
|
|
180
|
+
|
|
181
|
+
It does not write a customization tree.
|
|
182
182
|
|
|
183
183
|
The Bootstrap endpoint contract is package SoT (`bootstrap_project.xml` inside the CLI — `Bootstrap/1.4.0`).
|
|
184
184
|
`config init` never writes `project.xml`, and data repos must not keep one (a present file hard-errors on bootstrap/publish).
|
|
@@ -187,38 +187,36 @@ There is no `--flavor`.
|
|
|
187
187
|
|
|
188
188
|
| Path | What it holds |
|
|
189
189
|
| ---- | ------------- |
|
|
190
|
-
| `config/bootstrap/` | virgin-tenant config: features, company, credit terms (no `project.xml`) |
|
|
191
|
-
| `config/baseline/` | reference data: subaccounts, COA, ledger, UOMs |
|
|
192
|
-
| `config/setup/` | one-time actions: financial year, master calendar, open periods |
|
|
193
|
-
| `config/master/` | inventory/distribution masters: numbering (`05-…`) before prefs, warehouse, items, parties + Role/User (`90-roles` then `91-users` then `92-role-users`) |
|
|
194
|
-
| `scenario/` | lifecycle txns for `acu run`: once capital, then buy, build, sell |
|
|
195
|
-
| `config/views/` | observer views for `acu state` (`inquire:` / `entity:` / `gi:`; not SEED_DIRS) |
|
|
190
|
+
| `acu-config/bootstrap/` | virgin-tenant config: features, company, credit terms (no `project.xml`) |
|
|
191
|
+
| `acu-config/baseline/` | reference data: subaccounts, COA, ledger, UOMs |
|
|
192
|
+
| `acu-config/setup/` | one-time actions: financial year, master calendar, open periods |
|
|
193
|
+
| `acu-config/master/` | inventory/distribution masters: numbering (`05-…`) before prefs, warehouse, items, parties + Role/User (`90-roles` then `91-users` then `92-role-users`) |
|
|
194
|
+
| `acu-scenario/` | lifecycle txns for `acu run`: once capital, then buy, build, sell |
|
|
195
|
+
| `acu-config/views/` | observer views for `acu state` (`inquire:` / `entity:` / `gi:`; not SEED_DIRS) |
|
|
196
196
|
| `state/` | committed derived-state observations (evidence, not seed; money/qty fixed-point) |
|
|
197
197
|
| `inventory/` | engagement: offline snapshot tables from `acu survey inventory` (not seed; not SEED_DIRS) |
|
|
198
198
|
| `findings/` | engagement: `acu survey reconcile` cross-check output (never apply path) |
|
|
199
199
|
| `.env` | secrets + where (`ACU_BASE_URL`) + pin (`ACU_API_VERSION`) |
|
|
200
200
|
|
|
201
|
-
Legacy data repos may still keep root `bootstrap/`…`master/`; bare `apply`/`diff` prefer `config/` when present and never merge both trees.
|
|
202
|
-
|
|
203
201
|
Files in each directory apply alphabetically; the numbered prefixes (`10-`, `20-`, and so on) encode dependency order.
|
|
204
202
|
Commit seed YAML; keep `.env` out of git (scaffold `.gitignore` already lists it).
|
|
205
203
|
|
|
206
204
|
Seed YAML is state: `apply` upserts it, `diff` proves it.
|
|
207
|
-
`acu survey extract` is the inverse of `apply`: GET live tenant rows into seed YAML under `config/{bootstrap,baseline,setup,master}/` (hard-cut).
|
|
205
|
+
`acu survey extract` is the inverse of `apply`: GET live tenant rows into seed YAML under `acu-config/{bootstrap,baseline,setup,master}/` (hard-cut).
|
|
208
206
|
|
|
209
207
|
Packaged `seed_catalog.yaml` is the sole extract registry (entity, endpoint, keys, file, strip/include, filter-split).
|
|
210
208
|
|
|
211
|
-
Features synthesize to `config/bootstrap/features.yaml`.
|
|
209
|
+
Features synthesize to `acu-config/bootstrap/features.yaml`.
|
|
212
210
|
Existing files skip unless `--force`; empty live sets skip.
|
|
213
211
|
|
|
214
212
|
Row failures continue (exit 1 only if any row failed).
|
|
215
213
|
Drift stays with `diff`.
|
|
216
214
|
|
|
217
215
|
```sh
|
|
218
|
-
acu --tenant DEV survey extract --
|
|
219
|
-
git diff config/ # review extract delta before commit
|
|
220
|
-
acu --tenant DEV apply config
|
|
221
|
-
acu --tenant DEV diff config
|
|
216
|
+
acu --tenant DEV survey extract --force # refresh acu-config/** from live tenant
|
|
217
|
+
git diff acu-config/ # review extract delta before commit
|
|
218
|
+
acu --tenant DEV apply acu-config # replay extracted seed
|
|
219
|
+
acu --tenant DEV diff acu-config # expect exit 0
|
|
222
220
|
```
|
|
223
221
|
### Seed `endpoint:` symbols
|
|
224
222
|
|
|
@@ -286,7 +284,7 @@ Version fan-out is **not** long-running product branches (`acu-25r1`, `acu-26r1`
|
|
|
286
284
|
|
|
287
285
|
| Piece | Role |
|
|
288
286
|
| ----- | ---- |
|
|
289
|
-
| Trunk seed | Canonical `config/` + `scenario/` (newest supported Default half) |
|
|
287
|
+
| Trunk seed | Canonical `acu-config/` + `acu-scenario/` (newest supported Default half) |
|
|
290
288
|
| `.env` pin | Per-checkout `ACU_BASE_URL` + `ACU_API_VERSION` |
|
|
291
289
|
| Optional overlays | Surgical seed deltas keyed by Default half (e.g. `overlays/default-24.200.001/`) |
|
|
292
290
|
| OpenAPI | Live `acu schema` dump only (gitignored); never multi-version swagger trees in package or data repo |
|
|
@@ -294,21 +292,15 @@ Version fan-out is **not** long-running product branches (`acu-25r1`, `acu-26r1`
|
|
|
294
292
|
**Overlays** live under `overlays/default-<api_version>/` (scaffolded by `acu config init`).
|
|
295
293
|
No `--overlay` flag.
|
|
296
294
|
|
|
297
|
-
|
|
298
|
-
`acu run` replaces same-basename scenario files from the pin overlay.
|
|
295
|
+
Pass overlay trees as extra explicit paths when you need them.
|
|
299
296
|
|
|
300
297
|
Pin = resolved `api_version` (`--api-version`, else `ACU_API_VERSION`, else code default).
|
|
301
|
-
Explicit path args disable auto-compose.
|
|
302
298
|
|
|
303
299
|
```sh
|
|
304
|
-
# ACU_API_VERSION=24.200.001
|
|
305
|
-
acu apply
|
|
306
|
-
acu
|
|
307
|
-
acu
|
|
308
|
-
|
|
309
|
-
# explicit path args (no auto) — later path wins same keys
|
|
310
|
-
acu apply config/ overlays/default-24.200.001/
|
|
311
|
-
acu diff config/ overlays/default-24.200.001/
|
|
300
|
+
# ACU_API_VERSION=24.200.001 — this overlay is scenario-only
|
|
301
|
+
acu apply acu-config
|
|
302
|
+
acu diff acu-config
|
|
303
|
+
acu run acu-scenario overlays/default-24.200.001/acu-scenario/
|
|
312
304
|
```
|
|
313
305
|
|
|
314
306
|
Add a future half by creating `overlays/default-<new-half>/` with the
|
|
@@ -391,7 +383,7 @@ Per-bug contract probes fold onto those tenants.
|
|
|
391
383
|
Each run scaffolds a synthetic single-org company from the packaged `acu config init` templates into a temporary directory, copies the real `.env` into it, and runs the installed `acu` binary from there — no data repo, no pre-existing fixtures on the instance.
|
|
392
384
|
|
|
393
385
|
Scratch tenants (`E2E`, `E2EA`, `E2EB`, `E2ESCEN`) are created on the way in and always deleted on the way out, so nothing persists.
|
|
394
|
-
The packaged full `config init` seed (under `config/`) is the only scaffold.
|
|
386
|
+
The packaged full `config init` seed (under `acu-config/`) is the only scaffold.
|
|
395
387
|
|
|
396
388
|
```sh
|
|
397
389
|
gmake e2e # whole tier, three files
|
|
@@ -402,7 +394,7 @@ gmake e2e FILE=test_extract_roundtrip # extract inverse
|
|
|
402
394
|
|
|
403
395
|
### CLI test-seed soak
|
|
404
396
|
|
|
405
|
-
This checkout carries a CLI test seed at repo-root `config/` and `scenario/` (no `config
|
|
397
|
+
This checkout carries a CLI test seed at repo-root `acu-config/` and `acu-scenario/` (no customization YAML under `acu-config/`).
|
|
406
398
|
Soak the live CLI tenant from here with `--tenant ACUCLI`.
|
|
407
399
|
|
|
408
400
|
Never use tenant `CNBN`. Never `cd` the sibling GitOps repo for CLI soak.
|
|
@@ -411,10 +403,10 @@ Never use tenant `CNBN`. Never `cd` the sibling GitOps repo for CLI soak.
|
|
|
411
403
|
That path is not the soak.
|
|
412
404
|
|
|
413
405
|
```sh
|
|
414
|
-
uv run acu --tenant ACUCLI apply
|
|
415
|
-
uv run acu --tenant ACUCLI run
|
|
416
|
-
uv run acu --tenant ACUCLI diff
|
|
417
|
-
uv run acu --tenant ACUCLI state
|
|
406
|
+
uv run acu --tenant ACUCLI apply acu-config
|
|
407
|
+
uv run acu --tenant ACUCLI run acu-scenario
|
|
408
|
+
uv run acu --tenant ACUCLI diff acu-config
|
|
409
|
+
uv run acu --tenant ACUCLI state acu-config/views
|
|
418
410
|
```
|
|
419
411
|
|
|
420
412
|
## License
|
|
@@ -20,18 +20,18 @@ YAML in git is the source of truth; the live tenant is the target. `apply` is th
|
|
|
20
20
|
|
|
21
21
|
| You can | Command | Effect |
|
|
22
22
|
| ------- | ------- | ------ |
|
|
23
|
-
| Seed a tenant from YAML | `apply` | Idempotent PUT of `config/` into the live tenant |
|
|
23
|
+
| Seed a tenant from YAML | `apply` | Idempotent PUT of `acu-config/` into the live tenant |
|
|
24
24
|
| Detect drift | `diff` | Compare seed YAML to live (exit 2 when they diverge) |
|
|
25
|
-
| Pull live config into YAML | `survey extract` | Inverse of `apply` — GET into `config/{bootstrap,baseline,setup,master}/` |
|
|
26
|
-
| Run transaction scripts | `run` | Forward documents from `scenario/` (capital, buy, build, sell) |
|
|
25
|
+
| Pull live config into YAML | `survey extract` | Inverse of `apply` — GET into `acu-config/{bootstrap,baseline,setup,master}/` |
|
|
26
|
+
| Run transaction scripts | `run` | Forward documents from `acu-scenario/` (capital, buy, build, sell) |
|
|
27
27
|
| Capture derived balances | `state` | Inquire trial-balance etc. into `state/` (not seed) |
|
|
28
28
|
| Create and destroy tenants | `tenant` | SSH control plane: list / create / delete / recycle |
|
|
29
29
|
| Publish the Bootstrap contract | `bootstrap` | REST publish of AcuBootstrap (or `--export` zip for the UI) |
|
|
30
30
|
| Prove a cold rebuild | `tenant create` then `apply` then `run` then `diff` | Compose on a fresh tenant. No wrap command. |
|
|
31
31
|
| Snapshot a site offline | `survey inventory` | SM203520 XML ZIP or `ac.exe export xml` writes `inventory/` |
|
|
32
|
-
| Cross-check snapshot vs seed | `survey reconcile` | `inventory/` plus optional `
|
|
32
|
+
| Cross-check snapshot vs seed | `survey reconcile` | `inventory/` plus optional `--config` writes `findings/` only |
|
|
33
33
|
| Dump the contract schema | `schema` | OpenAPI `swagger.json` for the pinned endpoint |
|
|
34
|
-
| Scaffold a data repo | `config init` | Full `config/`, `scenario/`, `.env` tree |
|
|
34
|
+
| Scaffold a data repo | `config init` | Full `acu-config/`, `acu-scenario/`, `.env` tree |
|
|
35
35
|
| Preflight a target | `config check` | Discovery, secrets, REST, endpoints, SSH |
|
|
36
36
|
|
|
37
37
|
Seed YAML covers features, company, credit terms, subaccounts, chart of accounts, ledger, UOMs, financial year / calendar / periods, numbering sequences, inventory and distribution masters, roles, and users.
|
|
@@ -54,13 +54,13 @@ cd my-erp # edit .env: ACU_PASSWORD, ACU_TENANT
|
|
|
54
54
|
acu config check # read-only preflight
|
|
55
55
|
acu tenant create --login DEV # create + bootstrap (SSH; --id optional)
|
|
56
56
|
# or hosted: acu --tenant DEV bootstrap
|
|
57
|
-
acu --tenant DEV apply config
|
|
58
|
-
acu --tenant DEV run scenario
|
|
59
|
-
acu --tenant DEV diff config
|
|
60
|
-
acu --tenant DEV state
|
|
57
|
+
acu --tenant DEV apply acu-config # seed acu-config/{bootstrap,baseline,setup,master}/
|
|
58
|
+
acu --tenant DEV run acu-scenario # once capital → buy → build → sell
|
|
59
|
+
acu --tenant DEV diff acu-config # prove zero drift (exit 2 on drift)
|
|
60
|
+
acu --tenant DEV state acu-config/views # capture state/ trial-balance
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
apply / diff / run / state require an explicit data path.
|
|
64
64
|
|
|
65
65
|
**Hosted Acumatica (no SSH):** the tenant already exists; set a blank `ACU_SSH=` in `.env`.
|
|
66
66
|
The scaffold omits the key — without it, acu defaults to `Administrator@<ACU_BASE_URL host>` for SSH boxes.
|
|
@@ -70,8 +70,8 @@ acu config init --host customer.acumatica.com my-erp
|
|
|
70
70
|
cd my-erp # edit .env: ACU_TENANT, ACU_PASSWORD; add ACU_SSH=
|
|
71
71
|
acu config check # REST preflight; ssh probe is skipped
|
|
72
72
|
acu --tenant DEV bootstrap # publish AcuBootstrap via REST only
|
|
73
|
-
acu --tenant DEV apply config
|
|
74
|
-
acu --tenant DEV diff config
|
|
73
|
+
acu --tenant DEV apply acu-config
|
|
74
|
+
acu --tenant DEV diff acu-config
|
|
75
75
|
# offline UI fallback when REST publish is blocked:
|
|
76
76
|
acu bootstrap --export AcuBootstrap.zip # import + publish on SM204505
|
|
77
77
|
```
|
|
@@ -92,43 +92,41 @@ acu [--tenant NAME] [--url URL] [--ssh USER@HOST] [--api-version V]
|
|
|
92
92
|
│ └── recycle [--yes] restart site app pool (tenant map + free API slots)
|
|
93
93
|
│
|
|
94
94
|
├── bootstrap [--export PATH] publish AcuBootstrap (REST); --export = offline zip
|
|
95
|
-
├── apply [--dry-run]
|
|
96
|
-
├── diff
|
|
97
|
-
├── run [--dry-run]
|
|
98
|
-
├── state [--out DIR] [--diff] [--assert-unchanged] [--dry-run]
|
|
95
|
+
├── apply [--dry-run] <FILES...> push YAML via REST (idempotent PUT upserts)
|
|
96
|
+
├── diff <FILES...> drift check vs the live tenant (exit 2 on drift)
|
|
97
|
+
├── run [--dry-run] <FILES...> execute transaction scenario YAML (exit 1 on any miss)
|
|
98
|
+
├── state [--out DIR] [--diff] [--assert-unchanged] [--dry-run] <FILES...>
|
|
99
99
|
│ capture derived state into state/ (not seed)
|
|
100
100
|
├── survey existing-tenant dual-reader (never L1 extract/inventory/reconcile)
|
|
101
101
|
│ ├── extract [--out DIR] [--only NAME]... [--force] [--dry-run]
|
|
102
|
-
│ │ inverse of apply into config/{bootstrap,baseline,setup,master}/
|
|
102
|
+
│ │ inverse of apply into acu-config/{bootstrap,baseline,setup,master}/
|
|
103
103
|
│ ├── inventory [--out DIR] [--force] [--dry-run] ARTIFACT
|
|
104
104
|
│ │ offline snapshot artifact → inventory/ (not seed)
|
|
105
105
|
│ └── reconcile [--inventory DIR] [--config DIR] [--out DIR] [--force] [--dry-run]
|
|
106
|
-
│ inventory/ + optional config
|
|
106
|
+
│ inventory/ + optional --config DIR → findings/ only
|
|
107
107
|
├── schema [--out DIR] dump the endpoint's OpenAPI schema (swagger.json)
|
|
108
108
|
│
|
|
109
109
|
└── config configuration ops
|
|
110
|
-
├── init [--host HOST] [DIR] scaffold full data repo (config/, scenario/, .env)
|
|
110
|
+
├── init [--host HOST] [DIR] scaffold full data repo (acu-config/, acu-scenario/, .env)
|
|
111
111
|
├── show print the resolved config as a complete .env
|
|
112
112
|
└── check preflight: discovery, secrets, REST, endpoints, SSH
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
`apply` / `diff` / `run` / `state` require an explicit data path. Zero args print that command's help and do not call HTTP.
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
- `run` defaults to `scenario/`.
|
|
121
|
-
- `state` defaults to `config/views/`; writes go to `state/` (`--out`).
|
|
117
|
+
A dir with SEED_DIRS children (`bootstrap|baseline|setup|master`) expands those subdirs in that order. Typed path is used as given (`acu apply acu-config`, or `acu apply config/` if that dir exists).
|
|
118
|
+
|
|
119
|
+
`--out` defaults: `state` → `state/`; `survey extract` → `acu-config/` (SEED_DIRS into that root); `survey inventory` → `inventory/`; `survey reconcile` → `findings/`; `schema` → `schemas/`.
|
|
122
120
|
|
|
123
121
|
Scenario YAML may use `${current_period}` (host-local `MMyyyy`) on steps, expect params, and `once.present` params.
|
|
124
|
-
`config/views` and `state` keep Period pinned.
|
|
122
|
+
`acu-config/views` and `state` keep Period pinned.
|
|
125
123
|
|
|
126
|
-
`survey extract`
|
|
124
|
+
`survey extract` writes SEED_DIRS into `--out` (default `acu-config/`).
|
|
127
125
|
|
|
128
126
|
`survey inventory` and `survey reconcile` are offline (no REST, SSH, or password).
|
|
129
127
|
`survey inventory` turns an SM203520 Settings XML ZIP or `ac.exe export xml` folder into `inventory/`.
|
|
130
128
|
|
|
131
|
-
`survey reconcile` compares `inventory/` to optional
|
|
129
|
+
`survey reconcile` compares `inventory/` to optional `--config DIR` and writes `findings/` only.
|
|
132
130
|
It never writes seed.
|
|
133
131
|
|
|
134
132
|
Optional `snapshot_map.yaml` (data-repo root, or package defaults) maps DAC tables to catalog entities.
|
|
@@ -148,11 +146,11 @@ Do not confuse them with each other or with `state`:
|
|
|
148
146
|
|
|
149
147
|
| Command | Plane | Input | Writes | Role |
|
|
150
148
|
| ------- | ----- | ----- | ------ | ---- |
|
|
151
|
-
| `survey extract` | REST (live) | tenant via contract API | `config/{bootstrap,baseline,setup,master}/` | Inverse of `apply` — seed YAML |
|
|
149
|
+
| `survey extract` | REST (live) | tenant via contract API | `acu-config/{bootstrap,baseline,setup,master}/` | Inverse of `apply` — seed YAML |
|
|
152
150
|
| `survey inventory` | Offline | SM203520 Settings XML ZIP or `ac.exe export xml` folder | `inventory/` (`summary.yaml` + `tables/`) | Full-table snapshot IR — not seed |
|
|
153
|
-
| `survey reconcile` | Offline | `inventory/` + optional
|
|
154
|
-
| `state` | REST (live) | `config/views/` | `state/` | Derived balances/totals — not seed, not inventory |
|
|
155
|
-
| `apply` | REST (live) | seed YAML under `config/` | tenant | **Sole** tenant writer (keyed PUT) |
|
|
151
|
+
| `survey reconcile` | Offline | `inventory/` + optional `--config DIR` | `findings/` only | Cross-check gaps/deltas — never mutates seed or tenant |
|
|
152
|
+
| `state` | REST (live) | `acu-config/views/` | `state/` | Derived balances/totals — not seed, not inventory |
|
|
153
|
+
| `apply` | REST (live) | seed YAML under `acu-config/` | tenant | **Sole** tenant writer (keyed PUT) |
|
|
156
154
|
|
|
157
155
|
`inventory/` and `findings/` are engagement outputs: not SEED_DIRS, never loaded by `apply`/`diff`, not scaffolded by `config init`.
|
|
158
156
|
Binary `.adb` snapshots are rejected (XML only).
|
|
@@ -160,7 +158,9 @@ Binary `.adb` snapshots are rejected (XML only).
|
|
|
160
158
|
## The data repo
|
|
161
159
|
|
|
162
160
|
Your configuration lives in its own git repo.
|
|
163
|
-
`acu config init` scaffolds a **single full seed** under `config/` (features, company, credit terms, expanded COA, masters) plus lifecycle `scenario/`, observer `config/views/`, and README.
|
|
161
|
+
`acu config init` scaffolds a **single full seed** under `acu-config/` (features, company, credit terms, expanded COA, masters) plus lifecycle `acu-scenario/`, observer `acu-config/views/`, and README.
|
|
162
|
+
|
|
163
|
+
It does not write a customization tree.
|
|
164
164
|
|
|
165
165
|
The Bootstrap endpoint contract is package SoT (`bootstrap_project.xml` inside the CLI — `Bootstrap/1.4.0`).
|
|
166
166
|
`config init` never writes `project.xml`, and data repos must not keep one (a present file hard-errors on bootstrap/publish).
|
|
@@ -169,38 +169,36 @@ There is no `--flavor`.
|
|
|
169
169
|
|
|
170
170
|
| Path | What it holds |
|
|
171
171
|
| ---- | ------------- |
|
|
172
|
-
| `config/bootstrap/` | virgin-tenant config: features, company, credit terms (no `project.xml`) |
|
|
173
|
-
| `config/baseline/` | reference data: subaccounts, COA, ledger, UOMs |
|
|
174
|
-
| `config/setup/` | one-time actions: financial year, master calendar, open periods |
|
|
175
|
-
| `config/master/` | inventory/distribution masters: numbering (`05-…`) before prefs, warehouse, items, parties + Role/User (`90-roles` then `91-users` then `92-role-users`) |
|
|
176
|
-
| `scenario/` | lifecycle txns for `acu run`: once capital, then buy, build, sell |
|
|
177
|
-
| `config/views/` | observer views for `acu state` (`inquire:` / `entity:` / `gi:`; not SEED_DIRS) |
|
|
172
|
+
| `acu-config/bootstrap/` | virgin-tenant config: features, company, credit terms (no `project.xml`) |
|
|
173
|
+
| `acu-config/baseline/` | reference data: subaccounts, COA, ledger, UOMs |
|
|
174
|
+
| `acu-config/setup/` | one-time actions: financial year, master calendar, open periods |
|
|
175
|
+
| `acu-config/master/` | inventory/distribution masters: numbering (`05-…`) before prefs, warehouse, items, parties + Role/User (`90-roles` then `91-users` then `92-role-users`) |
|
|
176
|
+
| `acu-scenario/` | lifecycle txns for `acu run`: once capital, then buy, build, sell |
|
|
177
|
+
| `acu-config/views/` | observer views for `acu state` (`inquire:` / `entity:` / `gi:`; not SEED_DIRS) |
|
|
178
178
|
| `state/` | committed derived-state observations (evidence, not seed; money/qty fixed-point) |
|
|
179
179
|
| `inventory/` | engagement: offline snapshot tables from `acu survey inventory` (not seed; not SEED_DIRS) |
|
|
180
180
|
| `findings/` | engagement: `acu survey reconcile` cross-check output (never apply path) |
|
|
181
181
|
| `.env` | secrets + where (`ACU_BASE_URL`) + pin (`ACU_API_VERSION`) |
|
|
182
182
|
|
|
183
|
-
Legacy data repos may still keep root `bootstrap/`…`master/`; bare `apply`/`diff` prefer `config/` when present and never merge both trees.
|
|
184
|
-
|
|
185
183
|
Files in each directory apply alphabetically; the numbered prefixes (`10-`, `20-`, and so on) encode dependency order.
|
|
186
184
|
Commit seed YAML; keep `.env` out of git (scaffold `.gitignore` already lists it).
|
|
187
185
|
|
|
188
186
|
Seed YAML is state: `apply` upserts it, `diff` proves it.
|
|
189
|
-
`acu survey extract` is the inverse of `apply`: GET live tenant rows into seed YAML under `config/{bootstrap,baseline,setup,master}/` (hard-cut).
|
|
187
|
+
`acu survey extract` is the inverse of `apply`: GET live tenant rows into seed YAML under `acu-config/{bootstrap,baseline,setup,master}/` (hard-cut).
|
|
190
188
|
|
|
191
189
|
Packaged `seed_catalog.yaml` is the sole extract registry (entity, endpoint, keys, file, strip/include, filter-split).
|
|
192
190
|
|
|
193
|
-
Features synthesize to `config/bootstrap/features.yaml`.
|
|
191
|
+
Features synthesize to `acu-config/bootstrap/features.yaml`.
|
|
194
192
|
Existing files skip unless `--force`; empty live sets skip.
|
|
195
193
|
|
|
196
194
|
Row failures continue (exit 1 only if any row failed).
|
|
197
195
|
Drift stays with `diff`.
|
|
198
196
|
|
|
199
197
|
```sh
|
|
200
|
-
acu --tenant DEV survey extract --
|
|
201
|
-
git diff config/ # review extract delta before commit
|
|
202
|
-
acu --tenant DEV apply config
|
|
203
|
-
acu --tenant DEV diff config
|
|
198
|
+
acu --tenant DEV survey extract --force # refresh acu-config/** from live tenant
|
|
199
|
+
git diff acu-config/ # review extract delta before commit
|
|
200
|
+
acu --tenant DEV apply acu-config # replay extracted seed
|
|
201
|
+
acu --tenant DEV diff acu-config # expect exit 0
|
|
204
202
|
```
|
|
205
203
|
### Seed `endpoint:` symbols
|
|
206
204
|
|
|
@@ -268,7 +266,7 @@ Version fan-out is **not** long-running product branches (`acu-25r1`, `acu-26r1`
|
|
|
268
266
|
|
|
269
267
|
| Piece | Role |
|
|
270
268
|
| ----- | ---- |
|
|
271
|
-
| Trunk seed | Canonical `config/` + `scenario/` (newest supported Default half) |
|
|
269
|
+
| Trunk seed | Canonical `acu-config/` + `acu-scenario/` (newest supported Default half) |
|
|
272
270
|
| `.env` pin | Per-checkout `ACU_BASE_URL` + `ACU_API_VERSION` |
|
|
273
271
|
| Optional overlays | Surgical seed deltas keyed by Default half (e.g. `overlays/default-24.200.001/`) |
|
|
274
272
|
| OpenAPI | Live `acu schema` dump only (gitignored); never multi-version swagger trees in package or data repo |
|
|
@@ -276,21 +274,15 @@ Version fan-out is **not** long-running product branches (`acu-25r1`, `acu-26r1`
|
|
|
276
274
|
**Overlays** live under `overlays/default-<api_version>/` (scaffolded by `acu config init`).
|
|
277
275
|
No `--overlay` flag.
|
|
278
276
|
|
|
279
|
-
|
|
280
|
-
`acu run` replaces same-basename scenario files from the pin overlay.
|
|
277
|
+
Pass overlay trees as extra explicit paths when you need them.
|
|
281
278
|
|
|
282
279
|
Pin = resolved `api_version` (`--api-version`, else `ACU_API_VERSION`, else code default).
|
|
283
|
-
Explicit path args disable auto-compose.
|
|
284
280
|
|
|
285
281
|
```sh
|
|
286
|
-
# ACU_API_VERSION=24.200.001
|
|
287
|
-
acu apply
|
|
288
|
-
acu
|
|
289
|
-
acu
|
|
290
|
-
|
|
291
|
-
# explicit path args (no auto) — later path wins same keys
|
|
292
|
-
acu apply config/ overlays/default-24.200.001/
|
|
293
|
-
acu diff config/ overlays/default-24.200.001/
|
|
282
|
+
# ACU_API_VERSION=24.200.001 — this overlay is scenario-only
|
|
283
|
+
acu apply acu-config
|
|
284
|
+
acu diff acu-config
|
|
285
|
+
acu run acu-scenario overlays/default-24.200.001/acu-scenario/
|
|
294
286
|
```
|
|
295
287
|
|
|
296
288
|
Add a future half by creating `overlays/default-<new-half>/` with the
|
|
@@ -373,7 +365,7 @@ Per-bug contract probes fold onto those tenants.
|
|
|
373
365
|
Each run scaffolds a synthetic single-org company from the packaged `acu config init` templates into a temporary directory, copies the real `.env` into it, and runs the installed `acu` binary from there — no data repo, no pre-existing fixtures on the instance.
|
|
374
366
|
|
|
375
367
|
Scratch tenants (`E2E`, `E2EA`, `E2EB`, `E2ESCEN`) are created on the way in and always deleted on the way out, so nothing persists.
|
|
376
|
-
The packaged full `config init` seed (under `config/`) is the only scaffold.
|
|
368
|
+
The packaged full `config init` seed (under `acu-config/`) is the only scaffold.
|
|
377
369
|
|
|
378
370
|
```sh
|
|
379
371
|
gmake e2e # whole tier, three files
|
|
@@ -384,7 +376,7 @@ gmake e2e FILE=test_extract_roundtrip # extract inverse
|
|
|
384
376
|
|
|
385
377
|
### CLI test-seed soak
|
|
386
378
|
|
|
387
|
-
This checkout carries a CLI test seed at repo-root `config/` and `scenario/` (no `config
|
|
379
|
+
This checkout carries a CLI test seed at repo-root `acu-config/` and `acu-scenario/` (no customization YAML under `acu-config/`).
|
|
388
380
|
Soak the live CLI tenant from here with `--tenant ACUCLI`.
|
|
389
381
|
|
|
390
382
|
Never use tenant `CNBN`. Never `cd` the sibling GitOps repo for CLI soak.
|
|
@@ -393,10 +385,10 @@ Never use tenant `CNBN`. Never `cd` the sibling GitOps repo for CLI soak.
|
|
|
393
385
|
That path is not the soak.
|
|
394
386
|
|
|
395
387
|
```sh
|
|
396
|
-
uv run acu --tenant ACUCLI apply
|
|
397
|
-
uv run acu --tenant ACUCLI run
|
|
398
|
-
uv run acu --tenant ACUCLI diff
|
|
399
|
-
uv run acu --tenant ACUCLI state
|
|
388
|
+
uv run acu --tenant ACUCLI apply acu-config
|
|
389
|
+
uv run acu --tenant ACUCLI run acu-scenario
|
|
390
|
+
uv run acu --tenant ACUCLI diff acu-config
|
|
391
|
+
uv run acu --tenant ACUCLI state acu-config/views
|
|
400
392
|
```
|
|
401
393
|
|
|
402
394
|
## License
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "acumatica-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.35.0"
|
|
4
4
|
description = "Acumatica ERP Config-as-Code: tenant provisioning, baseline config, and reference data"
|
|
5
5
|
authors = [{ name = "Konstantin Borovik", email = "kb@lab5.ca" }]
|
|
6
6
|
license = "PolyForm-Noncommercial-1.0.0"
|
|
@@ -10,7 +10,8 @@ endpoint exposes the seeding surface (serialization verified T12).
|
|
|
10
10
|
|
|
11
11
|
Bootstrap endpoint contract is package SoT (V2/V21/T178): always the
|
|
12
12
|
packaged full company ``bootstrap_project.xml`` (``Bootstrap/1.11.0``).
|
|
13
|
-
Data-repo ``config/bootstrap/project.xml`` or
|
|
13
|
+
Data-repo ``acu-config/bootstrap/project.xml`` (or leftover
|
|
14
|
+
``config/bootstrap/project.xml`` / ``bootstrap/project.xml``) is
|
|
14
15
|
not a seed — present → hard error naming package SoT (no dual contract line).
|
|
15
16
|
|
|
16
17
|
Customization publishes are tenant-scoped, so the package must be published
|
|
@@ -19,9 +20,8 @@ digest embedded in the published package's description against the package
|
|
|
19
20
|
built now, and the plugin's UpdateDatabase is a keyed update on re-run.
|
|
20
21
|
|
|
21
22
|
The feature set the plugin enables is data, not code (V2): load_features()
|
|
22
|
-
reads config/bootstrap/features.yaml
|
|
23
|
-
|
|
24
|
-
source at build time. Features still dual-resolve; the contract does not.
|
|
23
|
+
reads acu-config/bootstrap/features.yaml only (absent -> the built-in six)
|
|
24
|
+
and package_zip() splices it into the plugin source at build time.
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
27
|
import hashlib
|
|
@@ -60,11 +60,9 @@ FEATURES_SENTINEL = "/*ACU_FEATURES*/"
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
def _bootstrap_file(root: Path, name: str) -> Path | None:
|
|
63
|
-
"""Resolve
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return path
|
|
67
|
-
return None
|
|
63
|
+
"""Resolve ``acu-config/bootstrap/<name>`` only (V60/V30)."""
|
|
64
|
+
path = root / "acu-config" / "bootstrap" / name
|
|
65
|
+
return path if path.is_file() else None
|
|
68
66
|
|
|
69
67
|
|
|
70
68
|
def packaged_contract_xml() -> bytes:
|
|
@@ -81,6 +79,7 @@ def _reject_data_repo_contract(root: Path | None) -> None:
|
|
|
81
79
|
if root is None:
|
|
82
80
|
return
|
|
83
81
|
for path in (
|
|
82
|
+
root / "acu-config" / "bootstrap" / "project.xml",
|
|
84
83
|
root / "config" / "bootstrap" / "project.xml",
|
|
85
84
|
root / "bootstrap" / "project.xml",
|
|
86
85
|
):
|
|
@@ -95,9 +94,9 @@ def load_contract_xml(root: Path | None = None) -> bytes:
|
|
|
95
94
|
"""Active contract bytes: always the packaged full company contract.
|
|
96
95
|
|
|
97
96
|
``root`` is the data-repo discovery root (the dir holding ``.env``).
|
|
98
|
-
Present ``config/bootstrap/project.xml`` or
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
Present ``acu-config/bootstrap/project.xml`` (or leftover
|
|
98
|
+
``config/bootstrap/project.xml`` / ``bootstrap/project.xml``) →
|
|
99
|
+
hard error naming package SoT (V2/V21/T178).
|
|
101
100
|
"""
|
|
102
101
|
_reject_data_repo_contract(root)
|
|
103
102
|
return packaged_contract_xml()
|
|
@@ -122,13 +121,13 @@ PACKAGE_DESCRIPTION = ET.fromstring(packaged_contract_xml()).get("description",
|
|
|
122
121
|
|
|
123
122
|
|
|
124
123
|
def load_features(root: Path) -> list[str]:
|
|
125
|
-
"""FeaturesSet property names from config/
|
|
124
|
+
"""FeaturesSet property names from ``acu-config/bootstrap/features.yaml``.
|
|
126
125
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
plausible property names here (they are spliced into C#
|
|
130
|
-
whether each matches a real FeaturesSet property only
|
|
131
|
-
tell — it logs the strays at publish time
|
|
126
|
+
Absent file -> the built-in six (SPEC I.data). Root ``bootstrap/`` and
|
|
127
|
+
leftover ``config/bootstrap/`` are not consulted (V60). Names are
|
|
128
|
+
validated as plausible property names here (they are spliced into C#
|
|
129
|
+
string literals); whether each matches a real FeaturesSet property only
|
|
130
|
+
the plugin can tell — it logs the strays at publish time.
|
|
132
131
|
"""
|
|
133
132
|
path = _bootstrap_file(root, "features.yaml")
|
|
134
133
|
if path is None:
|