# coding: utf-8 """ easybill REST API The first version of the easybill REST API. [CHANGELOG](https://api.easybill.de/rest/v1/CHANGELOG.md) ## Authentication You can choose between two available methods: `Basic Auth` or `Bearer Token`. In each HTTP request, one of the following HTTP headers is required: ``` # Basic Auth Authorization: Basic base64_encode(':') # Bearer Token Authorization: Bearer ``` ## Limitations ### Request Limit * PLUS: 10 requests per minute * BUSINESS: 60 requests per minute If the limit is exceeded, you will receive the HTTP error: `429 Too Many Requests` ### Result Limit All result lists are limited to 100 by default. This limit can be increased by the query parameter `limit` to a maximum of 1000. ## Query filter Many list resources can be filtered. In `/documents` you can filter e.g. by number with `/documents?number=111028654`. If you want to filter multiple numbers, you can either enter them separated by commas `/documents?number=111028654,222006895` or as an array `/documents?number[]=111028654&number[]=222006895`. **Warning**: The maximum size of an HTTP request line in bytes is 4094. If this limit is exceeded, you will receive the HTTP error: `414 Request-URI Too Large` ### Escape commas in query You can escape commans in query `name=Patrick\\, Peter` if you submit the header `X-Easybill-Escape: true` in your request. ## Property login_id This is the login of your admin or employee account. ## Date and Date-Time format Please use the timezone `Europe/Berlin`. * **date** = *Y-m-d* = `2016-12-31` * **date-time** = *Y-m-d H:i:s* = `2016-12-31 03:13:37` Date or datetime can be `null` because the attributes have been added later and the entry is older. The version of the OpenAPI document: 1.96.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. """ # noqa: E501 from __future__ import annotations import pprint import re # noqa: F401 import json from datetime import date, datetime from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr, field_validator from typing import Any, ClassVar, Dict, List, Optional, Union from easybill_generated_sync.models.advanced_data_field import AdvancedDataField from easybill_generated_sync.models.customer_snapshot import CustomerSnapshot from easybill_generated_sync.models.document_address import DocumentAddress from easybill_generated_sync.models.document_position import DocumentPosition from easybill_generated_sync.models.document_recurring import DocumentRecurring from easybill_generated_sync.models.file_format_config import FileFormatConfig from easybill_generated_sync.models.service_date import ServiceDate from typing import Optional, Set from typing_extensions import Self from pydantic_core import to_jsonable_python class Document(BaseModel): """ Document """ # noqa: E501 address: Optional[DocumentAddress] = None advanced_data_fields: Optional[List[AdvancedDataField]] = Field(default=None, description="EN16931 Business Terms (BT fields) for structured invoice data. On update the submitted list fully replaces the existing fields — send an empty array to clear all.") attachment_ids: Optional[List[StrictInt]] = None label_address: Optional[DocumentAddress] = None amount: Optional[StrictInt] = Field(default=None, description="Amount in cents (e.g. \"150\" = 1.50€)") amount_net: Optional[StrictInt] = Field(default=None, description="Amount in cents (e.g. \"150\" = 1.50€)") anonymize_due_date: Optional[date] = Field(default=None, description="A date which signals when to anonymize the document. Must be in the future. Turns into a read only field if the document is anonymized") anonymize_status: Optional[StrictStr] = Field(default='NOT_ANONYMIZED', description="This field signals if the document was anonymized") anonymized_at: Optional[StrictStr] = None bank_debit_form: Optional[StrictStr] = 'null' billing_country: Optional[StrictStr] = None calc_vat_from: Optional[StrictInt] = Field(default=None, description="0 === Net, 1 === Gross.") cancel_id: Optional[StrictInt] = Field(default=None, description="ID from the cancel document. Only for document type INVOICE.") cash_allowance: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Cash allowance percentage. If not provided, inherits from customer when available.") cash_allowance_days: Optional[StrictInt] = Field(default=None, description="Days for cash allowance. If not provided, inherits from customer when available.") cash_allowance_text: Optional[StrictStr] = 'null' contact_id: Optional[StrictInt] = None contact_label: Optional[StrictStr] = '' contact_text: Optional[StrictStr] = '' created_at: Optional[datetime] = None currency: Optional[StrictStr] = 'EUR' customer_id: Optional[StrictInt] = None customer_snapshot: Optional[CustomerSnapshot] = None discount: Optional[StrictStr] = 'null' discount_type: Optional[StrictStr] = null document_date: Optional[date] = None due_date: Optional[date] = Field(default=None, description="To change the value use grace_period.") edited_at: Optional[datetime] = None external_id: Optional[StrictStr] = 'null' replica_url: Optional[StrictStr] = 'null' grace_period: Optional[StrictInt] = Field(default=None, description="will be replaced by its alias due_in_days.") due_in_days: Optional[StrictInt] = Field(default=None, description="due date in days. If not provided, inherits from customer when available") id: Optional[StrictInt] = None is_acceptable_on_public_domain: Optional[StrictBool] = Field(default=False, description="Indicates if a document can be accepted by the end customer through the document's public access page.") is_archive: Optional[StrictBool] = False is_draft: Optional[StrictBool] = Field(default=None, description="This property is read only. To finish the document call /documents/{id}/done.") is_replica: Optional[StrictBool] = Field(default=False, description="Marks a document as a replica from another software.") is_oss: Optional[StrictBool] = Field(default=False, description="Indicates if a document is a one-stop-shop document") item_notes: Optional[List[StrictStr]] = Field(default=None, description="Field holds all unique document_note of items for the document") items: Optional[List[DocumentPosition]] = None last_postbox_id: Optional[StrictInt] = None login_id: Optional[StrictInt] = Field(default=None, description="If omitted or null, the currently active login is used.") number: Optional[StrictStr] = 'null' order_number: Optional[StrictStr] = '' buyer_reference: Optional[StrictStr] = '' paid_amount: Optional[StrictInt] = None paid_at: Optional[date] = None pdf_pages: Optional[StrictInt] = None pdf_template: Optional[StrictStr] = Field(default=None, description="Default template is null or 'DE', default english is 'EN' and for all others use the numeric template ID.") payment_link_enabled: Optional[StrictBool] = Field(default=False, description="Whether the payment link is shown on this document. Overrides the setting from the referenced template.") payment_link_locale: Optional[StrictStr] = Field(default='de', description="Language of the payment link text on the document.") project_id: Optional[StrictInt] = None recurring_options: Optional[DocumentRecurring] = None ref_id: Optional[StrictInt] = Field(default=None, description="Reference document id") root_id: Optional[StrictInt] = Field(default=None, description="Root document id") service_date: Optional[ServiceDate] = None shipping_country: Optional[StrictStr] = 'null' status: Optional[StrictStr] = Field(default=null, description="This value can only be used in document type DELIVERY, ORDER, CHARGE or OFFER. NULL is default = not set.") text: Optional[StrictStr] = None text_prefix: Optional[StrictStr] = None text_tax: Optional[StrictStr] = Field(default='null', description="Overwrites the default vat-option text from the document layout. It is only displayed in documents with the type other than: Delivery, Dunning, Reminder or Letter and a different vat-option than null") title: Optional[StrictStr] = 'null' type: Optional[StrictStr] = Field(default='INVOICE', description="Can only set on create.") use_shipping_address: Optional[StrictBool] = Field(default=False, description="If true and customer has shipping address then it will be used.") vat_country: Optional[StrictStr] = 'null' vat_id: Optional[StrictStr] = '' fulfillment_country: Optional[StrictStr] = 'null' vat_option: Optional[StrictStr] = Field(default=null, description="NULL: Normal steuerbar
nStb: Nicht steuerbar (Drittland)
nStbUstID: Nicht steuerbar (EU mit USt-IdNr.)
nStbNoneUstID: Nicht steuerbar (EU ohne USt-IdNr.)
nStbIm: Nicht steuerbarer Innenumsatz
revc: Steuerschuldwechsel §13b (Inland)
IG: Innergemeinschaftliche Lieferung
AL: Ausfuhrlieferung
sStfr: sonstige Steuerbefreiung
smallBusiness: Kleinunternehmen (Keine MwSt.)") file_format_config: Optional[List[FileFormatConfig]] = None __properties: ClassVar[List[str]] = ["address", "advanced_data_fields", "attachment_ids", "label_address", "amount", "amount_net", "anonymize_due_date", "anonymize_status", "anonymized_at", "bank_debit_form", "billing_country", "calc_vat_from", "cancel_id", "cash_allowance", "cash_allowance_days", "cash_allowance_text", "contact_id", "contact_label", "contact_text", "created_at", "currency", "customer_id", "customer_snapshot", "discount", "discount_type", "document_date", "due_date", "edited_at", "external_id", "replica_url", "grace_period", "due_in_days", "id", "is_acceptable_on_public_domain", "is_archive", "is_draft", "is_replica", "is_oss", "item_notes", "items", "last_postbox_id", "login_id", "number", "order_number", "buyer_reference", "paid_amount", "paid_at", "pdf_pages", "pdf_template", "payment_link_enabled", "payment_link_locale", "project_id", "recurring_options", "ref_id", "root_id", "service_date", "shipping_country", "status", "text", "text_prefix", "text_tax", "title", "type", "use_shipping_address", "vat_country", "vat_id", "fulfillment_country", "vat_option", "file_format_config"] @field_validator('anonymize_status') def anonymize_status_validate_enum(cls, value): """Validates the enum""" if value is None: return value if value not in set(['NOT_ANONYMIZED', 'ANONYMIZED']): raise ValueError("must be one of enum values ('NOT_ANONYMIZED', 'ANONYMIZED')") return value @field_validator('discount_type') def discount_type_validate_enum(cls, value): """Validates the enum""" if value is None: return value if value not in set(['PERCENT', 'AMOUNT']): raise ValueError("must be one of enum values ('PERCENT', 'AMOUNT')") return value @field_validator('payment_link_locale') def payment_link_locale_validate_enum(cls, value): """Validates the enum""" if value is None: return value if value not in set(['de', 'en']): raise ValueError("must be one of enum values ('de', 'en')") return value @field_validator('status') def status_validate_enum(cls, value): """Validates the enum""" if value is None: return value if value not in set(['ACCEPT', 'DONE', 'DROPSHIPPING', 'CANCEL']): raise ValueError("must be one of enum values ('ACCEPT', 'DONE', 'DROPSHIPPING', 'CANCEL')") return value @field_validator('type') def type_validate_enum(cls, value): """Validates the enum""" if value is None: return value if value not in set(['INVOICE', 'RECURRING', 'CREDIT', 'OFFER', 'REMINDER', 'DUNNING', 'STORNO', 'STORNO_CREDIT', 'DELIVERY', 'PDF', 'CHARGE', 'CHARGE_CONFIRM', 'LETTER', 'ORDER', 'PROFORMA_INVOICE', 'STORNO_PROFORMA_INVOICE']): raise ValueError("must be one of enum values ('INVOICE', 'RECURRING', 'CREDIT', 'OFFER', 'REMINDER', 'DUNNING', 'STORNO', 'STORNO_CREDIT', 'DELIVERY', 'PDF', 'CHARGE', 'CHARGE_CONFIRM', 'LETTER', 'ORDER', 'PROFORMA_INVOICE', 'STORNO_PROFORMA_INVOICE')") return value @field_validator('vat_option') def vat_option_validate_enum(cls, value): """Validates the enum""" if value is None: return value if value not in set(['NULL', 'nStb', 'nStbUstID', 'nStbNoneUstID', 'nStbIm', 'revc', 'IG', 'AL', 'sStfr', 'smallBusiness']): raise ValueError("must be one of enum values ('NULL', 'nStb', 'nStbUstID', 'nStbNoneUstID', 'nStbIm', 'revc', 'IG', 'AL', 'sStfr', 'smallBusiness')") return value model_config = ConfigDict( validate_by_name=True, validate_by_alias=True, validate_assignment=True, protected_namespaces=(), ) def to_str(self) -> str: """Returns the string representation of the model using alias""" return pprint.pformat(self.model_dump(by_alias=True)) def to_json(self) -> str: """Returns the JSON representation of the model using alias""" return json.dumps(to_jsonable_python(self.to_dict())) @classmethod def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of Document from a JSON string""" return cls.from_dict(json.loads(json_str)) def to_dict(self) -> Dict[str, Any]: """Return the dictionary representation of the model using alias. This has the following differences from calling pydantic's `self.model_dump(by_alias=True)`: * `None` is only added to the output dict for nullable fields that were set at model initialization. Other fields with value `None` are ignored. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. * OpenAPI `readOnly` fields are excluded. """ excluded_fields: Set[str] = set([ "attachment_ids", "amount", "amount_net", "anonymize_status", "anonymized_at", "billing_country", "cancel_id", "created_at", "due_date", "edited_at", "id", "is_draft", "item_notes", "last_postbox_id", "paid_amount", "paid_at", "pdf_pages", "root_id", "vat_id", ]) _dict = self.model_dump( by_alias=True, exclude=excluded_fields, exclude_none=True, ) # override the default output from pydantic by calling `to_dict()` of address if self.address: _dict['address'] = self.address.to_dict() # override the default output from pydantic by calling `to_dict()` of each item in advanced_data_fields (list) _items = [] if self.advanced_data_fields: for _item_advanced_data_fields in self.advanced_data_fields: if _item_advanced_data_fields: _items.append(_item_advanced_data_fields.to_dict()) _dict['advanced_data_fields'] = _items # override the default output from pydantic by calling `to_dict()` of label_address if self.label_address: _dict['label_address'] = self.label_address.to_dict() # override the default output from pydantic by calling `to_dict()` of customer_snapshot if self.customer_snapshot: _dict['customer_snapshot'] = self.customer_snapshot.to_dict() # override the default output from pydantic by calling `to_dict()` of each item in items (list) _items = [] if self.items: for _item_items in self.items: if _item_items: _items.append(_item_items.to_dict()) _dict['items'] = _items # override the default output from pydantic by calling `to_dict()` of recurring_options if self.recurring_options: _dict['recurring_options'] = self.recurring_options.to_dict() # override the default output from pydantic by calling `to_dict()` of service_date if self.service_date: _dict['service_date'] = self.service_date.to_dict() # override the default output from pydantic by calling `to_dict()` of each item in file_format_config (list) _items = [] if self.file_format_config: for _item_file_format_config in self.file_format_config: if _item_file_format_config: _items.append(_item_file_format_config.to_dict()) _dict['file_format_config'] = _items # set to None if anonymize_due_date (nullable) is None # and model_fields_set contains the field if self.anonymize_due_date is None and "anonymize_due_date" in self.model_fields_set: _dict['anonymize_due_date'] = None # set to None if anonymized_at (nullable) is None # and model_fields_set contains the field if self.anonymized_at is None and "anonymized_at" in self.model_fields_set: _dict['anonymized_at'] = None # set to None if bank_debit_form (nullable) is None # and model_fields_set contains the field if self.bank_debit_form is None and "bank_debit_form" in self.model_fields_set: _dict['bank_debit_form'] = None # set to None if cash_allowance (nullable) is None # and model_fields_set contains the field if self.cash_allowance is None and "cash_allowance" in self.model_fields_set: _dict['cash_allowance'] = None # set to None if cash_allowance_days (nullable) is None # and model_fields_set contains the field if self.cash_allowance_days is None and "cash_allowance_days" in self.model_fields_set: _dict['cash_allowance_days'] = None # set to None if cash_allowance_text (nullable) is None # and model_fields_set contains the field if self.cash_allowance_text is None and "cash_allowance_text" in self.model_fields_set: _dict['cash_allowance_text'] = None # set to None if contact_id (nullable) is None # and model_fields_set contains the field if self.contact_id is None and "contact_id" in self.model_fields_set: _dict['contact_id'] = None # set to None if customer_id (nullable) is None # and model_fields_set contains the field if self.customer_id is None and "customer_id" in self.model_fields_set: _dict['customer_id'] = None # set to None if discount (nullable) is None # and model_fields_set contains the field if self.discount is None and "discount" in self.model_fields_set: _dict['discount'] = None # set to None if discount_type (nullable) is None # and model_fields_set contains the field if self.discount_type is None and "discount_type" in self.model_fields_set: _dict['discount_type'] = None # set to None if external_id (nullable) is None # and model_fields_set contains the field if self.external_id is None and "external_id" in self.model_fields_set: _dict['external_id'] = None # set to None if replica_url (nullable) is None # and model_fields_set contains the field if self.replica_url is None and "replica_url" in self.model_fields_set: _dict['replica_url'] = None # set to None if grace_period (nullable) is None # and model_fields_set contains the field if self.grace_period is None and "grace_period" in self.model_fields_set: _dict['grace_period'] = None # set to None if due_in_days (nullable) is None # and model_fields_set contains the field if self.due_in_days is None and "due_in_days" in self.model_fields_set: _dict['due_in_days'] = None # set to None if number (nullable) is None # and model_fields_set contains the field if self.number is None and "number" in self.model_fields_set: _dict['number'] = None # set to None if project_id (nullable) is None # and model_fields_set contains the field if self.project_id is None and "project_id" in self.model_fields_set: _dict['project_id'] = None # set to None if ref_id (nullable) is None # and model_fields_set contains the field if self.ref_id is None and "ref_id" in self.model_fields_set: _dict['ref_id'] = None # set to None if root_id (nullable) is None # and model_fields_set contains the field if self.root_id is None and "root_id" in self.model_fields_set: _dict['root_id'] = None # set to None if shipping_country (nullable) is None # and model_fields_set contains the field if self.shipping_country is None and "shipping_country" in self.model_fields_set: _dict['shipping_country'] = None # set to None if status (nullable) is None # and model_fields_set contains the field if self.status is None and "status" in self.model_fields_set: _dict['status'] = None # set to None if text_tax (nullable) is None # and model_fields_set contains the field if self.text_tax is None and "text_tax" in self.model_fields_set: _dict['text_tax'] = None # set to None if title (nullable) is None # and model_fields_set contains the field if self.title is None and "title" in self.model_fields_set: _dict['title'] = None # set to None if vat_country (nullable) is None # and model_fields_set contains the field if self.vat_country is None and "vat_country" in self.model_fields_set: _dict['vat_country'] = None # set to None if fulfillment_country (nullable) is None # and model_fields_set contains the field if self.fulfillment_country is None and "fulfillment_country" in self.model_fields_set: _dict['fulfillment_country'] = None # set to None if vat_option (nullable) is None # and model_fields_set contains the field if self.vat_option is None and "vat_option" in self.model_fields_set: _dict['vat_option'] = None return _dict @classmethod def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: """Create an instance of Document from a dict""" if obj is None: return None if not isinstance(obj, dict): return cls.model_validate(obj) _obj = cls.model_validate({ "address": DocumentAddress.from_dict(obj["address"]) if obj.get("address") is not None else None, "advanced_data_fields": [AdvancedDataField.from_dict(_item) for _item in obj["advanced_data_fields"]] if obj.get("advanced_data_fields") is not None else None, "attachment_ids": obj.get("attachment_ids"), "label_address": DocumentAddress.from_dict(obj["label_address"]) if obj.get("label_address") is not None else None, "amount": obj.get("amount"), "amount_net": obj.get("amount_net"), "anonymize_due_date": obj.get("anonymize_due_date"), "anonymize_status": obj.get("anonymize_status") if obj.get("anonymize_status") is not None else 'NOT_ANONYMIZED', "anonymized_at": obj.get("anonymized_at"), "bank_debit_form": obj.get("bank_debit_form") if obj.get("bank_debit_form") is not None else 'null', "billing_country": obj.get("billing_country"), "calc_vat_from": obj.get("calc_vat_from"), "cancel_id": obj.get("cancel_id"), "cash_allowance": obj.get("cash_allowance"), "cash_allowance_days": obj.get("cash_allowance_days"), "cash_allowance_text": obj.get("cash_allowance_text") if obj.get("cash_allowance_text") is not None else 'null', "contact_id": obj.get("contact_id"), "contact_label": obj.get("contact_label") if obj.get("contact_label") is not None else '', "contact_text": obj.get("contact_text") if obj.get("contact_text") is not None else '', "created_at": obj.get("created_at"), "currency": obj.get("currency") if obj.get("currency") is not None else 'EUR', "customer_id": obj.get("customer_id"), "customer_snapshot": CustomerSnapshot.from_dict(obj["customer_snapshot"]) if obj.get("customer_snapshot") is not None else None, "discount": obj.get("discount") if obj.get("discount") is not None else 'null', "discount_type": obj.get("discount_type") if obj.get("discount_type") is not None else null, "document_date": obj.get("document_date"), "due_date": obj.get("due_date"), "edited_at": obj.get("edited_at"), "external_id": obj.get("external_id") if obj.get("external_id") is not None else 'null', "replica_url": obj.get("replica_url") if obj.get("replica_url") is not None else 'null', "grace_period": obj.get("grace_period"), "due_in_days": obj.get("due_in_days"), "id": obj.get("id"), "is_acceptable_on_public_domain": obj.get("is_acceptable_on_public_domain") if obj.get("is_acceptable_on_public_domain") is not None else False, "is_archive": obj.get("is_archive") if obj.get("is_archive") is not None else False, "is_draft": obj.get("is_draft"), "is_replica": obj.get("is_replica") if obj.get("is_replica") is not None else False, "is_oss": obj.get("is_oss") if obj.get("is_oss") is not None else False, "item_notes": obj.get("item_notes"), "items": [DocumentPosition.from_dict(_item) for _item in obj["items"]] if obj.get("items") is not None else None, "last_postbox_id": obj.get("last_postbox_id"), "login_id": obj.get("login_id"), "number": obj.get("number") if obj.get("number") is not None else 'null', "order_number": obj.get("order_number") if obj.get("order_number") is not None else '', "buyer_reference": obj.get("buyer_reference") if obj.get("buyer_reference") is not None else '', "paid_amount": obj.get("paid_amount"), "paid_at": obj.get("paid_at"), "pdf_pages": obj.get("pdf_pages"), "pdf_template": obj.get("pdf_template"), "payment_link_enabled": obj.get("payment_link_enabled") if obj.get("payment_link_enabled") is not None else False, "payment_link_locale": obj.get("payment_link_locale") if obj.get("payment_link_locale") is not None else 'de', "project_id": obj.get("project_id"), "recurring_options": DocumentRecurring.from_dict(obj["recurring_options"]) if obj.get("recurring_options") is not None else None, "ref_id": obj.get("ref_id"), "root_id": obj.get("root_id"), "service_date": ServiceDate.from_dict(obj["service_date"]) if obj.get("service_date") is not None else None, "shipping_country": obj.get("shipping_country") if obj.get("shipping_country") is not None else 'null', "status": obj.get("status") if obj.get("status") is not None else null, "text": obj.get("text"), "text_prefix": obj.get("text_prefix"), "text_tax": obj.get("text_tax") if obj.get("text_tax") is not None else 'null', "title": obj.get("title") if obj.get("title") is not None else 'null', "type": obj.get("type") if obj.get("type") is not None else 'INVOICE', "use_shipping_address": obj.get("use_shipping_address") if obj.get("use_shipping_address") is not None else False, "vat_country": obj.get("vat_country") if obj.get("vat_country") is not None else 'null', "vat_id": obj.get("vat_id") if obj.get("vat_id") is not None else '', "fulfillment_country": obj.get("fulfillment_country") if obj.get("fulfillment_country") is not None else 'null', "vat_option": obj.get("vat_option") if obj.get("vat_option") is not None else null, "file_format_config": [FileFormatConfig.from_dict(_item) for _item in obj["file_format_config"]] if obj.get("file_format_config") is not None else None }) return _obj