Creare factură

Descriere - Creare factură

  • Această secțiune este dedicată creării unei facturi noi

  • Această operațiune va returna identificatorul Keez al noii facturi externalId

  • Nu se poate crea sau modifica o factură fără articole, dacă nu există articolul pentru factură, acesta se creează înaintea facturii: Vezi Creare Articol

  • Facturile sunt de 2 tipuri:

    1. Facturi pentru persoane fizice

    2. Facturi pentru persoane juridice

    Diferența dintre facturile PF și PJ o face modul de completare a proprietății «partner» din modelul de request:

Operații care se pot realiza după ce o factură a fost creată:
  1. Vezi Modificare factură

  2. Vezi Ștergere factură

  3. Vezi Validare factură

  4. Vezi Trimite pe email

  5. Vezi Descărcare factură

Model de utilizare API - Creare factură

Notă

  • Verb: POST

  • Endpoint: /{clientEid}/invoices

  • Request parameter: {clientEid}

  • Request body: {data_body}

  • Returns: externalId

  • Type of return: String

Atenționare

  • A se observa parametrul {clientEid} și tipul acestuia (path variable)

  • A se observa parametrul {data_body} și tipul acestuia (request body)

Model de request body - Creare factură

  • Request body-ul se creează în prealabil, înaintea apelului către API

  • Acesta va conține informațiile specifice acelei facturi

  • Modelul acestui request body se regăsește în tabelul din Vezi Model factură

  • Informațiile obligatorii de completat pentru o factură sunt semnalizate în coloana «Coloană obligatorie» din modelul de mai sus

  • Formatul de date primit de fiecare parametrul în parte este specificat în coloana «Format» din modelul de mai sus

  • Model pentru facturi PF:

data_body = {
    'series': 'SERIE',
    'documentDate': 20190102,
    'dueDate': 20190102,
    'vatOnCollection': False,
    'currencyCode': 'EUR',
    'exchangeRate': 4.82,
    'originalNetAmount': 482,
    'originalNetAmountCurrency': 100,
    'originalVatAmount': 0,
    'originalVatAmountCurrency': 0,
    'netAmount': 482,
    'netAmountCurrency': 100,
    'vatAmount': 0,
    'vatAmountCurrency': 0,
    'grossAmount': 482,
    'grossAmountCurrency': 100,
    'paymentTypeId': 1,
    'partner': {
        'isLegalPerson': False,
        'identificationNumber': '1930912217543',
        'partnerName': 'Marian Ion',
        'countryCode': 'RO',
        'countryName': 'Romania',
        'countyCode': 'RO-B',
        'countyName': 'Bucuresti',
        'cityName': 'Sector 1',
        'addressDetails': 'Strada Maria Tanase nr. 1'
    },
    'invoiceDetails': [
        {
            'itemExternalId': '{ID_EXTERN_ARTICOL}',
            'measureUnitId': 1,
            'quantity': 1,
            'unitPrice': 100,
            'originalNetAmount': 482,
            'originalNetAmountCurrency': 100,
            'originalVatAmount': 0,
            'originalVatAmountCurrency': 0,
            'netAmount': 482,
            'netAmountCurrency': 100,
            'vatAmount': 0,
            'vatAmountCurrency': 0,
            'grossAmount': 482,
            'grossAmountCurrency': 100,
        }
    ]
}
  • Model pentru facturi PF:

data_body = {
    'series': 'SERIE',
    'number': 1,
    'documentDate': 20190102,
    'dueDate': 20190102,
    'vatOnCollection': False,
    'currencyCode': 'RON',
    'originalNetAmount': 100,
    'originalNetAmountCurrency': 100,
    'originalVatAmount': 0,
    'originalVatAmountCurrency': 0,
    'netAmount': 100,
    'netAmountCurrency': 100,
    'vatAmount': 0,
    'vatAmountCurrency': 0,
    'grossAmount': 100,
    'grossAmountCurrency': 100,
    'paymentTypeId': 1,
    'partner': {
        'isLegalPerson': true,
        'partnerName': 'CENTRUL MEDICAL UNIREA SRL',
        'registrationNumber': 'J40/15930/1991',
        'identificationNumber': '5919324',
        'taxAttribute': 'RO',
        'countryCode': 'RO',
        'countryName': 'Romania',
        'countyCode': 'RO-B',
        'countyName': 'BUCURESTI',
        'cityName': 'Sector 1',
        'addressDetails': 'PŢA. CHARLES DE GAULLE, NR.15, BL.CLADIREA CHARLES DE GAULLE PLAZA, ET.4 '
    },
    'invoiceDetails': [
        {
            'itemExternalId': '{ID_EXTERN_ARTICOL}',
            'measureUnitId': 1,
            'quantity': 1,
            'unitPrice': 100,
            'originalNetAmount': 100,
            'originalNetAmountCurrency': 100,
            'originalVatAmount': 0,
            'originalVatAmountCurrency': 0,
            'netAmount': 100,
            'netAmountCurrency': 100,
            'vatAmount': 0,
            'vatAmountCurrency': 0,
            'grossAmount': 100,
            'grossAmountCurrency': 120
        }
    ]
}

Notă

Dacă există deja o factură cu o anumită serie, nu mai trebuie completat numărul, acesta se va completa cu următorul disponibil Exemplu:

  • Dacă fac prima factură cu seria SRS atunci va trebui să completez proprietatea «number» cu numărul de început al acestei serii (nu trebuie să fie neapărat 1)

  • Dacă există deja o factură pe seria SRS atunci NU trebuie să pun proprietatea «number». Se va completa automat.

Validări - Creare factură

La momentul executării acestui apel se vor verifica și valida următoarele:

  • Dacă există factura

  • Toate proprietățile obligatorii trebuie să fie completate

  • Seria facturii nu permite spații

  • Se verifică dacă pentru seria facturii create există deja un număr generat

  • Data scadentă nu poate să fie mai mică decât data facturii

  • Dacă discount-ul este global atunci toate valorile de discount de pe articol trebuie să fie egale cu cele de pe factură

  • Dacă discount-ul este procentual atunci procentul de discount trebuie completat

  • Dacă discount-ul este valoric atunci procentul de discount nu trebuie să fie completat

  • Valoarea discount-ului pentru articol nu poate să fie mai mare decât valoarea netă a articolului

  • Procentul de discount pentru articol nu poate să fie mai mare de 100%

  • Dacă factura are articole care conțin accize atunci factura și articolul trebuie să conțină acest calcul

  • Este obligatoriu pentru persoanele fizice completarea adresei sau a CNP-ului

Verificările și validările vor arunca (throw) mesaje de eroare sub formă de excepție (Vezi Model Excepție) atașate de un cod HTTP error 500. Vezi Coduri eroare posibile

Mod de folosire - Wrapper - Creare factură

  • Dacă se folosește wrapper-ul scris în Python se utilizează astfel:
    1. Se preia token-ul Vezi Autorizarea

    2. Se apelează metoda specifică acestui request POST

    token_url = 'https://staging.keez.ro/idp/connect/token'
    api_url = f'https://{ENVIRONMENT}.keez.ro/api/v1.0/public-api'
    
    client_eid = '{RECEIVED_CLIENT_EID}'
    application_id = '{RECEIVED_APPLICATION_ID}'
    secret = '{RECEIVED_SECRET}'
    
    api = KeezPublicApi(app=application_id, secret=secret, token_url=token_url, api_url=api_url)
    
    data_body = {
        'series': 'SERIE',
        'documentDate': 20190102,
        'dueDate': 20190102,
        'vatOnCollection': False,
        'currencyCode': 'EUR',
        'exchangeRate': 4.82,
        'originalNetAmount': 482,
        'originalNetAmountCurrency': 100,
        'originalVatAmount': 0,
        'originalVatAmountCurrency': 0,
        'netAmount': 482,
        'netAmountCurrency': 100,
        'vatAmount': 0,
        'vatAmountCurrency': 0,
        'grossAmount': 482,
        'grossAmountCurrency': 100,
        'paymentTypeId': 1,
        'partner': {
            'isLegalPerson': False,
            'identificationNumber': '1930912217543',
            'partnerName': 'Marian Ion',
            'countryCode': 'RO',
            'countryName': 'Romania',
            'countyCode': 'RO-B',
            'countyName': 'Bucuresti',
            'cityName': 'Sector 1',
            'addressDetails': 'Strada Maria Tanase nr. 1'
        },
        'invoiceDetails': [
            {
                'itemExternalId': '{ID_EXTERN_ARTICOL}',
                'measureUnitId': 1,
                'quantity': 1,
                'unitPrice': 100,
                'originalNetAmount': 482,
                'originalNetAmountCurrency': 100,
                'originalVatAmount': 0,
                'originalVatAmountCurrency': 0,
                'netAmount': 482,
                'netAmountCurrency': 100,
                'vatAmount': 0,
                'vatAmountCurrency': 0,
                'grossAmount': 482,
                'grossAmountCurrency': 100,
            }
        ]
    }
    
    result = api.create_invoice(client_eid, data_body)
    

Mod de folosire - Fără Wrapper - Creare factură

class InvoiceService:
    def __init__(self):
        token = TokenService()
        self.auth_token = token.generate_token()
        self.token = f'{self.auth_token.get("token_type")} {self.auth_token.get("access_token")}'

        self.client_eid = token.client_eid
        self.api_endpoint = token.api_endpoint

    def createInvoice(self):
        invoice_url = f'{self.api_endpoint}/{self.client_eid}/invoices'

        data_body = {
            'series': 'SERIE',
            'documentDate': 20190102,
            'dueDate': 20190102,
            'vatOnCollection': False,
            'currencyCode': 'EUR',
            'exchangeRate': 4.82,
            'originalNetAmount': 482,
            'originalNetAmountCurrency': 100,
            'originalVatAmount': 0,
            'originalVatAmountCurrency': 0,
            'netAmount': 482,
            'netAmountCurrency': 100,
            'vatAmount': 0,
            'vatAmountCurrency': 0,
            'grossAmount': 482,
            'grossAmountCurrency': 100,
            'paymentTypeId': 1,
            'partner': {
                'isLegalPerson': False,
                'identificationNumber': '1930912217543',
                'partnerName': 'Marian Ion',
                'countryCode': 'RO',
                'countryName': 'Romania',
                'countyCode': 'RO-B',
                'countyName': 'Bucuresti',
                'cityName': 'Sector 1',
                'addressDetails': 'Strada Maria Tanase nr. 1'
            },
            'invoiceDetails': [
                {
                    'itemExternalId': '{ID_EXTERN_ARTICOL}',
                    'measureUnitId': 1,
                    'quantity': 1,
                    'unitPrice': 100,
                    'originalNetAmount': 482,
                    'originalNetAmountCurrency': 100,
                    'originalVatAmount': 0,
                    'originalVatAmountCurrency': 0,
                    'netAmount': 482,
                    'netAmountCurrency': 100,
                    'vatAmount': 0,
                    'vatAmountCurrency': 0,
                    'grossAmount': 482,
                    'grossAmountCurrency': 100,
                }
            ]
        }

        _req = requests.post(url=invoice_url, headers={'Content-Type': 'application/json', 'Authorization': self.token}, json=data_body)
        return _req.json()


if __name__ == '__main__':
    service = InvoiceService()
    invoice = service.createInvoice()
    print(invoice)

Notă

Clasa TokenService() se găsește la secțiunea Autorizarea: Vezi Autorizarea