"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from __future__ import annotations
from .address import Address, AddressTypedDict
from .currency import Currency
from .customfield import CustomField, CustomFieldTypedDict
from .linkedcustomer import LinkedCustomer, LinkedCustomerTypedDict
from .linkedcustomer_input import LinkedCustomerInput, LinkedCustomerInputTypedDict
from .linkedtaxrate import LinkedTaxRate, LinkedTaxRateTypedDict
from .linkedtaxrate_input import LinkedTaxRateInput, LinkedTaxRateInputTypedDict
from .linkedtrackingcategory import (
    LinkedTrackingCategory,
    LinkedTrackingCategoryTypedDict,
)
from apideck_unify.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
from datetime import date, datetime
from enum import Enum
from pydantic import model_serializer
from typing import List, Optional
from typing_extensions import NotRequired, TypedDict


class ProjectProjectStatus(str, Enum):
    r"""Current status of the project"""

    ACTIVE = "active"
    COMPLETED = "completed"
    ON_HOLD = "on_hold"
    CANCELLED = "cancelled"
    DRAFT = "draft"
    IN_PROGRESS = "in_progress"
    APPROVED = "approved"
    OTHER = "other"


class ProjectType(str, Enum):
    r"""Type or category of the project"""

    CLIENT_PROJECT = "client_project"
    INTERNAL_PROJECT = "internal_project"
    MAINTENANCE = "maintenance"
    RESEARCH_DEVELOPMENT = "research_development"
    TRAINING = "training"
    OTHER = "other"


class Priority(str, Enum):
    r"""Priority level of the project"""

    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"


class ProjectDepartmentTypedDict(TypedDict):
    r"""Department or organizational unit associated with the project"""

    id: NotRequired[str]
    r"""Unique identifier for the department"""
    name: NotRequired[str]
    r"""Name of the department"""


class ProjectDepartment(BaseModel):
    r"""Department or organizational unit associated with the project"""

    id: Optional[str] = None
    r"""Unique identifier for the department"""

    name: Optional[str] = None
    r"""Name of the department"""


class ParentProjectTypedDict(TypedDict):
    r"""Parent project if this is a subproject"""

    id: NotRequired[str]
    r"""Unique identifier for the parent project"""
    name: NotRequired[str]
    r"""Name of the parent project"""


class ParentProject(BaseModel):
    r"""Parent project if this is a subproject"""

    id: Optional[str] = None
    r"""Unique identifier for the parent project"""

    name: Optional[str] = None
    r"""Name of the parent project"""


class BillingMethod(str, Enum):
    r"""Method used for billing this project"""

    FIXED_PRICE = "fixed_price"
    TIME_AND_MATERIALS = "time_and_materials"
    MILESTONE_BASED = "milestone_based"
    RETAINER = "retainer"
    NON_BILLABLE = "non_billable"


class ProjectPhase(str, Enum):
    r"""Current phase of the project lifecycle"""

    INITIATION = "initiation"
    PLANNING = "planning"
    EXECUTION = "execution"
    MONITORING = "monitoring"
    CLOSURE = "closure"
    OTHER = "other"


class ScheduleStatus(str, Enum):
    r"""Current status of project schedule compared to plan"""

    AHEAD_OF_SCHEDULE = "ahead_of_schedule"
    ON_SCHEDULE = "on_schedule"
    BEHIND_SCHEDULE = "behind_schedule"
    CRITICAL_DELAY = "critical_delay"


class ProjectTypedDict(TypedDict):
    name: str
    r"""Name of the project"""
    id: NotRequired[str]
    r"""A unique identifier for an object."""
    downstream_id: NotRequired[Nullable[str]]
    r"""The third-party API ID of original entity"""
    display_id: NotRequired[Nullable[str]]
    r"""User-friendly project identifier"""
    reference_id: NotRequired[Nullable[str]]
    r"""External reference identifier for the project"""
    description: NotRequired[Nullable[str]]
    r"""Detailed description of the project"""
    status: NotRequired[Nullable[ProjectProjectStatus]]
    r"""Current status of the project"""
    active: NotRequired[Nullable[bool]]
    r"""Indicates whether the project is currently active or inactive"""
    project_type: NotRequired[Nullable[ProjectType]]
    r"""Type or category of the project"""
    priority: NotRequired[Nullable[Priority]]
    r"""Priority level of the project"""
    completion_percentage: NotRequired[Nullable[float]]
    r"""Percentage of project completion (0-100)"""
    start_date: NotRequired[Nullable[date]]
    r"""Start date of the project"""
    end_date: NotRequired[Nullable[date]]
    r"""Expected or actual end date of the project"""
    customer: NotRequired[Nullable[LinkedCustomerTypedDict]]
    r"""The customer this entity is linked to."""
    department: NotRequired[Nullable[ProjectDepartmentTypedDict]]
    r"""Department or organizational unit associated with the project"""
    company_id: NotRequired[Nullable[str]]
    r"""The company ID the transaction belongs to"""
    owner_id: NotRequired[Nullable[str]]
    r"""ID of the user who owns/manages this project"""
    parent_project: NotRequired[Nullable[ParentProjectTypedDict]]
    r"""Parent project if this is a subproject"""
    currency: NotRequired[Nullable[Currency]]
    r"""Indicates the associated currency for an amount of money. Values correspond to [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)."""
    budget_amount: NotRequired[Nullable[float]]
    r"""Total budgeted amount for the project"""
    approved_amount: NotRequired[Nullable[float]]
    r"""Approved budget amount for the project"""
    actual_amount: NotRequired[Nullable[float]]
    r"""Total actual amount spent on the project"""
    budget_hours: NotRequired[Nullable[float]]
    r"""Total budgeted hours for the project"""
    actual_hours: NotRequired[Nullable[float]]
    r"""Total actual hours worked on the project"""
    hourly_rate: NotRequired[Nullable[float]]
    r"""Default hourly rate for project work"""
    billing_method: NotRequired[Nullable[BillingMethod]]
    r"""Method used for billing this project"""
    is_billable: NotRequired[Nullable[bool]]
    r"""Indicates if the project is billable to the customer"""
    phase: NotRequired[Nullable[ProjectPhase]]
    r"""Current phase of the project lifecycle"""
    tax_rate: NotRequired[LinkedTaxRateTypedDict]
    tracking_categories: NotRequired[
        Nullable[List[Nullable[LinkedTrackingCategoryTypedDict]]]
    ]
    r"""A list of linked tracking categories."""
    tags: NotRequired[List[str]]
    r"""Tags associated with the project"""
    notes: NotRequired[Nullable[str]]
    r"""Additional notes about the project"""
    contract_number: NotRequired[Nullable[str]]
    r"""Contract or agreement number associated with the project"""
    profit_margin: NotRequired[Nullable[float]]
    r"""Expected profit margin percentage for the project"""
    schedule_status: NotRequired[Nullable[ScheduleStatus]]
    r"""Current status of project schedule compared to plan"""
    addresses: NotRequired[List[AddressTypedDict]]
    r"""An array of addresses associated with the project (billing, job site, etc.)"""
    team_size: NotRequired[Nullable[int]]
    r"""Number of team members assigned to the project"""
    custom_fields: NotRequired[List[CustomFieldTypedDict]]
    row_version: NotRequired[Nullable[str]]
    r"""A binary value used to detect updates to a object and prevent data conflicts. It is incremented each time an update is made to the object."""
    updated_by: NotRequired[Nullable[str]]
    r"""The user who last updated the object."""
    created_by: NotRequired[Nullable[str]]
    r"""The user who created the object."""
    created_at: NotRequired[Nullable[datetime]]
    r"""The date and time when the object was created."""
    updated_at: NotRequired[Nullable[datetime]]
    r"""The date and time when the object was last updated."""


class Project(BaseModel):
    name: str
    r"""Name of the project"""

    id: Optional[str] = None
    r"""A unique identifier for an object."""

    downstream_id: OptionalNullable[str] = UNSET
    r"""The third-party API ID of original entity"""

    display_id: OptionalNullable[str] = UNSET
    r"""User-friendly project identifier"""

    reference_id: OptionalNullable[str] = UNSET
    r"""External reference identifier for the project"""

    description: OptionalNullable[str] = UNSET
    r"""Detailed description of the project"""

    status: OptionalNullable[ProjectProjectStatus] = UNSET
    r"""Current status of the project"""

    active: OptionalNullable[bool] = UNSET
    r"""Indicates whether the project is currently active or inactive"""

    project_type: OptionalNullable[ProjectType] = UNSET
    r"""Type or category of the project"""

    priority: OptionalNullable[Priority] = UNSET
    r"""Priority level of the project"""

    completion_percentage: OptionalNullable[float] = UNSET
    r"""Percentage of project completion (0-100)"""

    start_date: OptionalNullable[date] = UNSET
    r"""Start date of the project"""

    end_date: OptionalNullable[date] = UNSET
    r"""Expected or actual end date of the project"""

    customer: OptionalNullable[LinkedCustomer] = UNSET
    r"""The customer this entity is linked to."""

    department: OptionalNullable[ProjectDepartment] = UNSET
    r"""Department or organizational unit associated with the project"""

    company_id: OptionalNullable[str] = UNSET
    r"""The company ID the transaction belongs to"""

    owner_id: OptionalNullable[str] = UNSET
    r"""ID of the user who owns/manages this project"""

    parent_project: OptionalNullable[ParentProject] = UNSET
    r"""Parent project if this is a subproject"""

    currency: OptionalNullable[Currency] = UNSET
    r"""Indicates the associated currency for an amount of money. Values correspond to [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)."""

    budget_amount: OptionalNullable[float] = UNSET
    r"""Total budgeted amount for the project"""

    approved_amount: OptionalNullable[float] = UNSET
    r"""Approved budget amount for the project"""

    actual_amount: OptionalNullable[float] = UNSET
    r"""Total actual amount spent on the project"""

    budget_hours: OptionalNullable[float] = UNSET
    r"""Total budgeted hours for the project"""

    actual_hours: OptionalNullable[float] = UNSET
    r"""Total actual hours worked on the project"""

    hourly_rate: OptionalNullable[float] = UNSET
    r"""Default hourly rate for project work"""

    billing_method: OptionalNullable[BillingMethod] = UNSET
    r"""Method used for billing this project"""

    is_billable: OptionalNullable[bool] = True
    r"""Indicates if the project is billable to the customer"""

    phase: OptionalNullable[ProjectPhase] = UNSET
    r"""Current phase of the project lifecycle"""

    tax_rate: Optional[LinkedTaxRate] = None

    tracking_categories: OptionalNullable[List[Nullable[LinkedTrackingCategory]]] = (
        UNSET
    )
    r"""A list of linked tracking categories."""

    tags: Optional[List[str]] = None
    r"""Tags associated with the project"""

    notes: OptionalNullable[str] = UNSET
    r"""Additional notes about the project"""

    contract_number: OptionalNullable[str] = UNSET
    r"""Contract or agreement number associated with the project"""

    profit_margin: OptionalNullable[float] = UNSET
    r"""Expected profit margin percentage for the project"""

    schedule_status: OptionalNullable[ScheduleStatus] = UNSET
    r"""Current status of project schedule compared to plan"""

    addresses: Optional[List[Address]] = None
    r"""An array of addresses associated with the project (billing, job site, etc.)"""

    team_size: OptionalNullable[int] = UNSET
    r"""Number of team members assigned to the project"""

    custom_fields: Optional[List[CustomField]] = None

    row_version: OptionalNullable[str] = UNSET
    r"""A binary value used to detect updates to a object and prevent data conflicts. It is incremented each time an update is made to the object."""

    updated_by: OptionalNullable[str] = UNSET
    r"""The user who last updated the object."""

    created_by: OptionalNullable[str] = UNSET
    r"""The user who created the object."""

    created_at: OptionalNullable[datetime] = UNSET
    r"""The date and time when the object was created."""

    updated_at: OptionalNullable[datetime] = UNSET
    r"""The date and time when the object was last updated."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "id",
            "downstream_id",
            "display_id",
            "reference_id",
            "description",
            "status",
            "active",
            "project_type",
            "priority",
            "completion_percentage",
            "start_date",
            "end_date",
            "customer",
            "department",
            "company_id",
            "owner_id",
            "parent_project",
            "currency",
            "budget_amount",
            "approved_amount",
            "actual_amount",
            "budget_hours",
            "actual_hours",
            "hourly_rate",
            "billing_method",
            "is_billable",
            "phase",
            "tax_rate",
            "tracking_categories",
            "tags",
            "notes",
            "contract_number",
            "profit_margin",
            "schedule_status",
            "addresses",
            "team_size",
            "custom_fields",
            "row_version",
            "updated_by",
            "created_by",
            "created_at",
            "updated_at",
        ]
        nullable_fields = [
            "downstream_id",
            "display_id",
            "reference_id",
            "description",
            "status",
            "active",
            "project_type",
            "priority",
            "completion_percentage",
            "start_date",
            "end_date",
            "customer",
            "department",
            "company_id",
            "owner_id",
            "parent_project",
            "currency",
            "budget_amount",
            "approved_amount",
            "actual_amount",
            "budget_hours",
            "actual_hours",
            "hourly_rate",
            "billing_method",
            "is_billable",
            "phase",
            "tracking_categories",
            "notes",
            "contract_number",
            "profit_margin",
            "schedule_status",
            "team_size",
            "row_version",
            "updated_by",
            "created_by",
            "created_at",
            "updated_at",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class ProjectInputTypedDict(TypedDict):
    name: str
    r"""Name of the project"""
    display_id: NotRequired[Nullable[str]]
    r"""User-friendly project identifier"""
    reference_id: NotRequired[Nullable[str]]
    r"""External reference identifier for the project"""
    description: NotRequired[Nullable[str]]
    r"""Detailed description of the project"""
    status: NotRequired[Nullable[ProjectProjectStatus]]
    r"""Current status of the project"""
    active: NotRequired[Nullable[bool]]
    r"""Indicates whether the project is currently active or inactive"""
    project_type: NotRequired[Nullable[ProjectType]]
    r"""Type or category of the project"""
    priority: NotRequired[Nullable[Priority]]
    r"""Priority level of the project"""
    completion_percentage: NotRequired[Nullable[float]]
    r"""Percentage of project completion (0-100)"""
    start_date: NotRequired[Nullable[date]]
    r"""Start date of the project"""
    end_date: NotRequired[Nullable[date]]
    r"""Expected or actual end date of the project"""
    customer: NotRequired[Nullable[LinkedCustomerInputTypedDict]]
    r"""The customer this entity is linked to."""
    department: NotRequired[Nullable[ProjectDepartmentTypedDict]]
    r"""Department or organizational unit associated with the project"""
    company_id: NotRequired[Nullable[str]]
    r"""The company ID the transaction belongs to"""
    owner_id: NotRequired[Nullable[str]]
    r"""ID of the user who owns/manages this project"""
    parent_project: NotRequired[Nullable[ParentProjectTypedDict]]
    r"""Parent project if this is a subproject"""
    currency: NotRequired[Nullable[Currency]]
    r"""Indicates the associated currency for an amount of money. Values correspond to [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)."""
    budget_amount: NotRequired[Nullable[float]]
    r"""Total budgeted amount for the project"""
    approved_amount: NotRequired[Nullable[float]]
    r"""Approved budget amount for the project"""
    budget_hours: NotRequired[Nullable[float]]
    r"""Total budgeted hours for the project"""
    hourly_rate: NotRequired[Nullable[float]]
    r"""Default hourly rate for project work"""
    billing_method: NotRequired[Nullable[BillingMethod]]
    r"""Method used for billing this project"""
    is_billable: NotRequired[Nullable[bool]]
    r"""Indicates if the project is billable to the customer"""
    phase: NotRequired[Nullable[ProjectPhase]]
    r"""Current phase of the project lifecycle"""
    tax_rate: NotRequired[LinkedTaxRateInputTypedDict]
    tracking_categories: NotRequired[
        Nullable[List[Nullable[LinkedTrackingCategoryTypedDict]]]
    ]
    r"""A list of linked tracking categories."""
    tags: NotRequired[List[str]]
    r"""Tags associated with the project"""
    notes: NotRequired[Nullable[str]]
    r"""Additional notes about the project"""
    contract_number: NotRequired[Nullable[str]]
    r"""Contract or agreement number associated with the project"""
    profit_margin: NotRequired[Nullable[float]]
    r"""Expected profit margin percentage for the project"""
    schedule_status: NotRequired[Nullable[ScheduleStatus]]
    r"""Current status of project schedule compared to plan"""
    addresses: NotRequired[List[AddressTypedDict]]
    r"""An array of addresses associated with the project (billing, job site, etc.)"""
    team_size: NotRequired[Nullable[int]]
    r"""Number of team members assigned to the project"""
    custom_fields: NotRequired[List[CustomFieldTypedDict]]
    row_version: NotRequired[Nullable[str]]
    r"""A binary value used to detect updates to a object and prevent data conflicts. It is incremented each time an update is made to the object."""


class ProjectInput(BaseModel):
    name: str
    r"""Name of the project"""

    display_id: OptionalNullable[str] = UNSET
    r"""User-friendly project identifier"""

    reference_id: OptionalNullable[str] = UNSET
    r"""External reference identifier for the project"""

    description: OptionalNullable[str] = UNSET
    r"""Detailed description of the project"""

    status: OptionalNullable[ProjectProjectStatus] = UNSET
    r"""Current status of the project"""

    active: OptionalNullable[bool] = UNSET
    r"""Indicates whether the project is currently active or inactive"""

    project_type: OptionalNullable[ProjectType] = UNSET
    r"""Type or category of the project"""

    priority: OptionalNullable[Priority] = UNSET
    r"""Priority level of the project"""

    completion_percentage: OptionalNullable[float] = UNSET
    r"""Percentage of project completion (0-100)"""

    start_date: OptionalNullable[date] = UNSET
    r"""Start date of the project"""

    end_date: OptionalNullable[date] = UNSET
    r"""Expected or actual end date of the project"""

    customer: OptionalNullable[LinkedCustomerInput] = UNSET
    r"""The customer this entity is linked to."""

    department: OptionalNullable[ProjectDepartment] = UNSET
    r"""Department or organizational unit associated with the project"""

    company_id: OptionalNullable[str] = UNSET
    r"""The company ID the transaction belongs to"""

    owner_id: OptionalNullable[str] = UNSET
    r"""ID of the user who owns/manages this project"""

    parent_project: OptionalNullable[ParentProject] = UNSET
    r"""Parent project if this is a subproject"""

    currency: OptionalNullable[Currency] = UNSET
    r"""Indicates the associated currency for an amount of money. Values correspond to [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)."""

    budget_amount: OptionalNullable[float] = UNSET
    r"""Total budgeted amount for the project"""

    approved_amount: OptionalNullable[float] = UNSET
    r"""Approved budget amount for the project"""

    budget_hours: OptionalNullable[float] = UNSET
    r"""Total budgeted hours for the project"""

    hourly_rate: OptionalNullable[float] = UNSET
    r"""Default hourly rate for project work"""

    billing_method: OptionalNullable[BillingMethod] = UNSET
    r"""Method used for billing this project"""

    is_billable: OptionalNullable[bool] = True
    r"""Indicates if the project is billable to the customer"""

    phase: OptionalNullable[ProjectPhase] = UNSET
    r"""Current phase of the project lifecycle"""

    tax_rate: Optional[LinkedTaxRateInput] = None

    tracking_categories: OptionalNullable[List[Nullable[LinkedTrackingCategory]]] = (
        UNSET
    )
    r"""A list of linked tracking categories."""

    tags: Optional[List[str]] = None
    r"""Tags associated with the project"""

    notes: OptionalNullable[str] = UNSET
    r"""Additional notes about the project"""

    contract_number: OptionalNullable[str] = UNSET
    r"""Contract or agreement number associated with the project"""

    profit_margin: OptionalNullable[float] = UNSET
    r"""Expected profit margin percentage for the project"""

    schedule_status: OptionalNullable[ScheduleStatus] = UNSET
    r"""Current status of project schedule compared to plan"""

    addresses: Optional[List[Address]] = None
    r"""An array of addresses associated with the project (billing, job site, etc.)"""

    team_size: OptionalNullable[int] = UNSET
    r"""Number of team members assigned to the project"""

    custom_fields: Optional[List[CustomField]] = None

    row_version: OptionalNullable[str] = UNSET
    r"""A binary value used to detect updates to a object and prevent data conflicts. It is incremented each time an update is made to the object."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "display_id",
            "reference_id",
            "description",
            "status",
            "active",
            "project_type",
            "priority",
            "completion_percentage",
            "start_date",
            "end_date",
            "customer",
            "department",
            "company_id",
            "owner_id",
            "parent_project",
            "currency",
            "budget_amount",
            "approved_amount",
            "budget_hours",
            "hourly_rate",
            "billing_method",
            "is_billable",
            "phase",
            "tax_rate",
            "tracking_categories",
            "tags",
            "notes",
            "contract_number",
            "profit_margin",
            "schedule_status",
            "addresses",
            "team_size",
            "custom_fields",
            "row_version",
        ]
        nullable_fields = [
            "display_id",
            "reference_id",
            "description",
            "status",
            "active",
            "project_type",
            "priority",
            "completion_percentage",
            "start_date",
            "end_date",
            "customer",
            "department",
            "company_id",
            "owner_id",
            "parent_project",
            "currency",
            "budget_amount",
            "approved_amount",
            "budget_hours",
            "hourly_rate",
            "billing_method",
            "is_billable",
            "phase",
            "tracking_categories",
            "notes",
            "contract_number",
            "profit_margin",
            "schedule_status",
            "team_size",
            "row_version",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m
