A clean, testable Python toolkit for updating nomenclature prices in 1C / 1Enterprise from supplier CSV price-lists — with dry-run safety, retry logic, and a human-readable diff report.
| Decision | Rationale |
|---|---|
| Env-only config | No secrets in code or config files; .env.example ships as the only template |
| Dry-run by default | DRY_RUN=true out of the box; the operator must explicitly opt-in to writes |
| Retry on transient 404/5xx | 1C HTTP-services can return transient 404 during reload; exponential back-off with configurable delay |
| Pure, testable parser/matcher | Parser uses stdlib csv; matcher uses Jaccard similarity — no network, no 1C needed for tests |
| Decimal prices | decimal.Decimal throughout to avoid float rounding errors in financial data |
| Ambiguity surfaced, not resolved | When multiple 1C entries match equally well, the item is flagged for manual review rather than silently picking one |
Supplier price-list (CSV / XLSX)
|
v
[ parser.py ] parse_pricelist()
| PriceItem list
v
[ matcher.py ] match_items(items, nomenclature)
| MatchResult list
v
[ diff_report.py ] build_diff(old_prices, matches)
| PriceChange list
v
[ price_writer.py ] write_prices(client, changes, dry_run=True)
|
v
1C via HTTP OneCClient.write_price()
onec-price-updater/
├── README.md
├── LICENSE
├── .gitignore
├── .env.example
├── requirements.txt
├── pyproject.toml
├── sample_data/
│ └── pricelist_example.csv
├── src/pricebot/
│ ├── __init__.py
│ ├── config.py env-driven settings + domain constants
│ ├── models.py PriceItem, NomenclatureRef, MatchResult, PriceChange
│ ├── parser.py CSV parser + mtime-based price-list date
│ ├── matcher.py Jaccard-similarity matcher with ambiguity detection
│ ├── onec_client.py HTTP client for 1C (fetch nomenclature / prices / write)
│ ├── price_writer.py Applies or dry-runs the price changes
│ ├── diff_report.py Builds and renders the human-readable diff
│ └── retry.py Exponential back-off decorator for transient errors
└── tests/
├── test_parser.py
├── test_matcher.py
├── test_diff_report.py
└── test_retry.py
# 1. Create and activate a virtual environment
python -m venv .venv
# Windows:
.venv\Scripts\activate
# macOS / Linux:
source .venv/bin/activate
# 2. Install dependencies
pip install -r requirements.txt
# 3. Configure
cp .env.example .env
# Edit .env: set ONEC_BASE_URL and ONEC_TOKEN
# 4. Run a dry-run demo on the sample data
# (DRY_RUN=true by default — no data is written)
python - <<'EOF'
from pricebot.parser import parse_pricelist
from pricebot.diff_report import render_report, build_diff
from pricebot.matcher import match_items
from decimal import Decimal
items = parse_pricelist("sample_data/pricelist_example.csv")
print(f"Parsed {len(items)} items from price-list")
# Without a real 1C connection, pass an empty nomenclature list
results = match_items(items, [])
changes = build_diff({}, results)
print(render_report(changes, results))
EOF
# 5. Run the test suite (no network required)
pytestThis is a sanitised, from-scratch reference implementation. All supplier names ("Acme Roofing"), product series ("Classic", "Premium", "Standard"), and article numbers are entirely fictional and do not represent any real company or product.
MIT — see LICENSE.