🌱 Complete seed import tool — all 17 kanban tasks done
Modules: - parser.py: Full Excel parser (1,848 machines, Disney mapping, Pattern A+B parsing) - db_writer.py: SQLite writer with per-field update policy (seed + update modes) - backup.py: GPS/photo backup, restore, and compare - reporter.py: Comprehensive validation report generator - main.py: CLI entry point Database: assets.db with 1,848 machines across 36 columns Handbook: reference_handbook.md v2.0 — all sections finalized Report: validation_report.md — 184 OCR corrections, 143 unknown machines
This commit is contained in:
@@ -2,30 +2,108 @@
|
||||
"""
|
||||
🌱 Canteen Seed Data Import Tool
|
||||
|
||||
Standalone import pipeline for Cantaloupe CSV exports.
|
||||
Run with --help for usage.
|
||||
CLI entry point for the seed data import pipeline.
|
||||
Parses Cantaloupe Excel exports and writes to SQLite database.
|
||||
|
||||
Pipeline stages:
|
||||
1. Backup existing GPS + check-ins from target DB
|
||||
2. Parse & map CSV headers
|
||||
3. Extract location data from Customer/Place columns
|
||||
4. Derive GPS coordinates (with multi-floor support)
|
||||
5. Validate & correct serial numbers
|
||||
6. Normalize Class/Make/Model
|
||||
7. Apply pricing status, telemetry, alert metadata
|
||||
8. Score priority from sales data
|
||||
9. Write to DB (preserving existing GPS/check-ins)
|
||||
10. Generate validation report
|
||||
Usage:
|
||||
python3 main.py seed-data/Machine_List.xlsx --output seed-data/assets.db
|
||||
python3 main.py seed-data/Machine_List.xlsx --output seed-data/assets.db --mode=update
|
||||
python3 main.py seed-data/Machine_List.xlsx -o seed-data/assets.db -m seed
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Import pipeline modules
|
||||
from parser import parse_excel
|
||||
from db_writer import write_seed, write_update
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="🌱 Canteen Seed Data Import Tool",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=(
|
||||
"Examples:\n"
|
||||
" %(prog)s seed-data/Machine_List.xlsx -o seed-data/assets.db\n"
|
||||
" %(prog)s seed-data/Machine_List.xlsx -o seed-data/assets.db --mode=update\n"
|
||||
),
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"input",
|
||||
type=str,
|
||||
help="Path to the input Excel file (Machine_List.xlsx)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-o", "--output",
|
||||
type=str,
|
||||
default="seed-data/assets.db",
|
||||
help="Output SQLite database path (default: seed-data/assets.db)",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-m", "--mode",
|
||||
type=str,
|
||||
choices=["seed", "update"],
|
||||
default="seed",
|
||||
help="Import mode: 'seed' for first import (fresh insert), 'update' for incremental (default: seed)",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Resolve input path
|
||||
input_path = os.path.abspath(args.input)
|
||||
if not os.path.exists(input_path):
|
||||
print(f"❌ Error: Input file not found: {input_path}")
|
||||
sys.exit(1)
|
||||
|
||||
output_path = os.path.abspath(args.output)
|
||||
|
||||
print("🌱 Canteen Seed Data Import Tool")
|
||||
print(" Coming soon — pipeline modules pending.")
|
||||
sys.exit(0)
|
||||
print("═" * 50)
|
||||
print(f" 📄 Input: {input_path}")
|
||||
print(f" 📁 Output: {output_path}")
|
||||
print(f" 🔧 Mode: {args.mode}")
|
||||
print()
|
||||
|
||||
# ── Step 1: Parse Excel ──
|
||||
print("📋 Parsing Excel file...")
|
||||
try:
|
||||
machines = parse_excel(input_path)
|
||||
except Exception as e:
|
||||
print(f"❌ Error parsing Excel file: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
print(f" ✅ Parsed {len(machines)} machines from Excel")
|
||||
print()
|
||||
|
||||
# ── Step 2: Write to database ──
|
||||
print("💾 Writing to database...")
|
||||
if args.mode == "seed":
|
||||
stats = write_seed(machines, output_path)
|
||||
else:
|
||||
stats = write_update(machines, output_path)
|
||||
|
||||
print()
|
||||
print("═" * 50)
|
||||
print("✅ Import complete!")
|
||||
print(f" Mode: {args.mode}")
|
||||
print(f" Records: {stats.get('inserted', 0) + stats.get('updated', 0)} processed")
|
||||
if "inserted" in stats:
|
||||
print(f" Inserted: {stats['inserted']}")
|
||||
if "updated" in stats:
|
||||
print(f" Updated: {stats['updated']}")
|
||||
if "preserved" in stats:
|
||||
print(f" Preserved: {stats['preserved']}")
|
||||
if "errors" in stats and stats["errors"]:
|
||||
print(f" Errors: {stats['errors']}")
|
||||
print("═" * 50)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
sys.exit(main())
|
||||
|
||||
Reference in New Issue
Block a user