From 83af32eb8879cfed455179fcd4059cd7fa52745a Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Fri, 3 Apr 2026 18:10:39 +0200 Subject: [PATCH] fix(hosting): POC builder works with existing sites The Build POC button on site detail now passes site_id to the POC builder, which populates the existing site's store with CMS content instead of trying to create a new site (which failed with duplicate slug error). - poc_builder_service.build_poc() accepts optional site_id param - If site_id given: uses existing site, skips hosted_site_service.create() - If not given: creates new site (standalone POC build) - API schema: added site_id to BuildPocRequest - Frontend: passes this.site.id in the build request Co-Authored-By: Claude Opus 4.6 (1M context) --- app/modules/hosting/routes/api/admin_sites.py | 2 ++ .../hosting/services/poc_builder_service.py | 30 +++++++++++-------- .../templates/hosting/admin/site-detail.html | 1 + 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/app/modules/hosting/routes/api/admin_sites.py b/app/modules/hosting/routes/api/admin_sites.py index f2cd1c6f..9219b999 100644 --- a/app/modules/hosting/routes/api/admin_sites.py +++ b/app/modules/hosting/routes/api/admin_sites.py @@ -75,6 +75,7 @@ class BuildPocRequest(BaseModel): prospect_id: int template_id: str merchant_id: int | None = None + site_id: int | None = None # If set, populate existing site instead of creating new one class BuildPocResponse(BaseModel): @@ -100,6 +101,7 @@ def build_poc( prospect_id=data.prospect_id, template_id=data.template_id, merchant_id=data.merchant_id, + site_id=data.site_id, ) db.commit() return BuildPocResponse(**result) diff --git a/app/modules/hosting/services/poc_builder_service.py b/app/modules/hosting/services/poc_builder_service.py index 589ace0b..8c154baf 100644 --- a/app/modules/hosting/services/poc_builder_service.py +++ b/app/modules/hosting/services/poc_builder_service.py @@ -35,9 +35,13 @@ class PocBuilderService: prospect_id: int, template_id: str, merchant_id: int | None = None, + site_id: int | None = None, ) -> dict: """Build a complete POC site from prospect data and a template. + If site_id is given, populates the existing site's store with CMS + content. Otherwise creates a new HostedSite + Store. + Returns dict with hosted_site, store, pages_created, theme_applied. """ from app.modules.prospecting.models import Prospect @@ -57,18 +61,20 @@ class PocBuilderService: # 3. Build placeholder context from prospect data context = self._build_context(prospect) - # 4. Create HostedSite + Store - site_data = { - "business_name": context["business_name"], - "domain_name": prospect.domain_name, # used for clean subdomain slug - "prospect_id": prospect_id, - "contact_email": context.get("email"), - "contact_phone": context.get("phone"), - } - if merchant_id: - site_data["merchant_id"] = merchant_id - - site = hosted_site_service.create(db, site_data) + # 4. Use existing site or create new one + if site_id: + site = hosted_site_service.get_by_id(db, site_id) + else: + site_data = { + "business_name": context["business_name"], + "domain_name": prospect.domain_name, + "prospect_id": prospect_id, + "contact_email": context.get("email"), + "contact_phone": context.get("phone"), + } + if merchant_id: + site_data["merchant_id"] = merchant_id + site = hosted_site_service.create(db, site_data) # 5. Get the hosting platform_id from the store from app.modules.tenancy.models import StorePlatform diff --git a/app/modules/hosting/templates/hosting/admin/site-detail.html b/app/modules/hosting/templates/hosting/admin/site-detail.html index 9cd1a104..e2e170f0 100644 --- a/app/modules/hosting/templates/hosting/admin/site-detail.html +++ b/app/modules/hosting/templates/hosting/admin/site-detail.html @@ -351,6 +351,7 @@ function hostingSiteDetail(siteId) { var result = await apiClient.post('/admin/hosting/sites/poc/build', { prospect_id: this.site.prospect_id, template_id: this.selectedTemplate, + site_id: this.site.id, }); this.pocResult = 'POC built! ' + result.pages_created + ' pages created.'; Utils.showToast('POC built successfully', 'success');