nordlet 0.5.5

Official Rust SDK for the Nordlet Accounting API
use crate::api::*;
use crate::{ApiError, ClientConfig, HttpClient, RequestOptions};
use reqwest::Method;

pub struct ProjectsClient {
    pub http_client: HttpClient,
}

impl ProjectsClient {
    pub fn new(config: ClientConfig) -> Result<Self, ApiError> {
        Ok(Self {
            http_client: HttpClient::new(config.clone())?,
        })
    }

    /// Create a project; `partnerId` is the customer that `projects/time-entries/bill` invoices by default. A duplicate `code` is refused with 409.
    ///
    /// # Arguments
    ///
    /// * `options` - Additional request options such as headers, timeout, etc.
    ///
    /// # Returns
    ///
    /// JSON response from the API
    pub async fn create(
        &self,
        request: &CreateProjectsRequest,
        options: Option<RequestOptions>,
    ) -> Result<CreateProjectsResponse, ApiError> {
        self.http_client
            .execute_request(
                Method::POST,
                "v1/projects/create",
                Some(serde_json::to_value(request).map_err(ApiError::Serialization)?),
                None,
                options,
            )
            .await
    }

    /// Change a project's name, customer, `status` (`active`, `completed`, `archived`) or notes; only the fields sent are changed. An archived project accepts no new time entries.
    ///
    /// # Arguments
    ///
    /// * `options` - Additional request options such as headers, timeout, etc.
    ///
    /// # Returns
    ///
    /// JSON response from the API
    pub async fn update(
        &self,
        request: &UpdateProjectsRequest,
        options: Option<RequestOptions>,
    ) -> Result<UpdateProjectsResponse, ApiError> {
        self.http_client
            .execute_request(
                Method::POST,
                "v1/projects/update",
                Some(serde_json::to_value(request).map_err(ApiError::Serialization)?),
                None,
                options,
            )
            .await
    }

    /// Return one project.
    ///
    /// # Arguments
    ///
    /// * `options` - Additional request options such as headers, timeout, etc.
    ///
    /// # Returns
    ///
    /// JSON response from the API
    pub async fn get(
        &self,
        request: &GetProjectsRequest,
        options: Option<RequestOptions>,
    ) -> Result<GetProjectsResponse, ApiError> {
        self.http_client
            .execute_request(
                Method::POST,
                "v1/projects/get",
                Some(serde_json::to_value(request).map_err(ApiError::Serialization)?),
                None,
                options,
            )
            .await
    }

    /// List projects. Filterable by `code`, `name`, `status` and `partnerId`; sortable by `code`, `name` and `createdAt`.
    ///
    /// # Arguments
    ///
    /// * `options` - Additional request options such as headers, timeout, etc.
    ///
    /// # Returns
    ///
    /// JSON response from the API
    pub async fn list(
        &self,
        request: &ListProjectsRequest,
        options: Option<RequestOptions>,
    ) -> Result<ListProjectsResponse, ApiError> {
        self.http_client
            .execute_request(
                Method::POST,
                "v1/projects/list",
                Some(serde_json::to_value(request).map_err(ApiError::Serialization)?),
                None,
                options,
            )
            .await
    }

    /// Record hours worked on a project on a date, optionally for an employee and with the `hourlyRate` used when billing. `hours` must be positive (422); an archived project is refused with 409.
    ///
    /// # Arguments
    ///
    /// * `options` - Additional request options such as headers, timeout, etc.
    ///
    /// # Returns
    ///
    /// JSON response from the API
    pub async fn time_entries_create(
        &self,
        request: &TimeEntriesCreateProjectsRequest,
        options: Option<RequestOptions>,
    ) -> Result<TimeEntriesCreateProjectsResponse, ApiError> {
        self.http_client
            .execute_request(
                Method::POST,
                "v1/projects/time-entries/create",
                Some(serde_json::to_value(request).map_err(ApiError::Serialization)?),
                None,
                options,
            )
            .await
    }

    /// Change a time entry; only the fields sent are changed. `hours` must be positive (422); an entry already billed to an invoice cannot be changed (409).
    ///
    /// # Arguments
    ///
    /// * `options` - Additional request options such as headers, timeout, etc.
    ///
    /// # Returns
    ///
    /// JSON response from the API
    pub async fn time_entries_update(
        &self,
        request: &TimeEntriesUpdateProjectsRequest,
        options: Option<RequestOptions>,
    ) -> Result<TimeEntriesUpdateProjectsResponse, ApiError> {
        self.http_client
            .execute_request(
                Method::POST,
                "v1/projects/time-entries/update",
                Some(serde_json::to_value(request).map_err(ApiError::Serialization)?),
                None,
                options,
            )
            .await
    }

    /// Delete a time entry (409 once it is billed).
    ///
    /// # Arguments
    ///
    /// * `options` - Additional request options such as headers, timeout, etc.
    ///
    /// # Returns
    ///
    /// JSON response from the API
    pub async fn time_entries_delete(
        &self,
        request: &TimeEntriesDeleteProjectsRequest,
        options: Option<RequestOptions>,
    ) -> Result<TimeEntriesDeleteProjectsResponse, ApiError> {
        self.http_client
            .execute_request(
                Method::POST,
                "v1/projects/time-entries/delete",
                Some(serde_json::to_value(request).map_err(ApiError::Serialization)?),
                None,
                options,
            )
            .await
    }

    /// List time entries. Filterable by `projectId`, `employeeId`, `billable`, `billedInvoiceId` and `date`; sortable by `date`, `createdAt` and `hours`.
    ///
    /// # Arguments
    ///
    /// * `options` - Additional request options such as headers, timeout, etc.
    ///
    /// # Returns
    ///
    /// JSON response from the API
    pub async fn time_entries_list(
        &self,
        request: &TimeEntriesListProjectsRequest,
        options: Option<RequestOptions>,
    ) -> Result<TimeEntriesListProjectsResponse, ApiError> {
        self.http_client
            .execute_request(
                Method::POST,
                "v1/projects/time-entries/list",
                Some(serde_json::to_value(request).map_err(ApiError::Serialization)?),
                None,
                options,
            )
            .await
    }

    /// Create a draft sale invoice from the project's unbilled billable time entries, optionally limited to `dateFrom` and `dateTo`, and mark them billed; needs the `sales:write` scope, and the invoice is issued with `sales/invoices/issue`. The customer is `partnerId`, else the project's partner (422 without either); each entry is priced at its own `hourlyRate`, else the call's `hourlyRate` (422 when an entry has neither); `groupBy` `rate` makes one line per rate with the summed hours, `entry` one line per entry; `itemId`, `vatRatePercent` and `vatClassifierCode` go onto every line. No matching entries is 422.
    ///
    /// # Arguments
    ///
    /// * `options` - Additional request options such as headers, timeout, etc.
    ///
    /// # Returns
    ///
    /// JSON response from the API
    pub async fn time_entries_bill(
        &self,
        request: &TimeEntriesBillProjectsRequest,
        options: Option<RequestOptions>,
    ) -> Result<TimeEntriesBillProjectsResponse, ApiError> {
        self.http_client
            .execute_request(
                Method::POST,
                "v1/projects/time-entries/bill",
                Some(serde_json::to_value(request).map_err(ApiError::Serialization)?),
                None,
                options,
            )
            .await
    }

    /// Profitability per project: `revenue` and `costs` from posted journal entries tagged with the project (income accounts credit less debit, expense accounts debit less credit), `profit` as their difference, and the hours from time entries (total, billable, billed, unbilled, and the unbilled amount at the entries' hourly rates). `projectId` limits the report to one project; `dateFrom` and `dateTo` limit the journal dates and the entry dates. Nothing is changed.
    ///
    /// # Arguments
    ///
    /// * `options` - Additional request options such as headers, timeout, etc.
    ///
    /// # Returns
    ///
    /// JSON response from the API
    pub async fn report(
        &self,
        request: &ReportProjectsRequest,
        options: Option<RequestOptions>,
    ) -> Result<ReportProjectsResponse, ApiError> {
        self.http_client
            .execute_request(
                Method::POST,
                "v1/projects/report",
                Some(serde_json::to_value(request).map_err(ApiError::Serialization)?),
                None,
                options,
            )
            .await
    }
}