Add WINC batches CLI and a CLI how-to README
The web import panel can list applied/undone batches, but the CLI had no equivalent, so an operator working from the shell had no way to find a batchid to feed into the undo command. Add a read-only batches command that reuses the same importbatches query, and a short README documenting the four WINC commands and their switches.
This commit is contained in:
67
scripts/site_imports/winc/README.md
Normal file
67
scripts/site_imports/winc/README.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# WINC machine-adoption import (CLI)
|
||||
|
||||
Adopts machines from a Maximo asset export (validated against the WINC / West
|
||||
Manufacturing site). It only updates machines that already exist; it never
|
||||
creates canonical per-table rows. Every commit is journaled so it can be undone
|
||||
as one batch.
|
||||
|
||||
Run all commands from the repo root. Each reads `.env` and connects to the
|
||||
configured database.
|
||||
|
||||
## 1. Preview (read-only)
|
||||
|
||||
```
|
||||
python -m scripts.site_imports.winc.dry_run --export EXPORT.csv
|
||||
```
|
||||
|
||||
| switch | what it does |
|
||||
| --- | --- |
|
||||
| `--export PATH` | the Maximo ASSET export CSV to analyze (required) |
|
||||
| `--rows` | print the per-row plan, not just the summary |
|
||||
| `--csv PATH` | write the full plan to a CSV so runs can be diffed |
|
||||
|
||||
Nothing is written. Use this to see what would change and which values are
|
||||
unresolved before committing.
|
||||
|
||||
## 2. Commit (writes, reversibly)
|
||||
|
||||
```
|
||||
python -m scripts.site_imports.winc.writer --export EXPORT.csv --commit --acknowledge businessunit
|
||||
```
|
||||
|
||||
| switch | what it does |
|
||||
| --- | --- |
|
||||
| `--export PATH` | the same export CSV (required) |
|
||||
| `--commit` | actually write; without it this is a dry run |
|
||||
| `--acknowledge GROUP` | approve a needs-create group (repeatable), e.g. `businessunit` |
|
||||
| `--createdby NAME` | who approved the import; stamped on the batch |
|
||||
|
||||
On success it prints the new `batchid` and the exact undo command.
|
||||
|
||||
## 3. List batches
|
||||
|
||||
```
|
||||
python -m scripts.site_imports.winc.batches
|
||||
```
|
||||
|
||||
| switch | what it does |
|
||||
| --- | --- |
|
||||
| `--limit N` | show at most N batches, newest first (default 50) |
|
||||
| `--json` | emit JSON instead of a table |
|
||||
|
||||
Read-only. Use it to find the `batchid` to undo.
|
||||
|
||||
## 4. Undo a batch
|
||||
|
||||
```
|
||||
python -m scripts.site_imports.winc.undo --batch BATCHID --commit
|
||||
```
|
||||
|
||||
| switch | what it does |
|
||||
| --- | --- |
|
||||
| `--batch BATCHID` | the batch to reverse (required) |
|
||||
| `--commit` | actually reverse; without it this is a no-op |
|
||||
|
||||
Reversal is conservative: a cell a human changed since the import is left as-is
|
||||
and reported, and a created business unit is deleted only when nothing outside
|
||||
the batch still references it.
|
||||
91
scripts/site_imports/winc/batches.py
Normal file
91
scripts/site_imports/winc/batches.py
Normal file
@@ -0,0 +1,91 @@
|
||||
"""WINC machine adoption - BATCHES (list applied/undone import batches).
|
||||
|
||||
A read-only companion to writer.py and undo.py: it prints the WINC batches
|
||||
newest-first so an operator can find a batchid to feed `--batch` into the undo
|
||||
CLI. Like the other WINC commands it is WINC-named only for discoverability; the
|
||||
underlying importbatches table is import-agnostic, so this simply filters to the
|
||||
winc-machine-adoption kind.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(__file__))))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from pathlib import Path
|
||||
|
||||
load_dotenv(Path(__file__).resolve().parents[3] / '.env')
|
||||
|
||||
from sqlalchemy import text
|
||||
|
||||
from scripts.site_imports.winc.dry_run import build_app_connection
|
||||
|
||||
_KIND = 'winc-machine-adoption'
|
||||
|
||||
|
||||
def _iso(value):
|
||||
# PyMySQL hands back datetime objects; SQLite hands back the stored ISO
|
||||
# string. Normalise both to an ISO string so the output is stable.
|
||||
if value is None:
|
||||
return '-'
|
||||
if hasattr(value, 'isoformat'):
|
||||
return value.isoformat()
|
||||
return str(value)
|
||||
|
||||
|
||||
def list_batches(connection, limit):
|
||||
rows = connection.execute(text(
|
||||
'SELECT batchid, kind, rowcount, createdat, createdby, status, '
|
||||
'undoneat FROM importbatches WHERE kind = :kind '
|
||||
'ORDER BY createdat DESC LIMIT :limit'),
|
||||
{'kind': _KIND, 'limit': limit}).fetchall()
|
||||
return [
|
||||
{'batchid': r[0], 'kind': r[1], 'rowcount': r[2],
|
||||
'createdat': _iso(r[3]), 'createdby': r[4], 'status': r[5],
|
||||
'undoneat': _iso(r[6])}
|
||||
for r in rows
|
||||
]
|
||||
|
||||
|
||||
def _print_table(batches):
|
||||
if not batches:
|
||||
print('No WINC import batches found.')
|
||||
return
|
||||
header = '%-36s %-8s %5s %-20s %-16s %s' % (
|
||||
'batchid', 'status', 'rows', 'createdat', 'createdby', 'undoneat')
|
||||
print(header)
|
||||
print('-' * len(header))
|
||||
for batch in batches:
|
||||
print('%-36s %-8s %5s %-20s %-16s %s' % (
|
||||
batch['batchid'], batch['status'], batch['rowcount'],
|
||||
batch['createdat'], batch['createdby'] or '-', batch['undoneat']))
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
parser = argparse.ArgumentParser(
|
||||
description='List applied/undone WINC import batches, newest first.')
|
||||
parser.add_argument('--limit', type=int, default=50,
|
||||
help='Maximum number of batches to show (default 50).')
|
||||
parser.add_argument('--json', action='store_true',
|
||||
help='Emit the batches as JSON instead of a table.')
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
if args.limit < 1:
|
||||
parser.error('--limit must be a positive integer')
|
||||
|
||||
_app, connection = build_app_connection()
|
||||
batches = list_batches(connection, args.limit)
|
||||
|
||||
if args.json:
|
||||
import json
|
||||
print(json.dumps(batches, indent=2))
|
||||
else:
|
||||
_print_table(batches)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user