Description
This API provides endpoints for parties that want to implement a shop based on information/functionality available in Fuga:
- product and stock data
- client data
- invoicing functionality
This shop can be an application created by an independent software house on request of a clinic OR it can be the shop module in the myPets application. So basically it is a front-end to the product-offering of the practice and/or its suppliers. It's not an independent legal entity.
TODO: provide backorder mechanism (allow to order/invoice when product not in stock).
A possible usecase is depicted in the below picture.
Endpoints
The base url is https://(testX.)sonetas.eu/fuga/rest/shop/{practiceId}
with {practiceId} the queried practice.
Catalog
Get catalogs
Return the available catalogs for a given practice.
GET catalog
RETURNS
http status 200 ok, returning json array with the available catalog ids
[TPractice,TCatalogA,TCatalogB]
or other http status on error
Get catalog info
Returns info specific for a certain catalog, e.g. logo, color theme, link to general conditions, shipping cost to be applied (cost is determined by practice and can depend on payment method and total amount of order) …
GET catalog/{catalogId}
Product
Get product list
GET catalog/{catalogId}/product/{productType}/{language}/?name=foo&label=bar¤tStock=false
with:
- productType: TAll, TDrug, TAnimalFood, TAnimalFoodSupplement, TCareProduct, TMaterial
- and optional parameters
- language: TDutch, TFrench, TEnglish (determines the language in which product names and units are returned)
- name: filter on the product name (behaviour: like 'foo%')
- label: filter on the product label(behaviour: like 'bar%')
- currentStock: indicate whether the current stock (availableNbrOfUnits) should be returned (default=false)
RETURNS
http status 200 ok, returning json array with product info
{"products":[{"id":2, "name":"zalmbrokken", "cnk":"1234567","type":"TAnimalFood", "unit"="zak", "listPriceExclVat"=12.34, "vatPercentage":21.00, "availableNbrOfUnits":4021},{…}]}
or other http status on error
If availableNbrOfUnits=null, it means that there is no limitation on the available stock.
Note: for catalogId=TPractice only active products that are made available to the shop are returned
Get product detail
GET catalog/{catalogId}/product/{productId}
Also returns the available deliveryMethods for this product (can be different per product: case of wholesaler catalog, but product is in stock at practice and one allows to order in outgoing units of practice => TShippedByWholesaler not possible).
Client
Get client info
GET client/{emailAddress}
with:
- emailAddress: the email address of the queried person
RETURNS
http status 200 ok, returning json with info of person
{"personId":123, "emailAddress":"dirk@sonetas.eu", "title":"TMr","firstName":"Dirk","lastName":"Ooms", "language"="TDutch", "reduction":5, "streetAndNumber":"", "city":"", "zipCode":"", "country":"TBelgium", "allowMarketingMessages":false}
or http status 404 not found
or other http status on error
Create/update client
POST client
PUT client/{personId}
{"emailAddress":"dirk@sonetas.eu", "title":"TMr","firstName":"Dirk","lastName":"Ooms", "language"="TDutch", "reduction":5, "streetAndNumber":"", "city":"", "zipCode":"", "country":"TBelgium", "companyName":"", "vatNumber":"", "allowMarketingMessages":false}
with:
- title: TMr, TMrs, TMiss, TDr, TVet, TProf, TFamily, TMrAndMrs,
POST: all fields are mandatory, except companyName and vatNumber
PUT: only specified fields are updated
RETURNS
http 200 ok with
{"personId":123}
or other http code on error
Get invoices
GET client/{personId}/invoice?startDate=20200701&endDate=20200731
with startDate and endDate optional
RETURNS
http status 200 ok, returning json array with summarized invoices info
{"invoices":[{"id":2, "number":"FA.000123", "date":"2020-07-02"},{"id":9, "number":"FA.000131", "date":"2020-07-12"},…]}
or other http status on error
Get orders
GET client/{personId}/order?startDate=20200701&endDate=20200731
with startDate and endDate optional
RETURNS
http status 200 ok, returning json array with summarized order info
{"orders":[{"id":1, "number":"OR.4", "date":"2020-07-09"},{"id":3, "number":"OR.5", "date":"2020-07-16"},…]}
or other http status on error
Order
Create an order
POST catalog/{catalogId}/order
{"personId":123,"orders":[{"productId":56, "nbrOfUnits":1, "reductionApplied":5, "sellingPriceExclVat":12.23, "vatAmount":2.57}, …], "amountPaid":5.00, "paymentMethod":"TCreditcard", "deliveryMethod": "TPickupAtPractice", "description":"freeTextMessage", "createInvoice":true}
with:
- person: if 'id' is known (!=0), it is sufficient to send the id. if 'id' is not known (=0) info of the person needs to be provided ()
- paymentMethod: TBancontact, TCreditcard, TMollie, …
- deliveryMethod: THandledByShop, TPickupAtPractice, TShippedByPractice, TShippedByWholesaler (only if catalogId!=TPractice)
RETURNS
http 200 ok with
{"orderIds":[123,124], "invoiceId":567}
with:
- the orderId and invoiceId being unique within a practice.
or other http code on error
Get invoice
GET invoice/{invoiceId}
RETURNS
http status 200 ok, returning json object with invoice info
{"id":2, "number":"FA.000123", "date":"2020-07-02", "amount":34.34,"pdfDocument":"BASE64ENCODEDPDFDOCUMENT"}
with:
- pdfDocument: base64 encoded
or other http status on error
Get order
GET order/{orderId}
RETURNS
http status 200 ok, returning json object with invoice info
{"id":1, "number":"OR.2", "date":"2020-07-13", "products":[{"name":"productA", "status":"TOrdered"},{"name":"productB", "status":"TCollected"}],"pdfDocument":"BASE64ENCODEDPDFDOCUMENT"}
with:
- pdfDocument: base64 encoded
or other http status on error
Wholesaler shops
A practice can expose its own stock in the shop, but it's also possible for third parties (typically wholesalers of the practice) to expose their catalog via this shop API.
It is up to the practice to decide which catalog(s) is/are exposed. Payment and invoicing to the customer is handled by the shop and/or the practice (not by the wholesaler).
The practice does the price setting based on margins on the public price or gross price (this margin can be set by the practice per product type). There is an option for the practice to 'overrule' an item in the wholesaler catalog by an item in its own stock/catalog.
Question: to which extent does the wholesaler want to be visible in the shop? own logo, theme (remark: is wholesaler known by the pet owner?)? or just mentioning 'powered by WholesalerA' and shop presented as shop of practice.
Question: at the moment we are inclined to allow only 1 catalog to be selected, else it could become confusing to the pet owner. Opinion wholesaler?
If a wholesaler wants to integrate with this mechanism the wholesaler should offer below web services. If a wholesaler already integrates with fuga for ordering (practice orders within Fuga products at wholesaler) most web services will already be more or less available, so the required effort to enter the system is rather low.
At the moment we assume a 'retour' is always handled by bringing the product back to the practice.
Get catalog
The catalog is provided in xml or json format. This typically will include:
- product name
- product type (and subtype)
- description
- publicPrice
- link(s) to picture
- link(s) to video
To enhance the user interface (filtering) it is good to have as much information as possible, e.g.:
- promotion/new
- target species
- age category
- indication
- animal size
- producer
A catalog can be language-specific.
Create order
This method should allow to order a product based on the article code in the catalog. It must be a real order (not adding to shopping basket). If wholesaler offers home delivery, this can be indicated. This method must return a wholesaler specific orderId.
Get order status
Get the current status of certain order based on an orderId.
Get list of orders
Get a list of the currently open orders (i.e. not yet completed) for the practice