From c654d25230d2f07dd14e97ddfb841b7b5299cbd0 Mon Sep 17 00:00:00 2001 From: Ruslan Bakiev Date: Thu, 5 Feb 2026 01:34:16 +0700 Subject: [PATCH] Add bulk seeding option --- offers/management/commands/seed_exchange.py | 71 +++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/offers/management/commands/seed_exchange.py b/offers/management/commands/seed_exchange.py index 0a4e0af..ad39128 100644 --- a/offers/management/commands/seed_exchange.py +++ b/offers/management/commands/seed_exchange.py @@ -117,6 +117,17 @@ class Command(BaseCommand): action="store_true", help="Create offers directly in DB without workflow (no graph sync)", ) + parser.add_argument( + "--bulk", + action="store_true", + help="Use bulk_create for offers (only with --no-workflow)", + ) + parser.add_argument( + "--bulk-size", + type=int, + default=200, + help="Batch size for bulk_create (default: 200)", + ) parser.add_argument( "--geo-url", type=str, @@ -173,6 +184,8 @@ class Command(BaseCommand): product_count = max(1, options["product_count"]) supplier_location_ratio = min(max(options["supplier_location_ratio"], 0.0), 1.0) use_workflow = not options["no_workflow"] + use_bulk = options["bulk"] + bulk_size = max(1, options["bulk_size"]) geo_url = options["geo_url"] odoo_url = options["odoo_url"] product_filter = options["product"] @@ -226,10 +239,17 @@ class Command(BaseCommand): # Create offers self.stdout.write(f"Creating {offers_count} offers (workflow={use_workflow})...") + if use_workflow and use_bulk: + self.stdout.write(self.style.ERROR("Bulk mode is only supported with --no-workflow.")) + return if use_workflow: created_offers = self._create_offers_via_workflow( offers_count, hubs, products, supplier_location_ratio ) + elif use_bulk: + created_offers = self._create_offers_direct_bulk( + offers_count, hubs, products, supplier_location_ratio, bulk_size + ) else: created_offers = self._create_offers_direct( offers_count, hubs, products, supplier_location_ratio @@ -679,6 +699,57 @@ class Command(BaseCommand): return created + def _create_offers_direct_bulk( + self, count: int, hubs: list, products: list, supplier_ratio: float, bulk_size: int + ) -> list: + """Create offers in bulk (no workflow, no graph sync)""" + suppliers = list(SupplierProfile.objects.all()) + if not suppliers: + self.stdout.write(self.style.ERROR("No suppliers found. Create suppliers first.")) + return [] + + created_uuids: list[str] = [] + batch: list[Offer] = [] + + for idx in range(count): + supplier = random.choice(suppliers) + hub = self._pick_location(supplier, hubs, supplier_ratio) + product_name, category_name, product_uuid, product_price = random.choice(products) + offer_uuid = str(uuid.uuid4()) + + batch.append( + Offer( + uuid=offer_uuid, + team_uuid=supplier.team_uuid, + status="active", + workflow_status="pending", + location_uuid=hub["uuid"], + location_name=hub["name"], + location_country=hub["country"], + location_country_code=hub.get("countryCode", ""), + location_latitude=hub["latitude"], + location_longitude=hub["longitude"], + product_uuid=product_uuid, + product_name=product_name, + category_name=category_name, + quantity=self._rand_decimal(10, 500, 2), + unit="ton", + price_per_unit=product_price, + currency="USD", + description=f"{product_name} available from {hub['name']} in {hub['country']}", + ) + ) + created_uuids.append(offer_uuid) + + if len(batch) >= bulk_size: + Offer.objects.bulk_create(batch, batch_size=bulk_size) + batch = [] + + if batch: + Offer.objects.bulk_create(batch, batch_size=bulk_size) + + return created_uuids + def _get_random_african_country(self) -> tuple: """Get random African country name and code""" country, code, _, _ = random.choice(AFRICAN_COUNTRIES)