mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-19 17:03:02 +00:00
The 'all properties' selection resolved against property.portfolio_id, but a
portfolio spans multiple HubSpot projects — so 'all' pulled the whole portfolio,
not the project the user was looking at. The project↔property grain lives on
hubspot_deal_data, not property.
task.inputs is now {project_codes?: str[], property_ids?: int[], portfolio_id?}:
the route resolves the distinct landlord_property_id set as the union of every
property in the named project_codes (from hubspot_deal_data) and the hand-picked
property_ids; portfolio_id is optional and only names the package. Drops the
portfolio-scoped select_all. Cap now applies to the resolved set size.
ADR-0060, CONTEXT.md and the request schema updated to match. New router tests
cover project-code resolution, the union+dedup, null landlord_property_id drop,
and the empty-project rejection.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
20 lines
858 B
Python
20 lines
858 B
Python
from uuid import UUID
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class BulkDownloadRequest(BaseModel):
|
|
"""A request to assemble a Download Package (ADR-0060).
|
|
|
|
The front end creates the app-owned Task first and writes the **selection
|
|
config** into ``task.inputs`` (a JSON object of
|
|
``{project_codes?: str[], property_ids?: int[], portfolio_id?: int}`` — so a
|
|
large selection never travels in an HTTP body), then passes only the
|
|
``task_id`` here. The backend reads the selection from ``task.inputs`` and
|
|
resolves it to the distinct ``landlord_property_id`` set: the union of every
|
|
property in the named HubSpot ``project_codes`` (from ``hubspot_deal_data``)
|
|
and the hand-picked ``property_ids``. At least one of the two must be given;
|
|
``portfolio_id`` is optional and used only to name the package.
|
|
"""
|
|
|
|
task_id: UUID
|