acumatica-cli 0.13.1__tar.gz → 0.14.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.13.1 → acumatica_cli-0.14.0}/PKG-INFO +9 -9
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/README.md +8 -8
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/pyproject.toml +1 -1
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/cli.py +20 -22
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/client.py +1 -1
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/config.py +2 -2
- acumatica_cli-0.13.1/src/acumatica_cli/snapshot.py → acumatica_cli-0.14.0/src/acumatica_cli/state.py +9 -9
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/README.md +4 -4
- {acumatica_cli-0.13.1/src/acumatica_cli/templates/config/snapshot → acumatica_cli-0.14.0/src/acumatica_cli/templates/config/views}/10-trial-balance.yaml +2 -2
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/__init__.py +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/bootstrap.py +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/bootstrap_plugin.cs +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/bootstrap_project.xml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/extract.py +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/extract_manifest.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/firstlogin.py +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/models.py +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/output.py +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/run.py +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/seed.py +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/target.py +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/baseline/10-subaccounts.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/baseline/20-accounts.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/baseline/40-ledger.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/baseline/50-gl-preferences.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/baseline/60-ledger-company.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/baseline/90-uoms.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/baseline/91-company-packaging.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/bootstrap/company.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/bootstrap/credit-terms.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/bootstrap/features.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/10-reason-codes.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/20-in-preferences.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/30-availability-rules.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/40-posting-classes.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/50-warehouse.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/51-warehouse-locations.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/52-warehouse-defaults.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/53-tax-categories.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/54-item-classes.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/56-so-preferences.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/57-po-preferences.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/58-order-types.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/60-ar-preferences.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/61-ap-preferences.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/62-ca-preferences.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/63-cash-account.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/64-payment-methods.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/65-statement-cycles.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/70-vendor-classes.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/71-customer-classes.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/75-vendors.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/76-customers.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/80-stock-items-parts.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/82-stock-items-kits.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/master/85-kit-specifications.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/setup/10-financial-year.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/setup/20-master-calendar.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/config/setup/30-open-periods.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/env +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/gitignore +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/scenario/10-seed-capital.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/scenario/20-buy.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/scenario/30-build.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/scenario/40-sell.yaml +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/target +0 -0
- {acumatica_cli-0.13.1 → acumatica_cli-0.14.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.14.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>
|
|
@@ -48,7 +48,7 @@ acu tenant create --id 3 --login DEV # create the tenant + bootstrap it (nee
|
|
|
48
48
|
acu --tenant DEV apply config/ # seed config/{bootstrap,baseline,setup,master}/
|
|
49
49
|
acu --tenant DEV run scenario/ # once capital → buy → build → sell
|
|
50
50
|
acu --tenant DEV diff config/ # prove zero drift (exit 2 on drift)
|
|
51
|
-
acu --tenant DEV
|
|
51
|
+
acu --tenant DEV state # capture state/ trial-balance
|
|
52
52
|
# warm: capital once-skips; Owner Capital stays 50000 (not 100000)
|
|
53
53
|
acu --tenant DEV run scenario/
|
|
54
54
|
```
|
|
@@ -85,7 +85,7 @@ acu [--tenant NAME] [--url URL] [--ssh USER@HOST] [--api-version V]
|
|
|
85
85
|
├── apply [--dry-run] [FILES...] push YAML via REST (idempotent PUT upserts)
|
|
86
86
|
├── diff [FILES...] drift check vs the live tenant (exit 2 on drift)
|
|
87
87
|
├── run [--dry-run] [FILES...] execute transaction scenario YAML (exit 1 on any miss)
|
|
88
|
-
├──
|
|
88
|
+
├── state [--out DIR] [--diff] [--assert-unchanged] [--dry-run] [FILES...]
|
|
89
89
|
│ capture derived state into state/ (not seed)
|
|
90
90
|
├── extract [--out DIR] [--only NAME]... [--force] [--dry-run]
|
|
91
91
|
│ dump live tenant state as seed YAML (inverse of apply)
|
|
@@ -100,14 +100,14 @@ acu [--tenant NAME] [--url URL] [--ssh USER@HOST] [--api-version V]
|
|
|
100
100
|
`apply` and `diff` without FILES prefer `config/<name>/` when any seed child exists under `config/`; otherwise root `bootstrap/`, `baseline/`, `setup/`, then `master/` when present.
|
|
101
101
|
A path like `config/` expands nested seed dirs in that fixed order.
|
|
102
102
|
`run` without FILES defaults to `scenario/`.
|
|
103
|
-
`
|
|
103
|
+
`state` without FILES defaults to `config/views/`; writes go to `state/` (`--out`).
|
|
104
104
|
`acu --completion` emits a completion script for bash, zsh, or fish — source it from your shell profile.
|
|
105
105
|
Run `acu <command> --help` for details on any command.
|
|
106
106
|
|
|
107
107
|
## The data repo
|
|
108
108
|
|
|
109
109
|
Your configuration lives in its own git repo.
|
|
110
|
-
`acu config init` scaffolds a **single full seed** under `config/` (Bootstrap `project.xml` at `Bootstrap/1.0.0`, expanded COA, masters) plus lifecycle `scenario/`, observer `config/
|
|
110
|
+
`acu config init` scaffolds a **single full seed** under `config/` (Bootstrap `project.xml` at `Bootstrap/1.0.0`, expanded COA, masters) plus lifecycle `scenario/`, observer `config/views/`, and README. There is no `--flavor`.
|
|
111
111
|
|
|
112
112
|
| Path | What it holds |
|
|
113
113
|
| ---- | ------------- |
|
|
@@ -116,7 +116,7 @@ Your configuration lives in its own git repo.
|
|
|
116
116
|
| `config/setup/` | one-time actions: financial year, master calendar, open periods |
|
|
117
117
|
| `config/master/` | inventory/distribution masters (prefs, warehouse, items, parties) |
|
|
118
118
|
| `scenario/` | lifecycle txns for `acu run`: once capital, then buy, build, sell |
|
|
119
|
-
| `config/
|
|
119
|
+
| `config/views/` | observer views for `acu state` (`inquire:` / `entity:` / `gi:`; not SEED_DIRS) |
|
|
120
120
|
| `state/` | committed derived-state observations (evidence, not seed; money/qty fixed-point) |
|
|
121
121
|
| `target.yaml` | committed verified matrix: `erp` + `default_api` (what, not where) |
|
|
122
122
|
| `.env` | where to apply and who signs in, every key an `ACU_*` variable |
|
|
@@ -132,9 +132,9 @@ Scenario YAML is different — it describes transactions that flow forward.
|
|
|
132
132
|
`acu run` executes each step in order (`put`, `action`, `wait`, `get`), captures server-assigned document numbers into `${var}` references for later steps, and checks `expect:` assertions as deltas against a pre-run snapshot, so additive scenarios re-run safely on a warm tenant.
|
|
133
133
|
`once: true` scenarios declare a `present` inquire-absolute gate; when the probe already holds, the CLI prints `skip <path> (once: already present)` and runs neither steps nor expects (Owner Capital does not restack).
|
|
134
134
|
|
|
135
|
-
`acu
|
|
135
|
+
`acu state` is the third observation path: it captures live derived state (balances) into `state/` for git review. It is not `extract` (config seed) and not `diff` (desired vs actual config). Packaged golden is trial-balance via contract `inquire:` (`EndingBalance` fixed-point); inventory-summary is not golden this pass. `gi:` stays optional when a GI is V12-verified and **Expose via OData** is on (`params` fail-closed vs `$metadata`). After a cold `acu run scenario/ && acu state`, warm `acu run scenario/10-seed-capital.yaml && acu state --assert-unchanged` is the once-class gate (full scenario re-run is additive and moves cash observations on the TB).
|
|
136
136
|
|
|
137
|
-
**Migration (
|
|
137
|
+
**Migration (T112–T114 hard-cut):** CLI verb is `state` only (no `snapshot` alias). Bare defaults are `config/views/` (views) and `state/` (observations). Prior `config/snapshot/` and root `snapshot/` / `snapshots/` are not fallbacks — move views to `config/views/` or pass explicit path args.
|
|
138
138
|
|
|
139
139
|
### Seed `endpoint:` symbols
|
|
140
140
|
|
|
@@ -308,7 +308,7 @@ The packaged full `config init` seed (under `config/`) is the only scaffold.
|
|
|
308
308
|
```sh
|
|
309
309
|
gmake e2e # whole tier, about 20 minutes
|
|
310
310
|
gmake e2e FILE=test_provision_lifecycle # apply/diff focus
|
|
311
|
-
gmake e2e FILE=test_scenario_lifecycle # scenario +
|
|
311
|
+
gmake e2e FILE=test_scenario_lifecycle # scenario + state focus
|
|
312
312
|
```
|
|
313
313
|
|
|
314
314
|
## License
|
|
@@ -30,7 +30,7 @@ acu tenant create --id 3 --login DEV # create the tenant + bootstrap it (nee
|
|
|
30
30
|
acu --tenant DEV apply config/ # seed config/{bootstrap,baseline,setup,master}/
|
|
31
31
|
acu --tenant DEV run scenario/ # once capital → buy → build → sell
|
|
32
32
|
acu --tenant DEV diff config/ # prove zero drift (exit 2 on drift)
|
|
33
|
-
acu --tenant DEV
|
|
33
|
+
acu --tenant DEV state # capture state/ trial-balance
|
|
34
34
|
# warm: capital once-skips; Owner Capital stays 50000 (not 100000)
|
|
35
35
|
acu --tenant DEV run scenario/
|
|
36
36
|
```
|
|
@@ -67,7 +67,7 @@ acu [--tenant NAME] [--url URL] [--ssh USER@HOST] [--api-version V]
|
|
|
67
67
|
├── apply [--dry-run] [FILES...] push YAML via REST (idempotent PUT upserts)
|
|
68
68
|
├── diff [FILES...] drift check vs the live tenant (exit 2 on drift)
|
|
69
69
|
├── run [--dry-run] [FILES...] execute transaction scenario YAML (exit 1 on any miss)
|
|
70
|
-
├──
|
|
70
|
+
├── state [--out DIR] [--diff] [--assert-unchanged] [--dry-run] [FILES...]
|
|
71
71
|
│ capture derived state into state/ (not seed)
|
|
72
72
|
├── extract [--out DIR] [--only NAME]... [--force] [--dry-run]
|
|
73
73
|
│ dump live tenant state as seed YAML (inverse of apply)
|
|
@@ -82,14 +82,14 @@ acu [--tenant NAME] [--url URL] [--ssh USER@HOST] [--api-version V]
|
|
|
82
82
|
`apply` and `diff` without FILES prefer `config/<name>/` when any seed child exists under `config/`; otherwise root `bootstrap/`, `baseline/`, `setup/`, then `master/` when present.
|
|
83
83
|
A path like `config/` expands nested seed dirs in that fixed order.
|
|
84
84
|
`run` without FILES defaults to `scenario/`.
|
|
85
|
-
`
|
|
85
|
+
`state` without FILES defaults to `config/views/`; writes go to `state/` (`--out`).
|
|
86
86
|
`acu --completion` emits a completion script for bash, zsh, or fish — source it from your shell profile.
|
|
87
87
|
Run `acu <command> --help` for details on any command.
|
|
88
88
|
|
|
89
89
|
## The data repo
|
|
90
90
|
|
|
91
91
|
Your configuration lives in its own git repo.
|
|
92
|
-
`acu config init` scaffolds a **single full seed** under `config/` (Bootstrap `project.xml` at `Bootstrap/1.0.0`, expanded COA, masters) plus lifecycle `scenario/`, observer `config/
|
|
92
|
+
`acu config init` scaffolds a **single full seed** under `config/` (Bootstrap `project.xml` at `Bootstrap/1.0.0`, expanded COA, masters) plus lifecycle `scenario/`, observer `config/views/`, and README. There is no `--flavor`.
|
|
93
93
|
|
|
94
94
|
| Path | What it holds |
|
|
95
95
|
| ---- | ------------- |
|
|
@@ -98,7 +98,7 @@ Your configuration lives in its own git repo.
|
|
|
98
98
|
| `config/setup/` | one-time actions: financial year, master calendar, open periods |
|
|
99
99
|
| `config/master/` | inventory/distribution masters (prefs, warehouse, items, parties) |
|
|
100
100
|
| `scenario/` | lifecycle txns for `acu run`: once capital, then buy, build, sell |
|
|
101
|
-
| `config/
|
|
101
|
+
| `config/views/` | observer views for `acu state` (`inquire:` / `entity:` / `gi:`; not SEED_DIRS) |
|
|
102
102
|
| `state/` | committed derived-state observations (evidence, not seed; money/qty fixed-point) |
|
|
103
103
|
| `target.yaml` | committed verified matrix: `erp` + `default_api` (what, not where) |
|
|
104
104
|
| `.env` | where to apply and who signs in, every key an `ACU_*` variable |
|
|
@@ -114,9 +114,9 @@ Scenario YAML is different — it describes transactions that flow forward.
|
|
|
114
114
|
`acu run` executes each step in order (`put`, `action`, `wait`, `get`), captures server-assigned document numbers into `${var}` references for later steps, and checks `expect:` assertions as deltas against a pre-run snapshot, so additive scenarios re-run safely on a warm tenant.
|
|
115
115
|
`once: true` scenarios declare a `present` inquire-absolute gate; when the probe already holds, the CLI prints `skip <path> (once: already present)` and runs neither steps nor expects (Owner Capital does not restack).
|
|
116
116
|
|
|
117
|
-
`acu
|
|
117
|
+
`acu state` is the third observation path: it captures live derived state (balances) into `state/` for git review. It is not `extract` (config seed) and not `diff` (desired vs actual config). Packaged golden is trial-balance via contract `inquire:` (`EndingBalance` fixed-point); inventory-summary is not golden this pass. `gi:` stays optional when a GI is V12-verified and **Expose via OData** is on (`params` fail-closed vs `$metadata`). After a cold `acu run scenario/ && acu state`, warm `acu run scenario/10-seed-capital.yaml && acu state --assert-unchanged` is the once-class gate (full scenario re-run is additive and moves cash observations on the TB).
|
|
118
118
|
|
|
119
|
-
**Migration (
|
|
119
|
+
**Migration (T112–T114 hard-cut):** CLI verb is `state` only (no `snapshot` alias). Bare defaults are `config/views/` (views) and `state/` (observations). Prior `config/snapshot/` and root `snapshot/` / `snapshots/` are not fallbacks — move views to `config/views/` or pass explicit path args.
|
|
120
120
|
|
|
121
121
|
### Seed `endpoint:` symbols
|
|
122
122
|
|
|
@@ -290,7 +290,7 @@ The packaged full `config init` seed (under `config/`) is the only scaffold.
|
|
|
290
290
|
```sh
|
|
291
291
|
gmake e2e # whole tier, about 20 minutes
|
|
292
292
|
gmake e2e FILE=test_provision_lifecycle # apply/diff focus
|
|
293
|
-
gmake e2e FILE=test_scenario_lifecycle # scenario +
|
|
293
|
+
gmake e2e FILE=test_scenario_lifecycle # scenario + state focus
|
|
294
294
|
```
|
|
295
295
|
|
|
296
296
|
## License
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "acumatica-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.14.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"
|
|
@@ -12,7 +12,7 @@ import click
|
|
|
12
12
|
import httpx
|
|
13
13
|
from click.shell_completion import get_completion_class
|
|
14
14
|
|
|
15
|
-
from . import bootstrap, extract, firstlogin, output, run, seed,
|
|
15
|
+
from . import bootstrap, extract, firstlogin, output, run, seed, state
|
|
16
16
|
from .client import AcumaticaClient
|
|
17
17
|
from .config import (
|
|
18
18
|
Instance,
|
|
@@ -419,7 +419,7 @@ def config_init(host: str | None, directory: Path | None) -> None:
|
|
|
419
419
|
Templates ship with the package; every value is a placeholder or a
|
|
420
420
|
verified example - no secrets. Single full seed under ``config/``
|
|
421
421
|
(bootstrap/baseline/setup/master) + lifecycle ``scenario/`` +
|
|
422
|
-
``config/
|
|
422
|
+
``config/views/`` + README; full company ``project.xml``
|
|
423
423
|
(Bootstrap/1.0.0). No ``--flavor`` (V28/T108). Existing files are
|
|
424
424
|
never overwritten (reported as skipped). DIRECTORY defaults to the
|
|
425
425
|
current directory and is created if absent. No git init, no gpg.
|
|
@@ -437,6 +437,7 @@ def config_init(host: str | None, directory: Path | None) -> None:
|
|
|
437
437
|
output.data(" 4. acu apply config/")
|
|
438
438
|
output.data(" 5. acu run scenario/")
|
|
439
439
|
output.data(" 6. acu diff config/")
|
|
440
|
+
output.data(" 7. acu state")
|
|
440
441
|
|
|
441
442
|
|
|
442
443
|
@config_group.command("show")
|
|
@@ -935,7 +936,7 @@ def _exit_on_drift(inst: Instance, drifts: list[str], files: int) -> None:
|
|
|
935
936
|
output.success(f"no drift on {inst.tenant} ({inst.base_url}, {files} file(s))")
|
|
936
937
|
|
|
937
938
|
|
|
938
|
-
@cli.command("
|
|
939
|
+
@cli.command("state")
|
|
939
940
|
@click.argument(
|
|
940
941
|
"files", nargs=-1, required=False, type=click.Path(exists=True, path_type=Path)
|
|
941
942
|
)
|
|
@@ -963,7 +964,7 @@ def _exit_on_drift(inst: Instance, drifts: list[str], files: int) -> None:
|
|
|
963
964
|
help="Resolve views and validate sources without HTTP",
|
|
964
965
|
)
|
|
965
966
|
@pass_instance
|
|
966
|
-
def
|
|
967
|
+
def state_cmd(
|
|
967
968
|
inst: Instance,
|
|
968
969
|
files: tuple[Path, ...],
|
|
969
970
|
out_dir: Path | None,
|
|
@@ -973,39 +974,36 @@ def snapshot_cmd(
|
|
|
973
974
|
) -> None:
|
|
974
975
|
"""Capture live derived state into committed observation files.
|
|
975
976
|
|
|
976
|
-
FILES are
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
moved). Never writes seed trees or endpoint: symbols (V32). Exit 0
|
|
977
|
+
FILES are view YAML files or directories. Omitted, they default to the
|
|
978
|
+
data repo's config/views/ directory (hard-cut; no config/snapshot/
|
|
979
|
+
fallback). Default write target is state/ (--out). Bare capture writes
|
|
980
|
+
observations (change is fine). --diff compares live to disk without
|
|
981
|
+
writing. --assert-unchanged is the warm-run idempotence gate (exit 2
|
|
982
|
+
when moved). Never writes seed trees or endpoint: symbols (V32). Exit 0
|
|
983
983
|
ok, 1 op fail, 2 only under --assert-unchanged when state moved.
|
|
984
984
|
"""
|
|
985
985
|
assert_target_compatible(inst)
|
|
986
986
|
if not files:
|
|
987
|
-
default = data_root() / "config" / "
|
|
987
|
+
default = data_root() / "config" / "views"
|
|
988
988
|
if not default.is_dir():
|
|
989
|
-
raise SystemExit(f"{default}:
|
|
989
|
+
raise SystemExit(f"{default}: views directory does not exist")
|
|
990
990
|
files = (Path(os.path.relpath(default)),)
|
|
991
|
-
paths =
|
|
992
|
-
views = [
|
|
991
|
+
paths = state.expand_view_files(files)
|
|
992
|
+
views = [state.load_view(path) for path in paths]
|
|
993
993
|
dest = out_dir if out_dir is not None else Path("state")
|
|
994
994
|
if dry_run:
|
|
995
|
-
code =
|
|
995
|
+
code = state.run_views(None, views, out_dir=dest, mode="dry")
|
|
996
996
|
else:
|
|
997
997
|
mode = "assert" if assert_unchanged else "diff" if do_diff else "write"
|
|
998
998
|
with AcumaticaClient(inst) as client:
|
|
999
|
-
code =
|
|
999
|
+
code = state.run_views(client, views, out_dir=dest, mode=mode)
|
|
1000
1000
|
if code:
|
|
1001
1001
|
raise SystemExit(code)
|
|
1002
1002
|
if dry_run:
|
|
1003
1003
|
return
|
|
1004
1004
|
if assert_unchanged:
|
|
1005
|
-
output.success(f"{len(views)}
|
|
1005
|
+
output.success(f"{len(views)} view(s) unchanged on {inst.tenant}")
|
|
1006
1006
|
elif do_diff:
|
|
1007
|
-
output.success(f"{len(views)}
|
|
1007
|
+
output.success(f"{len(views)} view(s) compared on {inst.tenant}")
|
|
1008
1008
|
else:
|
|
1009
|
-
output.success(
|
|
1010
|
-
f"{len(views)} snapshot(s) written under {dest} on {inst.tenant}"
|
|
1011
|
-
)
|
|
1009
|
+
output.success(f"{len(views)} view(s) written under {dest} on {inst.tenant}")
|
|
@@ -539,7 +539,7 @@ class AcumaticaClient:
|
|
|
539
539
|
self._http.post("/CustomizationApi/publishEnd", json={})
|
|
540
540
|
).json()
|
|
541
541
|
|
|
542
|
-
# -- OData Generic Inquiry (
|
|
542
|
+
# -- OData Generic Inquiry (state gi: source; V33) --
|
|
543
543
|
|
|
544
544
|
def _odata_gi_root(self) -> str:
|
|
545
545
|
"""24R2+ OData GI service root ``/t/<tenant>/api/odata/gi`` (V33)."""
|
|
@@ -118,8 +118,8 @@ INIT_TEMPLATES = (
|
|
|
118
118
|
"config/master/85-kit-specifications.yaml",
|
|
119
119
|
),
|
|
120
120
|
(
|
|
121
|
-
"config/
|
|
122
|
-
"config/
|
|
121
|
+
"config/views/10-trial-balance.yaml",
|
|
122
|
+
"config/views/10-trial-balance.yaml",
|
|
123
123
|
),
|
|
124
124
|
("scenario/10-seed-capital.yaml", "scenario/10-seed-capital.yaml"),
|
|
125
125
|
("scenario/20-buy.yaml", "scenario/20-buy.yaml"),
|
acumatica_cli-0.13.1/src/acumatica_cli/snapshot.py → acumatica_cli-0.14.0/src/acumatica_cli/state.py
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
"""Derived-state observations: config/
|
|
1
|
+
"""Derived-state observations: config/views/*.yaml views -> state/*.yaml.
|
|
2
2
|
|
|
3
|
-
`acu
|
|
3
|
+
`acu state` captures live balances, quantities, and totals as committed
|
|
4
4
|
evidence (SPEC I.cmd / V32). Not a seed inverse: never writes seed trees,
|
|
5
5
|
never carries endpoint: symbols, never participates in apply/diff. Views
|
|
6
|
-
configure the observer under config/
|
|
6
|
+
configure the observer under config/views/ (not SEED_DIRS); observations
|
|
7
7
|
are git-diffable flow-style YAML under state/. Bare defaults hard-cut those
|
|
8
|
-
paths (no
|
|
8
|
+
paths (no config/snapshot/ fallback).
|
|
9
9
|
|
|
10
|
-
View file format (I.data config/
|
|
10
|
+
View file format (I.data config/views/*):
|
|
11
11
|
|
|
12
12
|
name: trial-balance
|
|
13
13
|
source:
|
|
@@ -89,7 +89,7 @@ class SourceSpec(Model):
|
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
class ViewDef(Model):
|
|
92
|
-
"""Observer config for one capture (I.data config/
|
|
92
|
+
"""Observer config for one capture (I.data config/views/*; V32/V33)."""
|
|
93
93
|
|
|
94
94
|
name: str
|
|
95
95
|
source: SourceSpec
|
|
@@ -132,7 +132,7 @@ class Observation(Model):
|
|
|
132
132
|
|
|
133
133
|
|
|
134
134
|
def load_view(path: Path) -> ViewDef:
|
|
135
|
-
"""Parse one
|
|
135
|
+
"""Parse one view definition; hard error on invalid shape."""
|
|
136
136
|
try:
|
|
137
137
|
raw = yaml.safe_load(path.read_text(encoding="utf-8"))
|
|
138
138
|
except yaml.YAMLError as exc:
|
|
@@ -333,7 +333,7 @@ def expand_view_files(files: tuple[Path, ...]) -> list[Path]:
|
|
|
333
333
|
if path.is_dir():
|
|
334
334
|
found = sorted(path.glob("*.yaml"))
|
|
335
335
|
if not found:
|
|
336
|
-
raise SystemExit(f"{path}: no
|
|
336
|
+
raise SystemExit(f"{path}: no view *.yaml files in directory")
|
|
337
337
|
paths += found
|
|
338
338
|
else:
|
|
339
339
|
paths.append(path)
|
|
@@ -547,7 +547,7 @@ def run_views(
|
|
|
547
547
|
out_dir: Path,
|
|
548
548
|
mode: Literal["write", "diff", "assert", "dry"] = "write",
|
|
549
549
|
) -> int:
|
|
550
|
-
"""Execute
|
|
550
|
+
"""Execute state capture for views; return process exit code (V32 exit matrix).
|
|
551
551
|
|
|
552
552
|
0 = ok (write or compare; change fine unless assert)
|
|
553
553
|
1 = operational failure
|
|
@@ -24,9 +24,9 @@ acu run scenario/
|
|
|
24
24
|
acu diff config/
|
|
25
25
|
|
|
26
26
|
# 6. Capture derived-state observations (EndingBalance trial-balance)
|
|
27
|
-
acu
|
|
27
|
+
acu state
|
|
28
28
|
# warm gate: once-capital only — additive buy/sell moves numeric observations
|
|
29
|
-
acu run scenario/10-seed-capital.yaml && acu
|
|
29
|
+
acu run scenario/10-seed-capital.yaml && acu state --assert-unchanged
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
Bare `acu apply` / `acu diff` also prefer `config/` when those trees exist.
|
|
@@ -43,7 +43,7 @@ Bare `acu apply` / `acu diff` also prefer `config/` when those trees exist.
|
|
|
43
43
|
| `scenario/20-buy.yaml` | Additive component PO → receipt → bill → AP pay |
|
|
44
44
|
| `scenario/30-build.yaml` | Additive kit assembly |
|
|
45
45
|
| `scenario/40-sell.yaml` | Additive SO → ship → invoice → AR pay |
|
|
46
|
-
| `config/
|
|
47
|
-
| `state/` | Written by `acu
|
|
46
|
+
| `config/views/10-trial-balance.yaml` | Observer view (EndingBalance inquire; not SEED_DIRS) |
|
|
47
|
+
| `state/` | Written by `acu state` (derived-state observations) |
|
|
48
48
|
|
|
49
49
|
Monoscenario `buy-sell` is not part of this package.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# State view: GL trial balance (EndingBalance-class, V33).
|
|
2
2
|
# inquire: AccountSummaryInquiry — same contract inquiry as run expect/present
|
|
3
3
|
# (Ledger + Period pinned; Results projected by Account). gi: LAB5-TrialBalance
|
|
4
4
|
# remains optional when GenericInquiry is V12-verified and Expose via OData is on.
|
|
5
|
-
# After scenario/, `acu
|
|
5
|
+
# After scenario/, `acu state --assert-unchanged` is the idempotence gate (V32).
|
|
6
6
|
name: trial-balance
|
|
7
7
|
source:
|
|
8
8
|
inquire: AccountSummaryInquiry
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/scenario/20-buy.yaml
RENAMED
|
File without changes
|
{acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/scenario/30-build.yaml
RENAMED
|
File without changes
|
{acumatica_cli-0.13.1 → acumatica_cli-0.14.0}/src/acumatica_cli/templates/scenario/40-sell.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|