Use GEO_INTERNAL_URL for exchange seed

This commit is contained in:
Ruslan Bakiev
2026-02-05 14:51:05 +07:00
parent 1e8b5ad859
commit 0f857192d4

View File

@@ -2,8 +2,11 @@
Seed Suppliers and Offers for African cocoa belt.
Creates offers via Temporal workflow so they sync to the graph.
"""
import csv
import os
import random
import uuid
from pathlib import Path
from decimal import Decimal
import time
@@ -65,6 +68,9 @@ SUPPLIER_NAMES = [
"Dar Coast Commodities", "Maputo Export House",
]
# Default GLEIF Africa LEI dataset path (repo-local)
DEFAULT_GLEIF_PATH = "datasets/gleif/africa_lei_companies.csv"
# Fixed product catalog (10 items) with realistic prices per ton (USD)
PRODUCT_CATALOG = [
{"name": "Cocoa Beans", "category": "Cocoa", "price": Decimal("2450.00")},
@@ -138,8 +144,8 @@ class Command(BaseCommand):
parser.add_argument(
"--geo-url",
type=str,
default="http://geo:8000/graphql/public/",
help="Geo service GraphQL URL (default: http://geo:8000/graphql/public/)",
default=None,
help="Geo service GraphQL URL (defaults to GEO_INTERNAL_URL env var)",
)
parser.add_argument(
"--odoo-url",
@@ -176,6 +182,12 @@ class Command(BaseCommand):
default=None,
help="Filter offers by product name (e.g., 'Cocoa Beans')",
)
parser.add_argument(
"--company-csv",
type=str,
default=None,
help="Path to CSV with real company names (default: datasets/gleif/africa_lei_companies.csv)",
)
def handle(self, *args, **options):
if options["clear"]:
@@ -194,13 +206,17 @@ class Command(BaseCommand):
use_bulk = options["bulk"]
bulk_size = max(1, options["bulk_size"])
sleep_ms = max(0, options["sleep_ms"])
geo_url = options["geo_url"]
geo_url = options["geo_url"] or os.getenv("GEO_INTERNAL_URL") or os.getenv("GEO_URL")
if not geo_url:
self.stdout.write(self.style.ERROR("Geo URL is not set. Provide --geo-url or GEO_INTERNAL_URL."))
return
odoo_url = options["odoo_url"]
product_filter = options["product"]
ensure_products = options["ensure_products"]
odoo_db = options["odoo_db"]
odoo_user = options["odoo_user"]
odoo_password = options["odoo_password"]
company_csv = options["company_csv"]
# Fetch products from Odoo
self.stdout.write("Fetching products from Odoo...")
@@ -233,14 +249,13 @@ class Command(BaseCommand):
hubs = self._fetch_african_hubs(geo_url)
if not hubs:
self.stdout.write(self.style.WARNING(
"No African hubs found. Using default locations."
))
hubs = self._default_african_hubs()
self.stdout.write(self.style.ERROR("No African hubs found from geo service. Aborting seed."))
return
self.stdout.write(f"Found {len(hubs)} African hubs")
# Create suppliers
self._company_pool = self._load_company_pool(company_csv)
self.stdout.write(f"Creating {suppliers_count} suppliers...")
new_suppliers = self._create_suppliers(suppliers_count, hubs)
self.stdout.write(self.style.SUCCESS(f"Created {len(new_suppliers)} suppliers"))
@@ -572,15 +587,28 @@ class Command(BaseCommand):
lat += random.uniform(-0.5, 0.5)
lng += random.uniform(-0.5, 0.5)
name = self._generate_supplier_name(idx)
company = self._pick_company(idx)
if company:
name = company["name"]
company_code = company.get("country_code")
mapped_name = self._country_name_from_code(company_code)
if mapped_name:
country = mapped_name
country_code = company_code
supplier_uuid = self._stable_uuid("supplier", company.get("lei") or name)
team_uuid = self._stable_uuid("team", company.get("lei") or name)
else:
name = self._generate_supplier_name(idx)
supplier_uuid = str(uuid.uuid4())
team_uuid = str(uuid.uuid4())
description = (
f"{name} is a reliable supplier based in {country}, "
"focused on consistent quality and transparent logistics."
)
profile = SupplierProfile.objects.create(
uuid=str(uuid.uuid4()),
team_uuid=str(uuid.uuid4()),
uuid=supplier_uuid,
team_uuid=team_uuid,
name=name,
description=description,
country=country,
@@ -600,6 +628,68 @@ class Command(BaseCommand):
return SUPPLIER_NAMES[index]
return f"{random.choice(SUPPLIER_NAMES)} Group"
def _find_default_company_csv(self) -> str | None:
"""Locate default company CSV in repo (datasets/gleif/africa_lei_companies.csv)."""
here = Path(__file__).resolve()
for parent in here.parents:
candidate = parent / DEFAULT_GLEIF_PATH
if candidate.exists():
return str(candidate)
return None
def _load_company_pool(self, csv_path: str | None) -> list[dict]:
"""Load real company names from CSV; returns list of dicts."""
path = csv_path or self._find_default_company_csv()
if not path or not os.path.exists(path):
self.stdout.write(self.style.WARNING("Company CSV not found; using fallback names."))
return []
companies = []
seen = set()
try:
with open(path, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
name = (row.get("entity_name") or "").strip()
if not name:
continue
if name in seen:
continue
seen.add(name)
companies.append(
{
"name": name,
"lei": (row.get("lei") or "").strip(),
"country_code": (row.get("legal_address_country") or row.get("headquarters_country") or "").strip(),
"city": (row.get("legal_address_city") or row.get("headquarters_city") or "").strip(),
}
)
except Exception as e:
self.stdout.write(self.style.WARNING(f"Failed to read company CSV: {e}"))
return []
random.shuffle(companies)
self.stdout.write(f"Loaded {len(companies)} company names from CSV")
return companies
def _pick_company(self, index: int) -> dict | None:
if not getattr(self, "_company_pool", None):
return None
if index < len(self._company_pool):
return self._company_pool[index]
return random.choice(self._company_pool)
def _stable_uuid(self, prefix: str, value: str) -> str:
return str(uuid.uuid5(uuid.NAMESPACE_DNS, f"{prefix}:{value}"))
def _country_name_from_code(self, code: str | None) -> str | None:
if not code:
return None
for name, country_code, _, _ in AFRICAN_COUNTRIES:
if country_code == code:
return name
return None
def _price_for_product(self, product_name: str) -> Decimal:
for item in PRODUCT_CATALOG:
if item["name"].lower() == product_name.lower():