From 85e4b4fb69db79b37dbb528c403763138d147ce4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 15:39:01 +0000 Subject: [PATCH 1/3] feat(vehicles): used-vehicle CRUD + bulk insert for v1.1.0 --- .stats.yml | 6 +- api.md | 1 + .../resources/dealers/vehicles/vehicles.py | 77 +------------------ src/partnermax/types/dealers/__init__.py | 1 + src/partnermax/types/dealers/ai_content.py | 65 ++++++++++++++++ .../types/dealers/bulk_row_outcome.py | 23 ++++-- .../types/dealers/vehicle_bulk_params.py | 25 +----- .../types/dealers/vehicle_create_params.py | 25 +----- .../types/dealers/vehicle_detail.py | 54 +++++++------ .../types/dealers/vehicle_update_params.py | 19 +---- tests/api_resources/dealers/test_vehicles.py | 65 ---------------- 11 files changed, 124 insertions(+), 237 deletions(-) create mode 100644 src/partnermax/types/dealers/ai_content.py diff --git a/.stats.yml b/.stats.yml index 9de5f99..aa1effc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 21 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/azure/partnermax-5a0409bb0fddcda8df26a189afdb3328c0402ce1385e56c4793e2969efd2b290.yml -openapi_spec_hash: fa78b80fb8127ab4e7761cbf9ccbbdd2 -config_hash: 84dd1a86856c12a806c07e9e23badbfd +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/azure/partnermax-8e9792fdc8ae3014eba29b0de5b3fb675466f979bf88c66c73f957ce353bf0a1.yml +openapi_spec_hash: 373fc725db05b75b4bd515667c8a8d12 +config_hash: 18c6c7df17bad3320b9f2c126947f00a diff --git a/api.md b/api.md index cb3ea5d..1b965c3 100644 --- a/api.md +++ b/api.md @@ -62,6 +62,7 @@ Types: ```python from partnermax.types.dealers import ( + AIContent, BulkCreateVehiclesResponse, BulkRowOutcome, VehicleDetail, diff --git a/src/partnermax/resources/dealers/vehicles/vehicles.py b/src/partnermax/resources/dealers/vehicles/vehicles.py index f0c5a58..424941e 100644 --- a/src/partnermax/resources/dealers/vehicles/vehicles.py +++ b/src/partnermax/resources/dealers/vehicles/vehicles.py @@ -2,8 +2,7 @@ from __future__ import annotations -from typing import Union, Iterable, Optional -from datetime import date +from typing import Iterable, Optional import httpx @@ -78,7 +77,6 @@ def create( dealer_id: str, *, certified_km: int, - cost_price_eur: float, motornet_code: str, plate: str, registration_year: int, @@ -88,17 +86,10 @@ def create( description: str | Omit = omit, extended_warranty_enabled: bool | Omit = omit, extended_warranty_months: Optional[int] | Omit = omit, - inspection_expiry_date: Union[str, date, None] | Omit = omit, is_for_sale: bool | Omit = omit, is_visible: bool | Omit = omit, - last_service_date: Union[str, date, None] | Omit = omit, - last_service_km: Optional[int] | Omit = omit, - last_service_notes: Optional[str] | Omit = omit, notes: Optional[str] | Omit = omit, - previous_owner_count: Optional[int] | Omit = omit, - previous_ownership_transfer_date: Union[str, date, None] | Omit = omit, registration_month: Optional[int] | Omit = omit, - road_tax_expiry_date: Union[str, date, None] | Omit = omit, vat_displayed: bool | Omit = omit, vehicle_damaged: bool | Omit = omit, vin: Optional[str] | Omit = omit, @@ -124,9 +115,6 @@ def create( Args: certified_km: Certified odometer reading at intake, in kilometres. - cost_price_eur: Cost basis to the dealer in EUR (partner/dealer internal). Not surfaced on - consumer-facing AI surfaces; used by dealer reporting and margin analytics only. - motornet_code: Motornet UNI code identifying the exact vehicle configuration. Must exist in `mnet_dettagli_usato` at submission time; otherwise the call returns 422 `motornet_code_not_in_catalogue`. The partner is expected to source this from @@ -151,8 +139,6 @@ def create( notes: Free-form short notes; surfaced as `mnet_dettagli.precisazioni`-style. - previous_ownership_transfer_date: Date of the most recent ownership transfer, if known. - registration_month: Month of registration (1–12). vat_displayed: If true the public price is displayed VAT-exposed (B2B); otherwise VAT-inclusive @@ -176,7 +162,6 @@ def create( body=maybe_transform( { "certified_km": certified_km, - "cost_price_eur": cost_price_eur, "motornet_code": motornet_code, "plate": plate, "registration_year": registration_year, @@ -186,17 +171,10 @@ def create( "description": description, "extended_warranty_enabled": extended_warranty_enabled, "extended_warranty_months": extended_warranty_months, - "inspection_expiry_date": inspection_expiry_date, "is_for_sale": is_for_sale, "is_visible": is_visible, - "last_service_date": last_service_date, - "last_service_km": last_service_km, - "last_service_notes": last_service_notes, "notes": notes, - "previous_owner_count": previous_owner_count, - "previous_ownership_transfer_date": previous_ownership_transfer_date, "registration_month": registration_month, - "road_tax_expiry_date": road_tax_expiry_date, "vat_displayed": vat_displayed, "vehicle_damaged": vehicle_damaged, "vin": vin, @@ -264,21 +242,13 @@ def update( alloy_wheel_size: Optional[int] | Omit = omit, certified_km: Optional[int] | Omit = omit, color: Optional[str] | Omit = omit, - cost_price_eur: Optional[float] | Omit = omit, description: Optional[str] | Omit = omit, extended_warranty_enabled: Optional[bool] | Omit = omit, extended_warranty_months: Optional[int] | Omit = omit, - inspection_expiry_date: Union[str, date, None] | Omit = omit, is_for_sale: Optional[bool] | Omit = omit, is_visible: Optional[bool] | Omit = omit, - last_service_date: Union[str, date, None] | Omit = omit, - last_service_km: Optional[int] | Omit = omit, - last_service_notes: Optional[str] | Omit = omit, notes: Optional[str] | Omit = omit, - previous_owner_count: Optional[int] | Omit = omit, - previous_ownership_transfer_date: Union[str, date, None] | Omit = omit, registration_month: Optional[int] | Omit = omit, - road_tax_expiry_date: Union[str, date, None] | Omit = omit, sale_price_eur: Optional[float] | Omit = omit, vat_displayed: Optional[bool] | Omit = omit, vehicle_damaged: Optional[bool] | Omit = omit, @@ -318,21 +288,13 @@ def update( "alloy_wheel_size": alloy_wheel_size, "certified_km": certified_km, "color": color, - "cost_price_eur": cost_price_eur, "description": description, "extended_warranty_enabled": extended_warranty_enabled, "extended_warranty_months": extended_warranty_months, - "inspection_expiry_date": inspection_expiry_date, "is_for_sale": is_for_sale, "is_visible": is_visible, - "last_service_date": last_service_date, - "last_service_km": last_service_km, - "last_service_notes": last_service_notes, "notes": notes, - "previous_owner_count": previous_owner_count, - "previous_ownership_transfer_date": previous_ownership_transfer_date, "registration_month": registration_month, - "road_tax_expiry_date": road_tax_expiry_date, "sale_price_eur": sale_price_eur, "vat_displayed": vat_displayed, "vehicle_damaged": vehicle_damaged, @@ -562,7 +524,6 @@ async def create( dealer_id: str, *, certified_km: int, - cost_price_eur: float, motornet_code: str, plate: str, registration_year: int, @@ -572,17 +533,10 @@ async def create( description: str | Omit = omit, extended_warranty_enabled: bool | Omit = omit, extended_warranty_months: Optional[int] | Omit = omit, - inspection_expiry_date: Union[str, date, None] | Omit = omit, is_for_sale: bool | Omit = omit, is_visible: bool | Omit = omit, - last_service_date: Union[str, date, None] | Omit = omit, - last_service_km: Optional[int] | Omit = omit, - last_service_notes: Optional[str] | Omit = omit, notes: Optional[str] | Omit = omit, - previous_owner_count: Optional[int] | Omit = omit, - previous_ownership_transfer_date: Union[str, date, None] | Omit = omit, registration_month: Optional[int] | Omit = omit, - road_tax_expiry_date: Union[str, date, None] | Omit = omit, vat_displayed: bool | Omit = omit, vehicle_damaged: bool | Omit = omit, vin: Optional[str] | Omit = omit, @@ -608,9 +562,6 @@ async def create( Args: certified_km: Certified odometer reading at intake, in kilometres. - cost_price_eur: Cost basis to the dealer in EUR (partner/dealer internal). Not surfaced on - consumer-facing AI surfaces; used by dealer reporting and margin analytics only. - motornet_code: Motornet UNI code identifying the exact vehicle configuration. Must exist in `mnet_dettagli_usato` at submission time; otherwise the call returns 422 `motornet_code_not_in_catalogue`. The partner is expected to source this from @@ -635,8 +586,6 @@ async def create( notes: Free-form short notes; surfaced as `mnet_dettagli.precisazioni`-style. - previous_ownership_transfer_date: Date of the most recent ownership transfer, if known. - registration_month: Month of registration (1–12). vat_displayed: If true the public price is displayed VAT-exposed (B2B); otherwise VAT-inclusive @@ -660,7 +609,6 @@ async def create( body=await async_maybe_transform( { "certified_km": certified_km, - "cost_price_eur": cost_price_eur, "motornet_code": motornet_code, "plate": plate, "registration_year": registration_year, @@ -670,17 +618,10 @@ async def create( "description": description, "extended_warranty_enabled": extended_warranty_enabled, "extended_warranty_months": extended_warranty_months, - "inspection_expiry_date": inspection_expiry_date, "is_for_sale": is_for_sale, "is_visible": is_visible, - "last_service_date": last_service_date, - "last_service_km": last_service_km, - "last_service_notes": last_service_notes, "notes": notes, - "previous_owner_count": previous_owner_count, - "previous_ownership_transfer_date": previous_ownership_transfer_date, "registration_month": registration_month, - "road_tax_expiry_date": road_tax_expiry_date, "vat_displayed": vat_displayed, "vehicle_damaged": vehicle_damaged, "vin": vin, @@ -748,21 +689,13 @@ async def update( alloy_wheel_size: Optional[int] | Omit = omit, certified_km: Optional[int] | Omit = omit, color: Optional[str] | Omit = omit, - cost_price_eur: Optional[float] | Omit = omit, description: Optional[str] | Omit = omit, extended_warranty_enabled: Optional[bool] | Omit = omit, extended_warranty_months: Optional[int] | Omit = omit, - inspection_expiry_date: Union[str, date, None] | Omit = omit, is_for_sale: Optional[bool] | Omit = omit, is_visible: Optional[bool] | Omit = omit, - last_service_date: Union[str, date, None] | Omit = omit, - last_service_km: Optional[int] | Omit = omit, - last_service_notes: Optional[str] | Omit = omit, notes: Optional[str] | Omit = omit, - previous_owner_count: Optional[int] | Omit = omit, - previous_ownership_transfer_date: Union[str, date, None] | Omit = omit, registration_month: Optional[int] | Omit = omit, - road_tax_expiry_date: Union[str, date, None] | Omit = omit, sale_price_eur: Optional[float] | Omit = omit, vat_displayed: Optional[bool] | Omit = omit, vehicle_damaged: Optional[bool] | Omit = omit, @@ -802,21 +735,13 @@ async def update( "alloy_wheel_size": alloy_wheel_size, "certified_km": certified_km, "color": color, - "cost_price_eur": cost_price_eur, "description": description, "extended_warranty_enabled": extended_warranty_enabled, "extended_warranty_months": extended_warranty_months, - "inspection_expiry_date": inspection_expiry_date, "is_for_sale": is_for_sale, "is_visible": is_visible, - "last_service_date": last_service_date, - "last_service_km": last_service_km, - "last_service_notes": last_service_notes, "notes": notes, - "previous_owner_count": previous_owner_count, - "previous_ownership_transfer_date": previous_ownership_transfer_date, "registration_month": registration_month, - "road_tax_expiry_date": road_tax_expiry_date, "sale_price_eur": sale_price_eur, "vat_displayed": vat_displayed, "vehicle_damaged": vehicle_damaged, diff --git a/src/partnermax/types/dealers/__init__.py b/src/partnermax/types/dealers/__init__.py index f97da52..9e42df0 100644 --- a/src/partnermax/types/dealers/__init__.py +++ b/src/partnermax/types/dealers/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations +from .ai_content import AIContent as AIContent from .nlt_settings import NltSettings as NltSettings from .vehicle_list import VehicleList as VehicleList from .vehicle_detail import VehicleDetail as VehicleDetail diff --git a/src/partnermax/types/dealers/ai_content.py b/src/partnermax/types/dealers/ai_content.py new file mode 100644 index 0000000..a7eb24d --- /dev/null +++ b/src/partnermax/types/dealers/ai_content.py @@ -0,0 +1,65 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime + +from ..._models import BaseModel + +__all__ = ["AIContent"] + + +class AIContent(BaseModel): + """AI-generated editorial content for a single vehicle. + + Produced asynchronously by the ``usato_ai_content_worker`` in + ``azurenet-engine`` within ~60 seconds of vehicle creation. While the + worker is still pending, every field is ``null``; once the worker + completes the row this object carries the full editorial set the + cross-network AI consumers (MCP, ChatGPT Custom GPT, NLWeb) display. + + Layered descriptions: + + * ``tagline`` — 8–12 word headline. Use on listing cards / push notifications. + * ``short`` — 1–2 sentence summary (≤ 220 chars). Use as the meta description fallback. + * ``medium`` — paragraph (~400 chars). Use on vehicle-detail SEO blurbs. + * ``long`` — full marketing description (1500–3000 chars). Use on detail pages. + * ``highlights`` — array of 3–7 selling points. Render as a bullet list above the description. + * ``faq`` — array of ``{question, answer}`` objects. Render as accordion / JSON-LD ``FAQPage``. + * ``seo_title`` — ≤ 60 chars, ````-ready. + * ``seo_description`` — ≤ 160 chars, meta description-ready. + * ``slug`` — URL-safe slug used in the canonical URL on the dealer site. + + The Italian language is canonical (``lang='it'``). Multi-language is + on the roadmap; until then the partner gets exactly what the + consumer AI surfaces get. + """ + + faq: Optional[List[Dict[str, str]]] = None + """Array of `{question, answer}` objects. + + Each entry has two string keys; render with the partner's own FAQ UI or feed + into a `FAQPage` JSON-LD block. + """ + + generated_at: Optional[datetime] = None + """UTC timestamp of the most recent AI generation. + + `null` until the worker first processes the vehicle (≤ 60 seconds after vehicle + creation). + """ + + highlights: Optional[List[str]] = None + + long: Optional[str] = None + + medium: Optional[str] = None + + seo_description: Optional[str] = None + + seo_title: Optional[str] = None + + short: Optional[str] = None + + slug: Optional[str] = None + + tagline: Optional[str] = None diff --git a/src/partnermax/types/dealers/bulk_row_outcome.py b/src/partnermax/types/dealers/bulk_row_outcome.py index e3b6cb7..83d8b98 100644 --- a/src/partnermax/types/dealers/bulk_row_outcome.py +++ b/src/partnermax/types/dealers/bulk_row_outcome.py @@ -39,9 +39,22 @@ class BulkRowOutcome(BaseModel): Returned by `GET /v1/dealers/{id}/vehicles/{id}`, `POST /v1/dealers/{id}/vehicles`, and `PATCH /v1/dealers/{id}/vehicles/{id}`. - `technical_details` carries the flat Motornet specs dict (Italian column names - as keys: `cilindrata`, `kw`, `hp`, `lunghezza`, `consumo_medio`, - `emissioni_co2`, etc.). Same shape conventions as `NltOfferDetail` - (`feedback_partnermax_field_naming_us_english`: field names are English - snake_case, raw catalogue values stay verbatim). + Carries three layers of information: + + - **Partner-supplied** — what the partner posted (`plate`, `description`, + `sale_price_eur`, etc.). + - **Catalogue-derived** — `technical_details` is the flat `mnet_dettagli_usato` + dict (Italian column keys: `cilindrata`, `kw`, `hp`, `lunghezza`, + `consumo_medio`, `emissioni_co2`, etc.). Same shape conventions as + `NltOfferDetail` per `feedback_partnermax_field_naming_us_english`. + - **AI-derived** — `ai_content` carries the editorial output the cross-network + consumers display (descriptions, highlights, FAQ, SEO meta). `null` until the + worker has processed the vehicle. + + Fields the partner does NOT see through this surface (because they are + dealer-internal margin/operations data the partner does not own): + `cost_price_eur`, `inspection_expiry_date`, `road_tax_expiry_date`, + `previous_owner_count`, `previous_ownership_transfer_date`, `last_service_*`. + These exist in the underlying DB tables for the DealerMAX dashboard but are + intentionally not exposed via the SDK. """ diff --git a/src/partnermax/types/dealers/vehicle_bulk_params.py b/src/partnermax/types/dealers/vehicle_bulk_params.py index 38d9fcb..35578ad 100644 --- a/src/partnermax/types/dealers/vehicle_bulk_params.py +++ b/src/partnermax/types/dealers/vehicle_bulk_params.py @@ -2,8 +2,7 @@ from __future__ import annotations -from typing import Union, Iterable, Optional -from datetime import date +from typing import Iterable, Optional from typing_extensions import Required, Annotated, TypedDict from ..._utils import PropertyInfo @@ -40,13 +39,6 @@ class Vehicle(TypedDict, total=False): certified_km: Required[int] """Certified odometer reading at intake, in kilometres.""" - cost_price_eur: Required[float] - """Cost basis to the dealer in EUR (partner/dealer internal). - - Not surfaced on consumer-facing AI surfaces; used by dealer reporting and margin - analytics only. - """ - motornet_code: Required[str] """Motornet UNI code identifying the exact vehicle configuration. @@ -84,8 +76,6 @@ class Vehicle(TypedDict, total=False): extended_warranty_months: Optional[int] - inspection_expiry_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - is_for_sale: bool """Maps to `azlease_usatoauto.is_vendita_enabled`. @@ -99,25 +89,12 @@ class Vehicle(TypedDict, total=False): surfaces. Maps to `azlease_usatoin.visibile`. """ - last_service_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - - last_service_km: Optional[int] - - last_service_notes: Optional[str] - notes: Optional[str] """Free-form short notes; surfaced as `mnet_dettagli.precisazioni`-style.""" - previous_owner_count: Optional[int] - - previous_ownership_transfer_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - """Date of the most recent ownership transfer, if known.""" - registration_month: Optional[int] """Month of registration (1–12).""" - road_tax_expiry_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - vat_displayed: bool """ If true the public price is displayed VAT-exposed (B2B); otherwise VAT-inclusive diff --git a/src/partnermax/types/dealers/vehicle_create_params.py b/src/partnermax/types/dealers/vehicle_create_params.py index ed80776..6dfda24 100644 --- a/src/partnermax/types/dealers/vehicle_create_params.py +++ b/src/partnermax/types/dealers/vehicle_create_params.py @@ -2,8 +2,7 @@ from __future__ import annotations -from typing import Union, Optional -from datetime import date +from typing import Optional from typing_extensions import Required, Annotated, TypedDict from ..._utils import PropertyInfo @@ -15,13 +14,6 @@ class VehicleCreateParams(TypedDict, total=False): certified_km: Required[int] """Certified odometer reading at intake, in kilometres.""" - cost_price_eur: Required[float] - """Cost basis to the dealer in EUR (partner/dealer internal). - - Not surfaced on consumer-facing AI surfaces; used by dealer reporting and margin - analytics only. - """ - motornet_code: Required[str] """Motornet UNI code identifying the exact vehicle configuration. @@ -59,8 +51,6 @@ class VehicleCreateParams(TypedDict, total=False): extended_warranty_months: Optional[int] - inspection_expiry_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - is_for_sale: bool """Maps to `azlease_usatoauto.is_vendita_enabled`. @@ -74,25 +64,12 @@ class VehicleCreateParams(TypedDict, total=False): surfaces. Maps to `azlease_usatoin.visibile`. """ - last_service_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - - last_service_km: Optional[int] - - last_service_notes: Optional[str] - notes: Optional[str] """Free-form short notes; surfaced as `mnet_dettagli.precisazioni`-style.""" - previous_owner_count: Optional[int] - - previous_ownership_transfer_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - """Date of the most recent ownership transfer, if known.""" - registration_month: Optional[int] """Month of registration (1–12).""" - road_tax_expiry_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - vat_displayed: bool """ If true the public price is displayed VAT-exposed (B2B); otherwise VAT-inclusive diff --git a/src/partnermax/types/dealers/vehicle_detail.py b/src/partnermax/types/dealers/vehicle_detail.py index e25fce1..a243d04 100644 --- a/src/partnermax/types/dealers/vehicle_detail.py +++ b/src/partnermax/types/dealers/vehicle_detail.py @@ -1,9 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, List, Optional -from datetime import date, datetime +from datetime import datetime from ..._models import BaseModel +from .ai_content import AIContent __all__ = ["VehicleDetail"] @@ -14,17 +15,29 @@ class VehicleDetail(BaseModel): Returned by `GET /v1/dealers/{id}/vehicles/{id}`, `POST /v1/dealers/{id}/vehicles`, and `PATCH /v1/dealers/{id}/vehicles/{id}`. - `technical_details` carries the flat Motornet specs dict (Italian column - names as keys: `cilindrata`, `kw`, `hp`, `lunghezza`, `consumo_medio`, - `emissioni_co2`, etc.). Same shape conventions as `NltOfferDetail` - (`feedback_partnermax_field_naming_us_english`: field names are - English snake_case, raw catalogue values stay verbatim). + Carries three layers of information: + + * **Partner-supplied** — what the partner posted (``plate``, ``description``, + ``sale_price_eur``, etc.). + * **Catalogue-derived** — ``technical_details`` is the flat + ``mnet_dettagli_usato`` dict (Italian column keys: ``cilindrata``, ``kw``, + ``hp``, ``lunghezza``, ``consumo_medio``, ``emissioni_co2``, etc.). + Same shape conventions as ``NltOfferDetail`` per + ``feedback_partnermax_field_naming_us_english``. + * **AI-derived** — ``ai_content`` carries the editorial output the + cross-network consumers display (descriptions, highlights, FAQ, + SEO meta). ``null`` until the worker has processed the vehicle. + + Fields the partner does NOT see through this surface (because they + are dealer-internal margin/operations data the partner does not own): + ``cost_price_eur``, ``inspection_expiry_date``, ``road_tax_expiry_date``, + ``previous_owner_count``, ``previous_ownership_transfer_date``, + ``last_service_*``. These exist in the underlying DB tables for the + DealerMAX dashboard but are intentionally not exposed via the SDK. """ certified_km: int - cost_price_eur: float - created_at: datetime dealer_id: str @@ -55,6 +68,13 @@ class VehicleDetail(BaseModel): vehicle_id: str + ai_content: Optional[AIContent] = None + """Editorial content generated by the partnermax AI pipeline. + + `null` immediately after `POST` until the worker has produced the row (≤ 60 + seconds). Populated for the same consumer-AI surfaces (MCP, Custom GPT, NLWeb). + """ + alloy_wheel_size: Optional[int] = None brand: Optional[str] = None @@ -66,28 +86,18 @@ class VehicleDetail(BaseModel): fuel_type: Optional[str] = None image_urls: Optional[List[str]] = None - """Vehicle photos. Empty in v1 (media upload ships in v1.2).""" - - inspection_expiry_date: Optional[date] = None - - last_service_date: Optional[date] = None + """Vehicle photos in display order. - last_service_km: Optional[int] = None - - last_service_notes: Optional[str] = None + The first entry is the cover photo (`position=1` in the dedicated images + endpoint). + """ model: Optional[str] = None notes: Optional[str] = None - previous_owner_count: Optional[int] = None - - previous_ownership_transfer_date: Optional[date] = None - registration_month: Optional[int] = None - road_tax_expiry_date: Optional[date] = None - technical_details: Optional[Dict[str, object]] = None """ Flat dict of every non-null `mnet_dettagli_usato` column for this diff --git a/src/partnermax/types/dealers/vehicle_update_params.py b/src/partnermax/types/dealers/vehicle_update_params.py index 5707c59..eaa57da 100644 --- a/src/partnermax/types/dealers/vehicle_update_params.py +++ b/src/partnermax/types/dealers/vehicle_update_params.py @@ -2,8 +2,7 @@ from __future__ import annotations -from typing import Union, Optional -from datetime import date +from typing import Optional from typing_extensions import Required, Annotated, TypedDict from ..._utils import PropertyInfo @@ -20,36 +19,20 @@ class VehicleUpdateParams(TypedDict, total=False): color: Optional[str] - cost_price_eur: Optional[float] - description: Optional[str] extended_warranty_enabled: Optional[bool] extended_warranty_months: Optional[int] - inspection_expiry_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - is_for_sale: Optional[bool] is_visible: Optional[bool] - last_service_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - - last_service_km: Optional[int] - - last_service_notes: Optional[str] - notes: Optional[str] - previous_owner_count: Optional[int] - - previous_ownership_transfer_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - registration_month: Optional[int] - road_tax_expiry_date: Annotated[Union[str, date, None], PropertyInfo(format="iso8601")] - sale_price_eur: Optional[float] vat_displayed: Optional[bool] diff --git a/tests/api_resources/dealers/test_vehicles.py b/tests/api_resources/dealers/test_vehicles.py index 53f0af6..ddd1183 100644 --- a/tests/api_resources/dealers/test_vehicles.py +++ b/tests/api_resources/dealers/test_vehicles.py @@ -9,7 +9,6 @@ from partnermax import Partnermax, AsyncPartnermax from tests.utils import assert_matches_type -from partnermax._utils import parse_date from partnermax.types.dealers import ( VehicleList, VehicleDetail, @@ -28,7 +27,6 @@ def test_method_create(self, client: Partnermax) -> None: vehicle = client.dealers.vehicles.create( dealer_id="dealer_id", certified_km=0, - cost_price_eur=100, motornet_code="xxxx", plate="26F1KLZN", registration_year=1960, @@ -42,7 +40,6 @@ def test_method_create_with_all_params(self, client: Partnermax) -> None: vehicle = client.dealers.vehicles.create( dealer_id="dealer_id", certified_km=0, - cost_price_eur=100, motornet_code="xxxx", plate="26F1KLZN", registration_year=1960, @@ -52,17 +49,10 @@ def test_method_create_with_all_params(self, client: Partnermax) -> None: description="description", extended_warranty_enabled=True, extended_warranty_months=1, - inspection_expiry_date=parse_date("2019-12-27"), is_for_sale=True, is_visible=True, - last_service_date=parse_date("2019-12-27"), - last_service_km=0, - last_service_notes="last_service_notes", notes="notes", - previous_owner_count=0, - previous_ownership_transfer_date=parse_date("2019-12-27"), registration_month=1, - road_tax_expiry_date=parse_date("2019-12-27"), vat_displayed=True, vehicle_damaged=True, vin="PTNLCJPPNYGP316PJ", @@ -76,7 +66,6 @@ def test_raw_response_create(self, client: Partnermax) -> None: response = client.dealers.vehicles.with_raw_response.create( dealer_id="dealer_id", certified_km=0, - cost_price_eur=100, motornet_code="xxxx", plate="26F1KLZN", registration_year=1960, @@ -94,7 +83,6 @@ def test_streaming_response_create(self, client: Partnermax) -> None: with client.dealers.vehicles.with_streaming_response.create( dealer_id="dealer_id", certified_km=0, - cost_price_eur=100, motornet_code="xxxx", plate="26F1KLZN", registration_year=1960, @@ -115,7 +103,6 @@ def test_path_params_create(self, client: Partnermax) -> None: client.dealers.vehicles.with_raw_response.create( dealer_id="", certified_km=0, - cost_price_eur=100, motornet_code="xxxx", plate="26F1KLZN", registration_year=1960, @@ -202,21 +189,13 @@ def test_method_update_with_all_params(self, client: Partnermax) -> None: alloy_wheel_size=13, certified_km=0, color="color", - cost_price_eur=100, description="description", extended_warranty_enabled=True, extended_warranty_months=1, - inspection_expiry_date=parse_date("2019-12-27"), is_for_sale=True, is_visible=True, - last_service_date=parse_date("2019-12-27"), - last_service_km=0, - last_service_notes="last_service_notes", notes="notes", - previous_owner_count=0, - previous_ownership_transfer_date=parse_date("2019-12-27"), registration_month=1, - road_tax_expiry_date=parse_date("2019-12-27"), sale_price_eur=100, vat_displayed=True, vehicle_damaged=True, @@ -382,7 +361,6 @@ def test_method_bulk(self, client: Partnermax) -> None: vehicles=[ { "certified_km": 0, - "cost_price_eur": 100, "motornet_code": "xxxx", "plate": "26F1KLZN", "registration_year": 1960, @@ -400,7 +378,6 @@ def test_method_bulk_with_all_params(self, client: Partnermax) -> None: vehicles=[ { "certified_km": 0, - "cost_price_eur": 100, "motornet_code": "xxxx", "plate": "26F1KLZN", "registration_year": 1960, @@ -410,17 +387,10 @@ def test_method_bulk_with_all_params(self, client: Partnermax) -> None: "description": "description", "extended_warranty_enabled": True, "extended_warranty_months": 1, - "inspection_expiry_date": parse_date("2019-12-27"), "is_for_sale": True, "is_visible": True, - "last_service_date": parse_date("2019-12-27"), - "last_service_km": 0, - "last_service_notes": "last_service_notes", "notes": "notes", - "previous_owner_count": 0, - "previous_ownership_transfer_date": parse_date("2019-12-27"), "registration_month": 1, - "road_tax_expiry_date": parse_date("2019-12-27"), "vat_displayed": True, "vehicle_damaged": True, "vin": "PTNLCJPPNYGP316PJ", @@ -438,7 +408,6 @@ def test_raw_response_bulk(self, client: Partnermax) -> None: vehicles=[ { "certified_km": 0, - "cost_price_eur": 100, "motornet_code": "xxxx", "plate": "26F1KLZN", "registration_year": 1960, @@ -460,7 +429,6 @@ def test_streaming_response_bulk(self, client: Partnermax) -> None: vehicles=[ { "certified_km": 0, - "cost_price_eur": 100, "motornet_code": "xxxx", "plate": "26F1KLZN", "registration_year": 1960, @@ -485,7 +453,6 @@ def test_path_params_bulk(self, client: Partnermax) -> None: vehicles=[ { "certified_km": 0, - "cost_price_eur": 100, "motornet_code": "xxxx", "plate": "26F1KLZN", "registration_year": 1960, @@ -506,7 +473,6 @@ async def test_method_create(self, async_client: AsyncPartnermax) -> None: vehicle = await async_client.dealers.vehicles.create( dealer_id="dealer_id", certified_km=0, - cost_price_eur=100, motornet_code="xxxx", plate="26F1KLZN", registration_year=1960, @@ -520,7 +486,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncPartnermax vehicle = await async_client.dealers.vehicles.create( dealer_id="dealer_id", certified_km=0, - cost_price_eur=100, motornet_code="xxxx", plate="26F1KLZN", registration_year=1960, @@ -530,17 +495,10 @@ async def test_method_create_with_all_params(self, async_client: AsyncPartnermax description="description", extended_warranty_enabled=True, extended_warranty_months=1, - inspection_expiry_date=parse_date("2019-12-27"), is_for_sale=True, is_visible=True, - last_service_date=parse_date("2019-12-27"), - last_service_km=0, - last_service_notes="last_service_notes", notes="notes", - previous_owner_count=0, - previous_ownership_transfer_date=parse_date("2019-12-27"), registration_month=1, - road_tax_expiry_date=parse_date("2019-12-27"), vat_displayed=True, vehicle_damaged=True, vin="PTNLCJPPNYGP316PJ", @@ -554,7 +512,6 @@ async def test_raw_response_create(self, async_client: AsyncPartnermax) -> None: response = await async_client.dealers.vehicles.with_raw_response.create( dealer_id="dealer_id", certified_km=0, - cost_price_eur=100, motornet_code="xxxx", plate="26F1KLZN", registration_year=1960, @@ -572,7 +529,6 @@ async def test_streaming_response_create(self, async_client: AsyncPartnermax) -> async with async_client.dealers.vehicles.with_streaming_response.create( dealer_id="dealer_id", certified_km=0, - cost_price_eur=100, motornet_code="xxxx", plate="26F1KLZN", registration_year=1960, @@ -593,7 +549,6 @@ async def test_path_params_create(self, async_client: AsyncPartnermax) -> None: await async_client.dealers.vehicles.with_raw_response.create( dealer_id="", certified_km=0, - cost_price_eur=100, motornet_code="xxxx", plate="26F1KLZN", registration_year=1960, @@ -680,21 +635,13 @@ async def test_method_update_with_all_params(self, async_client: AsyncPartnermax alloy_wheel_size=13, certified_km=0, color="color", - cost_price_eur=100, description="description", extended_warranty_enabled=True, extended_warranty_months=1, - inspection_expiry_date=parse_date("2019-12-27"), is_for_sale=True, is_visible=True, - last_service_date=parse_date("2019-12-27"), - last_service_km=0, - last_service_notes="last_service_notes", notes="notes", - previous_owner_count=0, - previous_ownership_transfer_date=parse_date("2019-12-27"), registration_month=1, - road_tax_expiry_date=parse_date("2019-12-27"), sale_price_eur=100, vat_displayed=True, vehicle_damaged=True, @@ -860,7 +807,6 @@ async def test_method_bulk(self, async_client: AsyncPartnermax) -> None: vehicles=[ { "certified_km": 0, - "cost_price_eur": 100, "motornet_code": "xxxx", "plate": "26F1KLZN", "registration_year": 1960, @@ -878,7 +824,6 @@ async def test_method_bulk_with_all_params(self, async_client: AsyncPartnermax) vehicles=[ { "certified_km": 0, - "cost_price_eur": 100, "motornet_code": "xxxx", "plate": "26F1KLZN", "registration_year": 1960, @@ -888,17 +833,10 @@ async def test_method_bulk_with_all_params(self, async_client: AsyncPartnermax) "description": "description", "extended_warranty_enabled": True, "extended_warranty_months": 1, - "inspection_expiry_date": parse_date("2019-12-27"), "is_for_sale": True, "is_visible": True, - "last_service_date": parse_date("2019-12-27"), - "last_service_km": 0, - "last_service_notes": "last_service_notes", "notes": "notes", - "previous_owner_count": 0, - "previous_ownership_transfer_date": parse_date("2019-12-27"), "registration_month": 1, - "road_tax_expiry_date": parse_date("2019-12-27"), "vat_displayed": True, "vehicle_damaged": True, "vin": "PTNLCJPPNYGP316PJ", @@ -916,7 +854,6 @@ async def test_raw_response_bulk(self, async_client: AsyncPartnermax) -> None: vehicles=[ { "certified_km": 0, - "cost_price_eur": 100, "motornet_code": "xxxx", "plate": "26F1KLZN", "registration_year": 1960, @@ -938,7 +875,6 @@ async def test_streaming_response_bulk(self, async_client: AsyncPartnermax) -> N vehicles=[ { "certified_km": 0, - "cost_price_eur": 100, "motornet_code": "xxxx", "plate": "26F1KLZN", "registration_year": 1960, @@ -963,7 +899,6 @@ async def test_path_params_bulk(self, async_client: AsyncPartnermax) -> None: vehicles=[ { "certified_km": 0, - "cost_price_eur": 100, "motornet_code": "xxxx", "plate": "26F1KLZN", "registration_year": 1960, From 570b71b66728aeb27db3078d5bd5cebe433dbf70 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 16:30:01 +0000 Subject: [PATCH 2/3] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index aa1effc..cef3e65 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 21 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/azure/partnermax-8e9792fdc8ae3014eba29b0de5b3fb675466f979bf88c66c73f957ce353bf0a1.yml -openapi_spec_hash: 373fc725db05b75b4bd515667c8a8d12 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/azure/partnermax-aee817a9450d1094d357a560cebc1c876863fb7d1c712efaf2509a567cd55954.yml +openapi_spec_hash: 6f576691201740bbee9e1f7f97bdd9b0 config_hash: 18c6c7df17bad3320b9f2c126947f00a From 496b1a230752b84f9f64ae45a3af5b66097b6661 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 18 May 2026 16:30:24 +0000 Subject: [PATCH 3/3] release: 0.10.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ pyproject.toml | 2 +- src/partnermax/_version.py | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6d78745..091cfb1 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.9.0" + ".": "0.10.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5412df1..009af4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.10.0 (2026-05-18) + +Full Changelog: [v0.9.0...v0.10.0](https://github.com/DealerMax-app/partnermax-python/compare/v0.9.0...v0.10.0) + +### Features + +* **vehicles:** used-vehicle CRUD + bulk insert for v1.1.0 ([85e4b4f](https://github.com/DealerMax-app/partnermax-python/commit/85e4b4fb69db79b37dbb528c403763138d147ce4)) + ## 0.9.0 (2026-05-18) Full Changelog: [v0.8.0...v0.9.0](https://github.com/DealerMax-app/partnermax-python/compare/v0.8.0...v0.9.0) diff --git a/pyproject.toml b/pyproject.toml index a1e3262..3a90c52 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "partnermax" -version = "0.9.0" +version = "0.10.0" description = "The official Python library for the partnermax API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/partnermax/_version.py b/src/partnermax/_version.py index f52be1e..a5b18a0 100644 --- a/src/partnermax/_version.py +++ b/src/partnermax/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "partnermax" -__version__ = "0.9.0" # x-release-please-version +__version__ = "0.10.0" # x-release-please-version