Bookings (Boekingen) ==================== Current version: 1.1.0 Create ------ .. http:post:: /api2/boekingen Create a new booking **Example request**: .. sourcecode:: http POST /api2/boekingen HTTP/1.1 Host: demo.recras.nl Accept: application/json { "klant_id": 47, // (customer_id) "begin": "2014-01-01T15:00:00+01:00", // (start) "personen": 15, // (persons) "arrangement_id": 2, // (package_id) "arrangement": "Klimmen en barbecue" // (package: "Climbing and barbecue") } :json integer klant_id: **Required** The ``id`` of a customer (`klant_id` means customer_id) :json datetime begin: **Required** Start moment of the booking (`begin` means start) :json integer personen: **Required** The group size (`personen` means persons) :json string status: Default: *informatie* (information) The status of the booking (for possible statuses see :ref:`booking_status`) :json string arrangement: The name of the package (`arrangement`) as displayed to the customer :json integer boeking_id: The ``id`` of the booking this booking is based on. This cannot be sent in combination with the following fields: ``arrangement_id``, ``book_process_id``, ``product_id`` (`boeking_id` means booking_id) :json integer arrangement_id: The ``id`` of the package (`arrangement`) this booking is based on :json integer book_process_id: The ``id`` of the booking process this booking is based on :json integer product_id: The ``id`` of the product this booking is based on :json date status_vervaldatum: The date on which the option/reservation will expire (`status_vervaldatum` means status_expiry_date) :json string bijzonderheden: Particulars of this booking that are important for staff and suppliers (`bijzonderheden` means particulars) **Example response**: .. sourcecode:: http HTTP/1.1 201 Created Content-Type: application/json { "id": 34, "klant_id": 47, // (customer_id) "datum": "2014-01-01", // (date) "status": "informatie", // (status: "information") "arrangement": "Klimmen en barbecue", // (package: "Climbing and barbecue") "personen": 15, // (persons) "status_updated_at": "2014-10-29T10:53:15+01:00", // (status_updated_at) "arrangement_id": 2, // (package_id) "online_boeking": false, // (online_booking) "status_vervaldatum": null, // (status_expiry_date) "bijzonderheden": "", // (particulars) "conceptfactuur_na_dagen": null, // (draft_invoice_after_days) "referentie": "47-2", // (reference) "boekingsregels": [ // (booking_lines) { "id": 132, "locatie_id": 2, // (location_id) "aantal": 15, // (number/quantity) "begin": "2014-01-01T18:00:00+01:00", // (start) "eind": "2014-01-01T20:00:00+01:00", // (end) "minimum_aantal": 0, // (minimum_number) "beschrijving": "Genieten van onze heerlijke BBQ", // (description: "Enjoy our delicious BBQ") "opmerking": null, // (remark/note) "betaald_bedrag": null, // (paid_amount) "betaal_datum": null, // (payment_date) "betaal_opmerking": null, // (payment_remark) "herinnering_leverancier": null, // (supplier_reminder) "product_id": 5 }, { "id": 133, "locatie_id": 1, // (location_id) "aantal": 15, // (number/quantity) "begin": "2014-01-01T15:30:00+01:00", // (start) "eind": "2014-01-01T18:00:00+01:00", // (end) "minimum_aantal": 8, // (minimum_number) "beschrijving": "Met de hele groep, onder begeleiding, heerlijk klimmen.", // (description: "With the whole group, under supervision, enjoy climbing.") "opmerking": null, // (remark/note) "betaald_bedrag": null, // (paid_amount) "betaal_datum": null, // (payment_date) "betaal_opmerking": null, // (payment_remark) "herinnering_leverancier": null, // (supplier_reminder) "product_id": 6 }, { "id": 134, "locatie_id": 2, // (location_id) "aantal": 15, // (number/quantity) "begin": "2014-01-01T15:00:00+01:00", // (start) "eind": "2014-01-01T15:30:00+01:00", // (end) "minimum_aantal": 0, // (minimum_number) "beschrijving": "Ontvangst met koffie,thee op het Klimbos terras", // (description: "Reception with coffee, tea on the Klimbos (Climbing Forest) terrace") "opmerking": null, // (remark/note) "betaald_bedrag": null, // (paid_amount) "betaal_datum": null, // (payment_date) "betaal_opmerking": null, // (payment_remark) "herinnering_leverancier": null, // (supplier_reminder) "product_id": 3 } ], "kosten": { // (costs) "klant_id": 47, // (customer_id) "opmerking": null, // (remark/note) "betaaltermijn": 14, // (payment_term) "referentie_klant": null, // (customer_reference) "calculated_totaalbedrag_inclusief_btw": 643.95, // (calculated_total_amount_including_vat) "bedrijf_id": 1, // (company_id) "boeking_id": 34, // (booking_id) "regels": [ // (lines) { "id": 285, "naam": "Klimmen en barbecue", // (name: "Climbing and barbecue") "type": "groep", // (type: "group") "kortingspercentage": 0, // (discount_percentage) "kortingomschrijving": null, // (discount_description) "children_visible": false, "regels": [ // (lines) { "id": 288, "naam": "Ontvangst koffie / thee", // (name: "Reception coffee / tea") "type": "item", "kortingspercentage": 0, // (discount_percentage) "kortingomschrijving": null, // (discount_description) "aantal": 15, // (number/quantity) "bedrag": 2.5, // (amount) "btw_percentage": 6, // (vat_percentage) "product_id": 3, "boekingsregel_id": 134 // (booking_line_id) }, { "id": 287, "naam": "Groepen klimmen", // (name: "Group climbing") "type": "item", "kortingspercentage": 0, // (discount_percentage) "kortingomschrijving": null, // (discount_description) "aantal": 15, // (number/quantity) "bedrag": 15, // (amount) "btw_percentage": 6, // (vat_percentage) "product_id": 6, "boekingsregel_id": 133 // (booking_line_id) }, { "id": 286, "naam": "Basis BBQ", // (name: "Basic BBQ") "type": "item", "kortingspercentage": 0, // (discount_percentage) "kortingomschrijving": null, // (discount_description) "aantal": 15, // (number/quantity) "bedrag": 23, // (amount) "btw_percentage": 6, // (vat_percentage) "product_id": 5, "boekingsregel_id": 132 // (booking_line_id) } ] } ] } } :resheader Location: The location of the new booking :statuscode 201: Booking created :statuscode 406: Error in the input :statuscode 403: User does not have the ``createBoeking`` (createBooking) permission Read ---- .. _BoekingenEmbedParameter: .. http:get:: /api2/boekingen Get a list of bookings :query integer page: Default: *1*, minimum: *1* The page to display :query integer page_size: Default: *100* The number of bookings per page :query integer locatie: Comma-separated list of location-ids (`locatie-ids`), request bookings that have an activity at one of these locations (`locatie` means location) :query periode periode: ISO 8601 time interval. E.g.: *P1D* or *2021-11-01T00:00:00+01:00/2021-11-05T00:00:00+01:00* (`periode` means period) :query string referentiedatum: Default: *boekingsregel* (booking_line) Filter bookings by containing a booking line in the given period (``boekingsregel`` (booking_line), default); by start date of the booking (``startdatum`` (start_date)); or by booking creation date (``created_at``) (`referentiedatum` means reference_date) :query boekingsstatus_ status: Comma-separated list of statuses (`statussen` means statuses) :query boolean los_op_planning: Only return bookings that contain a product with the setting *separate on planning* (`los_op_planning` means separate_on_planning) :query objectnaam embed: Comma-separated list of objects to include in the results list. Possible object names are ``Klant`` (Customer), ``boekingsregels`` (booking_lines), ``kosten`` (costs), ``Klant.Hoofdcontact`` (Customer.MainContact) (implies ``Klant`` (Customer)), ``Creator``, ``Diensten`` (Services), ``Facturen`` (Invoices), ``Facturen._betaald_bedrag`` (Invoices._paid_amount) (`objectnaam` means object_name) :query integer klant_id: Only return bookings from this customer (`klant_id` means customer_id) :query string Klant.soort_klant: Comma-separated list of customer types (`klantsoorten`). Only display bookings where the customer is of this type. (implies ``embed=Klant`` (Customer)) (Since version 0.1.1) (`soort_klant` means customer_type) :query integer bedrijf_id: Comma-separated list of company ids (`bedrijfsids`). Only display bookings where the booking belongs to this company. (implies ``embed=Klant`` (Customer)) (Since version 0.1.1) (`bedrijf_id` means company_id) :query bevat_product_id: Comma separated list of product ids the booking must contain :statuscode 200: OK :statuscode 406: Error in the parameters **Example request**: .. sourcecode:: http GET /api2/boekingen HTTP/1.1 Host: demo.recras.nl Accept: application/json **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json [ { "id": 75, "klant_id": 49, // (customer_id) "referentie": "49-2", // (reference) "datum": "2015-01-01", // (date) "status": "informatie", // (status: "information") "arrangement": "Boogschieten met buffet", // (package: "Archery with buffet") "personen": 15, // (persons) "status_updated_at": "2014-06-03T15:11:34+02:00", // (status_updated_at) "arrangement_id": 4, // (package_id) "online_boeking": false, // (online_booking) "status_vervaldatum": null, // (status_expiry_date) "bijzonderheden": null, // (particulars) }, { "id": 1, "klant_id": 9, // (customer_id) "referentie": "9-1", // (reference) "datum": "2014-05-01", // (date) "status": "informatie", // (status: "information") "arrangement": "Gezinsmaaltijd", // (package: "Family meal") "personen": 10, // (persons) "status_updated_at": "2013-06-19T10:46:47+02:00", // (status_updated_at) "arrangement_id": 2, // (package_id) "online_boeking": false, // (online_booking) "status_vervaldatum": null, // (status_expiry_date) "bijzonderheden": "", // (particulars) "conceptfactuur_na_dagen": null // (draft_invoice_after_days) } ] .. http:get:: /api2/boekingen/(int:id) A specific booking :query objectnaam embed: Comma-separated list of objects to include in the results list. See also BoekingenEmbedParameter_ (`objectnaam` means object_name) :statuscode 200: OK :statuscode 406: Error in the parameters :statuscode 404: Booking not found **Example request (embed Customer (`Klant`))**: .. sourcecode:: http GET /api2/boekingen/75?embed=Klant,Klant.Hoofdcontact,boekingsregels,kosten,gefactureerd_bedrag HTTP/1.1 Host: demo.recras.nl Accept: application/json **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "id": 25, "klant_id": 46, // (customer_id) "datum": "2014-11-15", // (date) "status": "optie", // (status: "option") "arrangement": "Klimmen en bbq", // (package: "Climbing and bbq") "personen": 23, // (persons) "status_updated_at": "2014-10-14T12:04:05+02:00", // (status_updated_at) "arrangement_id": 2, // (package_id) "online_boeking": false, // (online_booking) "status_vervaldatum": "2014-10-13", // (status_expiry_date) "bijzonderheden": "", // (particulars) "conceptfactuur_na_dagen": null, // (draft_invoice_after_days) "gefactureerd_bedrag": 0, // (invoiced_amount) "referentie": "46-1", // (reference) "boekingsregels": [ // (booking_lines) { "id": 112, "locatie_id": 2, // (location_id) "aantal": 23, // (number/quantity) "begin": "2014-11-15T12:00:00+01:00", // (start) "eind": "2014-11-15T14:00:00+01:00", // (end) "minimum_aantal": 0, // (minimum_number) "beschrijving": "Genieten van onze heerlijke BBQ", // (description: "Enjoy our delicious BBQ") "opmerking": "", // (remark/note) "betaald_bedrag": null, // (paid_amount) "betaal_datum": null, // (payment_date) "betaal_opmerking": null, // (payment_remark) "herinnering_leverancier": null, // (supplier_reminder) "product_id": 5 }, { "id": 113, "locatie_id": 1, // (location_id) "aantal": 20, // (number/quantity) "begin": "2014-11-15T09:30:00+01:00", // (start) "eind": "2014-11-15T12:00:00+01:00", // (end) "minimum_aantal": 8, // (minimum_number) "beschrijving": "Met de hele groep, onder begeleiding, heerlijk klimmen.", // (description: "With the whole group, under supervision, enjoy climbing.") "opmerking": "", // (remark/note) "betaald_bedrag": null, // (paid_amount) "betaal_datum": null, // (payment_date) "betaal_opmerking": null, // (payment_remark) "herinnering_leverancier": null, // (supplier_reminder) "product_id": 6 }, { "id": 114, "locatie_id": 2, // (location_id) "aantal": 23, // (number/quantity) "begin": "2014-11-15T09:00:00+01:00", // (start) "eind": "2014-11-15T09:30:00+01:00", // (end) "minimum_aantal": 0, // (minimum_number) "beschrijving": "Ontvangst met koffie,thee op het Klimbos terras", // (description: "Reception with coffee, tea on the Klimbos (Climbing Forest) terrace") "opmerking": "", // (remark/note) "betaald_bedrag": null, // (paid_amount) "betaal_datum": null, // (payment_date) "betaal_opmerking": null, // (payment_remark) "herinnering_leverancier": null, // (supplier_reminder) "product_id": 3 } ], "Klant": { // (Customer) "id": 46, "displaynaam": "Restaurant de Dinkel", // (display_name: "Restaurant de Dinkel") "naam": "Restaurant de Dinkel", // (name: "Restaurant de Dinkel") "adres": "", // (address) "postcode": "", // (postal_code) "plaats": "Dinxperloo", // (city: "Dinxperloo") "provinciecode": null, // (province_code) "website": "", // (website) "bedrijf_id": 1, // (company_id) "soort_klant": null, // (customer_type) "afdeling": null, // (department) "factuur_adressering": null, // (invoice_addressing) "Hoofdcontact": { // (MainContact) "id": 41, "voornaam": "Fiona", // (first_name) "achternaam": "Teggartz", // (last_name) "geslacht": "onbekend", // (gender: "unknown") "aanhef": "", // (salutation) "adres": "", // (address) "postcode": "", // (postal_code) "plaats": "", // (city) "telefoon1": "", // (phone1) "telefoon2": "", "email1": "", "email2": "", "hoofdcontact": true // (main_contact) } }, "kosten": { // (costs) "klant_id": 46, // (customer_id) "opmerking": "", // (remark/note) "betaaltermijn": 14, // (payment_term) "referentie_klant": "", // (customer_reference) "calculated_totaalbedrag_inclusief_btw": 886.5, // (calculated_total_amount_including_vat) "bedrijf_id": 1, // (company_id) "boeking_id": 25, // (booking_id) "regels": [ // (lines) { "id": 236, "naam": "Klimmen en bbq", // (name: "Climbing and bbq") "type": "groep", // (type: "group") "kortingspercentage": 0, // (discount_percentage) "kortingomschrijving": "", // (discount_description) "children_visible": false, "regels": [ // (lines) { "id": 239, "naam": "Ontvangst koffie / thee", // (name: "Reception coffee / tea") "type": "item", "kortingspercentage": 0, // (discount_percentage) "kortingomschrijving": "", // (discount_description) "aantal": 23, // (number/quantity) "bedrag": 2.5, // (amount) "btw_percentage": 6, // (vat_percentage) "product_id": 3, "boekingsregel_id": 114 // (booking_line_id) }, { "id": 238, "naam": "Groepen klimmen", // (name: "Group climbing") "type": "item", "kortingspercentage": 0, // (discount_percentage) "kortingomschrijving": "", // (discount_description) "aantal": 20, // (number/quantity) "bedrag": 15, // (amount) "btw_percentage": 6, // (vat_percentage) "product_id": 6, "boekingsregel_id": 113 // (booking_line_id) }, { "id": 237, "naam": "Basis BBQ", // (name: "Basic BBQ") "type": "item", "kortingspercentage": 0, // (discount_percentage) "kortingomschrijving": "", // (discount_description) "aantal": 23, // (number/quantity) "bedrag": 23, // (amount) "btw_percentage": 6, // (vat_percentage) "product_id": 5, "boekingsregel_id": 112 // (booking_line_id) } ] } ] } } Update ------ .. http:put:: /api2/boekingen/(int:id) Update an existing booking. :json int id: The ``id`` number, cannot be changed :json string klant_id: The ``id`` number of the customer, cannot be changed (`klant_id` means customer_id) :json date datum: *Deprecated* The date of the booking, cannot be changed (`datum` means date) :json string status: The status of the booking (for possible statuses see :ref:`booking_status`) :json string arrangement: The name of the package (`arrangement`) as presented to the customer :json int personen: The number of persons for the booking (`personen` means persons) :json datetime status_updated_at: The moment this booking's status was last changed. Cannot be changed :json int arrangement_id: The ``id`` number of the package (`arrangement`) this booking is based on, cannot be changed :json boolean online_boeking: Whether this booking was created by the Online Booking module. Cannot be changed (`online_boeking` means online_booking) :json date status_vervaldatum: Status expiry date. Only valid for bookings with status *informatie* (information), *interesse* (interest), *optie* (option) and *reservering* (reservation) (`status_vervaldatum` means status_expiry_date) :json string bijzonderheden: Remarks for internal use (`bijzonderheden` means particulars) :json int conceptfactuur_na_dagen: How many days after the booking a draft invoice should be created. A negative number ensures that a draft invoice is created before the booking date. *null* means no draft invoice will be created (`conceptfactuur_na_dagen` means draft_invoice_after_days). :json string referentie: The reference of the booking. Cannot be changed (`referentie` means reference) :json array boekingsregels: The list of booking lines for this booking. Booking lines (`boekingsregels`) can be added, removed, or modified. Must be modified simultaneously with the ``kosten`` (costs) field. If a new line is added, no cost line needs to be added; this happens automatically. :json kosten: The cost structure (`kosten`) of this booking. Cost lines can be added, removed, or modified. Must be modified simultaneously with the ``boekingsregels`` (booking_lines) field. A cost structure must contain a corresponding *item* line for each booking line. **Booking lines (`Boekingsregels`)** :json int boekingsregel.id: ``id`` number of the booking line to be modified. Cannot be changed. :json string boekingsregel.ref: User-chosen reference to refer to from new cost lines. :json int boekingsregel.locatie_id: ``id`` number of the location (`locatie_id`) where this activity takes place. Can only be set to locations where the specified product can take place. :json int boekingsregel.aantal: *Required for new booking lines* (`aantal` means number/quantity) :json datetime boekingsregel.begin: Start (`begin`) of the activity. Must be less than or equal to the corresponding end time :json datetime boekingsregel.eind: End (`eind`) time. Must be greater than or equal to the corresponding start time :json int boekingsregel.minimum_aantal: Cannot be changed (`minimum_aantal` means minimum_number) :json string boekingsregel.beschrijving: Description (`beschrijving`) of the booking line to show to the customer :json string boekingsregel.opmerking: Remark (`opmerking`) for the booking line for staff and/or supplier :json float boekingsregel.betaald_bedrag: Amount paid (`betaald_bedrag`) to the supplier for this booking line :json date boekingsregel.betaal_datum: Date (`betaal_datum`) on which payment was made to the supplier for this booking line :json string boekingsregel.betaal_opmerking: Remark (`betaal_opmerking`) for the payment to the supplier :json datetime boekingsregel.herinnering_leverancier: Moment the last automatic reminder (`herinnering_leverancier`) was sent to the supplier. Cannot be changed :json int boekingsregel.product_id: ``id`` number of the product. Modifying this field also modifies ``boekingsregel.minimum_aantal`` (booking_line.minimum_number) **Cost structure (`Kosten-structuur`)** :json int kosten.klant_id: *Deprecated* ``id`` number of the customer (`klant_id`). Cannot be changed :json string kosten.opmerking: Remark (`opmerking`) for on the invoice :json int kosten.betaaltermijn: The payment term (`betaaltermijn`) in days :json string kosten.referentie_klant: An extra reference (`referentie_klant`) for the customer :json float kosten.calculated_totaalbedrag_inclusief_btw: The total amount (`calculated_totaalbedrag_inclusief_btw`) the customer would have to pay if the booking is invoiced. Cannot be changed :json int kosten.bedrijf_id: ``id`` number of the company (`bedrijf_id`) on whose behalf invoices are sent :json int kosten.boeking_id: *Deprecated* ``id`` number of the booking (`boeking_id`). Cannot be changed :json array kosten.regels: List of ``kostenregel`` (cost_line) objects (`regels` means lines). **Cost line (`Kostenregel`)** :json int kostenregel.id: ``id`` number of the cost line. Cannot be changed :json string kostenregel.boekingsregel_ref: Reference of new booking line. Cannot be modified simultaneously with ``id`` or ``boekingsregel_id`` (booking_line_id) :json string kostenregel.naam: (`naam` means name) :json string kostenregel.type: *Required* Type of the cost line, possible values are *groep* (group), *item* :json float kostenregel.kortingspercentage: Discount percentage (`kortingspercentage`) to calculate for this *item* or this *groep* (group) :json string kostenregel.kortingomschrijving: Description (`kortingomschrijving`) of the calculated discount :json boolean kostenregel.children_visible: *Only for group lines* Whether the underlying lines should be displayed on the invoice :json array kostenregel.regels: *Only for group lines* List of cost lines (`regels` means lines) :json int kostenregel.product_id: *Only for item lines* ``id`` number of the product. Can only be modified when ``boekingsregel_id`` (booking_line_id) = *null*. Is automatically adjusted when the corresponding booking line is modified. :json int kostenregel.aantal: *Only for item lines* Number of units (`aantal`). Can only be modified when ``boekingsregel_id`` (booking_line_id) = *null*. Is automatically adjusted when the corresponding booking line is modified. :json float kostenregel.bedrag: *Only for item lines* Unit price (`stuksprijs`). Is automatically adjusted when the corresponding booking line is modified (`bedrag` means amount). :json float kostenregel.btw_percentage: *Only for item lines* VAT percentage (`btw_percentage`) to calculate. Is automatically adjusted when ``kostenregel.product_id`` (cost_line.product_id) is modified. :json int kostenregel.boekingsregel_id: *Only for item lines* ``id`` number of the corresponding booking line (`boekingsregel_id`) Delete ------ .. http:delete:: /api2/boekingen/(int:id) Delete an existing booking. Not all bookings can be deleted. To check if a booking can be deleted, make a GET request to /api2/boekingen/:id/deletable **Example request**: .. sourcecode:: http DELETE /api2/boekingen/5 HTTP/1.1 Host: demo.recras.nl **Example response**: .. sourcecode:: http HTTP/1.1 200 OK :statuscode 200: Booking deleted .. _booking_status: Booking Statuses (Statussen van boekingen) ------------------------------------------ Every booking in Recras has a status. All statuses are described on `the general support page about booking statuses `_. The possible statuses are: * *informatie* (information) * *interesse* (interest) * *optie* (option) * *pending_online* (pending_online) * *reservering* (reservation) * *definitief* (confirmed) * *gaande* (ongoing) * *voltooid* (finished/completed) * *geannuleerd* (cancelled) HATEOAS Links ------------- Each booking resource should have a ``_links`` map. The following relations may be present: ``recras:diensten_bij_boeking`` (services_for_booking) If this link is present, you may follow it to find a list of shifts associated with this booking. ``recras:send_boekingsvoorstel`` (send_booking_proposal) If this link is present, you may follow it to send a booking proposal. ``recras:invoices`` If this link is present, you may follow it to find a list if invoices associated with this booking. ``recras:booking:set_status:ongoing`` .. _link-ongoing: If this link is present, you may follow it to set the status of the booking to *ongoing* (``gaande``). In the special case of the booking-status being set from *finished* (``voltooid``) to *ongoing* (``gaande``), the link may return 403 response if the authenticated user doesn't have the ``saveOverbooking`` permission, otherwise, it should return a 204 status code. The Recras Point-of-Sale uses this link to set bookings to *ongoing* (``gaande``). New in API version 0.2.1 ``recras:booking:set_status:finished`` .. _link-finished: If this link is present, you may follow it to set the status of the booking to *finished* (``voltooid``). The Recras Point-of-Sale uses this link to set bookings to *finished* (``voltooid``). New in API version 0.2.1 ``recras:booking:set_status:confirmed`` .. _link-confirmed: If this link is present, you may follow it to set the status of the booking to *confirmed* (``definitief``). The Recras Point-of-Sale uses this link to set bookings to *confirmed* (``definitief``). New in API version 0.2.1 ``recras:booking:qr`` If this link is present, you may follow it to get the contents of a QR-code that can be used to put the booking to "ongoing" (``gaande``) in the POS