A sale is described by a hierarchical data model defined by the XML Schema
posps.xsd
. The root element is
sale
. The data model is created by the server on request by the client when calling a
startSale
operation
. The client then manipulates the model by calling the various operations of the
port. The server changes the data model, inserts additional information derived from
the data, and sends the updated model back to the client.
The server is in control of the data. The client supplies new data when it calls an operation but must discard the data and accept whatever the server sends back as response as the valid form of the data. This makes it possible for the server to correct data, map it to its own native data format, or ignore unsupported information. It also prevents a divergence in the sale as seen by the client and the server.
false
, calls to startSale will fail. If
true
is returned, a sale may be started. The client could use this information to go into
an "out-of-order" state while the server is not ready.
The server may not be ready, for example, when a server component did not boot completely.
The position describes the sale of an article with a given quantity. The articleId should be taken from an article search. The position can optionally reference a prescription which prescribes the article. After a position was created, the article cannot be changed.
The server creates a new positionId which is used to refer to the position. The positionId is only valid in the context of the current sale.
The server responds with the updated data model. Usually, it contains a
new position
element for the added position with a newly generated
positionId and an updated total
entry.
position
and the total
have been updated.
position
is removed and the total
entry has been
updated.
The person can either be a person already known to the server and referenced by a personId obtained by a person search or a new person with the data supplied by the client. It is up to the server to decide whether it should create a new entry in the server person store for a person supplied by the client. If it thinks the person data matches an existing entry, it might return the corresponding personId instead of creating a new entry.
The role the person plays in the sale depends on from where it is referenced. It
might be the customer if it is referenced by
setCustomer
, a patient if it is referenced by a prescription, or a physician.
The server responds with the updated data model. Usually, it contains a new
person
element for the person and possibly an updated
total
entry. If the person with the personId has already been part of the sale, the
existing person
entry is updated if the person was changed
by the operation.
person
and perhaps the
total
will have been updated.
person
is removed and perhaps the
total
is updated.
A prescription can be referenced by one or more positions meaning that the position is sold as indicated by the prescription. This can change the price the customer has to pay for the position according to local laws.
The prescription can reference to two person elements - to the patient and the physician.
The server responds with the updated data model. Usually, it contains a
new prescription
element for the new prescription.
prescription
entry for the changed prescription and perhaps updated
position
entries and an updated
total
entry.
prescription
element is removed.
Setting the operator of a sale is optional since there is no operator in case of a self-service sale. If an operator is already set when the operation is called, the old operator will be overwritten with the new one. To delete the operator from the sale, pass a nil value.
The server responds with the updated data model. Usually, it contains an
operator
entry for the operator which has been set.
If there is not already a person element for the customer, the server will add it to the sale. Setting the customer is optional, for a simple sale no customer data is needed. If a customer is already set when the operation is called, the old customer will be overwritten with the new one. To delete the customer from the sale, pass a nil value.
The server responds with the updated data model. Usually, it contains a
customer
entry for the customer who has been set.
If pickup is enabled, the client will be allowed to sell articles which it currently
cannot deliver. The customer can return later to the pharmacy and pick up the
articles which were not delivered. To allow this,
createSaleReceipt
will usually generate a receipt that contains some pickup information the
customer can present to the pharmacist.
If the server allows pickup, it will set the
pickup
element in the returned data model
. If the element is not set, pickup will not be allowed. It is the
responsibility of the client to take this into account and to only sell deliverable articles.
The client can try to enable pickup at any time in the sale, as long it is not too late to roll back the transaction if the server does not allow pickup. If pickup is already enabled, the call will be ignored and the server should return an unchanged data model.
If shipment is enabled, the client will be allowed to sell articles which it currently cannot deliver. The pharmacist will send the undelivered articles to the person set by the operation. To disable shipment, pass a nil value for the personId.
If the server allows shipment, it will set the
shipment
element in the returned data model
. If the element is not set, shipment will not be allowed. It is the
responsibilty of the client to take this into account and to only sell deliverable articles.
Shipment may incur shipping charges, in which case a
total
element including the charges is returned.
Adds a charge/rebate to the charges/rebates of this sale. If there already exists a charge of the given kind in the sale, the amount given is added to the existing amount. If no amount is given, the server is expected to add an amount configured on the server side, e. g. it could calculate shipping charges or use a preset night duty charge.
Deletes the charge of the given type from the sale.
Notification to the server about the payment process selected by the client for this sale. If the payment is canceled (the canceled parameter is true), the payment has been aborted and the customer has been given back his money. Otherwise (an "uncanceled payment"), the client has collected the total amount which the server has specified for this sale and this transaction cannot be undone any more. The client can confirm an arbitrary number of canceled payments, but once an uncanceled payment has been confirmed, there must be no more payment transactions.
After confirmation of an uncanceled payment the server will reject all changes
to the sale that would change the total with a
IllegalStateFault
. If the receipt is to contain information on the payment type (as it is
customary done), the payment must be confirmed before
createSaleReceipt
is called.
closeSale
, the saleId must become invalid and calls which use this ID must raise an
UnknownIdFault
.
Searches are usually performed during a sale to look up articles and persons that are to be included in the search. Alternatively, the client can use a user interface to perform searches independently of a sale.
In order to achieve fast feedback for searches, server and client can control how
many elements from the search result are to be returned for each operation invocation. The
search...
returns the first elements of the result, and the remaining elements (if any) can be
fetched by repeatedly calling
getNextSearchResults
.
The many possibilities for which the search port can be used also means that the
server must support several concurrently open searches. The open searches are
identified by their searchResultId
. A search result is closed if
either the client has received all search result elements or it invokes
discardSearchResults
, or the server discards it after the client has
not used the search result ID for a long time. If the server has an internal limit on
the number of parallel searches and the limit is reached, it raises
a TooManySearchesFault
. The client should react by closing other
search results before starting a new search.
This is usually the first step when adding an article to a sale. The pharmacist
searches for an article, and the
articleId
of the selected element of the search result is used to add the article to a
sale.
If not all elements from the search result are returned, the remaining elements
can be requested with
getNextSearchResults
using the searchResultId returned by this operation.
getNextSearchResults
using the searchResultId returned by this operation.
Instead of communicating with the robot directly to fetch sold articles, the posps service leaves it to the pharmacy system to control the article delivery. This enables the pharmacy system to correctly maintain the inventory and to implement advanced features such as reservation of items.
IMPORTANT: If the OrderPort is supported by the server, all other ports must be supported (implemented) too.
false
, calls to orderArticles
and orderPickupOrders
will always result in delivery errors. If
true
is returned, orders placed may or may not succeed. The client can use this
information to go into an "out-of-order" state while the server is not
ready.
The server will try to deliver the articles to the output location configured for the client. The operation returns immediately, returning an orderId which the client can use to track the status of the order. The orderId may only be valid for the client that placed the order.
A client may place several orders at the same time that the server should handle in FIFO order. A server implementation should try to handle as many concurrent orders as possible, but if for some reason it currently cannot accept more orders, it raises a TooManyOrdersFault.
The server must guarantee that the article delivered for an articleId matches the data (especially product and price) that the server supplies for a sale position with the same articleId. The details which data must match is dependent on the regulations of the country in which the system is used. The PS must also try as far as possible not to deliver an article that has already expired.
A pickup order may consist of one or more articles. The server is responsible for assigning the pickupOrderId to the packages that have to be delivered. Either the pharmacist pre-packaged the articles into a single package or the PS orders the articles individually from the pharmacy robot. In both cases, the articles should be listed individually in the result to this call.
The server will try to deliver the pack(s) to the output location configured for the client. The operation returns immediately, returning an orderId that the client can use to track the status of the order. The orderId may only be valid for the client that placed the order.
A client may place several orders at the same time that the server should handle in FIFO order. A server implementation should try to handle as many concurrent orders as possible, but if for some reason it currently cannot accept more orders, it raises a TooManyOrdersFault.
If trackOrder is requested with orderId it returns a list with the current order statuses of the ordered packs.
If trackOrder is requested with saleId it returns a list with the current order statuses of all articles from this sale.
The client will poll until all packs of the order/sale have been processed (either delivered or failed).
The server may discard the orderId after the sale is closed or aborted.
The server should try to stop the delivery of all packs that have not
already been delivered. This will not always be possible since the server may
already have sent an order to the robot. Since some articles may still be in
delivery, the order can still be incomplete and has to be tracked to await
completion. Packs which were not delivered due to the order being aborted are
listed as failed articles with reason code
aborted
.
A call to abort on an already aborted order is ignored.
A pickup is described by a hierarchical data model defined by the XML Schema
posps.xsd
. The root element is
pickup
. The data model is created by the server on request by the client when calling the
operation
startPickup
. The client then manipulates the model by calling the various operations of the
port. The server changes the data model, inserts additional information derived from
the data, and sends the updated data model back to the client.
The server is in control of the data. The client supplies new data when calling an operation but must discard the data and accept whatever the server sends back as response as the valid form of the data. This enables the server to correct data, map it to its own native data format, or ignore unsupported information. It also prevents a divergence in the pickup as seen by the client and the server.
false
, calls to startSale will fail. If
true
is returned, a pickup may be started. The client might use this information to go into
an "out-of-order" state while the server is not ready. The server may not be
ready, for example, when a server component did not boot completely.
Sets the customer-provided code which identifies a pickup order to the server. The customer must have earlier aquired the code by some means not specified by this interface.
The specification does not define how the code is to be generated. To prevent customers from picking up pickup orders that are not meant for them, it should not be easy to guess valid codes. On the other hand, codes should not be too long so that it is not too difficult for the customer to enter it.
Codes not accepted by the server (invalid format, unknown, etc.) are reported by
UnknownPickupCodeFault
. If the authentication is not accepted, it raises an
AuthenticationRejectedFault
. If the server accepts a pickup code, it sends back the data model containing
the list of articles put
together for this pickup, a pickupId with which the client can order the pickup
order using the
Order
port, and possibly customer information with a person element. Once a pickup
code is accepted, no further calls to
setPickupCode
are allowed for this pickup.
Setting the operator of a pickup is optional since there is no operator in case of a self-service sale. If an operator is already set when the operation is called, the old operator will be overwritten with the new one. To delete the operator from the pickup, pass a nil value.
The server responds with the updated the data model. Usually, it contains an
operator
entry for the operator which has been set.
createPickupReceipt
is called. If there are
problems handing out the picked-up articles afterwards, the client will give the
customer his money back and inform the server by a call to cancelPickupPayment
.
closePickup
, the pickupId must become invalid and calls which use the ID must raise an
UnknownIdFault
.
The implementation of PospsPort is required for working with all other ports.
If several posps clients are configured to access the same server, the server has to be able to identify the clients. For example, when an article has to be delivered the server has to determine the output location for the articles ordered by a specific client. The specification provides a simple means to identify the calling client by using the posId element. This ID is previously agreed upon between client and server and stored in their configuration (by implementation-specific means which are not covered in this specification).
The posId element is only used as parameter in calls where the server cannot determine
the caller ID by other means. For example, it is used in Sale.startSale()
, but not in
Sale.closeSale()
. The server generates a saleId when startSale is called, and
it is expected that the server can determine the client by this saleId when it calls
closeSale
. This keeps the number of arguments passed smaller.
The posId can't be used to securely authenticate the client. If authentication is required between client and server, it should be implemented on the transport level (e. g. by using TLS and certificates) or by using other standards like WS-Security.
Using the posId element in the server is optional. If the server only supports one client, or if the server works the same for all clients, the server can ignore the ID.
The posps web service is designed to be adapted for usage in different countries. This does not mean that implementations will have to support all countries that are supported by the specification. It is usually enough if one country is supported.
Country-specific extensions are implemented in several places of the interface. This
is done by defining elements that are of the type
*CountrySpecific
. This type is an abstract base type from which concrete types are derived. A
concrete type adds the data that is needed to work in a particular country. The
names of the concrete types consist of the name of the base type without the
"CountrySpecific" plus a country code which usually consists of two upper-case
letters. For example, the type
PatientDE
, which is a concrete type derived from
PatientCountrySpecific
, defines elements containing data that has to be processed in a pharmacy
system designed for the German market.
An implementation must support the country-specific types of at least one country.
There may be cases where additional types are also supported. The implementation
might, for example, support several different concrete implementations of
AddressCountrySpecific
to enable the processing of addresses of customers who live abroad. There is
currently no mechanism built into the specification to negotiate which
country-specific types are supported by client and server.
At the moment, the specification only defines country-specific types for Germany.
All monetary amounts in elements are given in the smallest unit of the currency of the country in which the sale is carried out. The amount is given without fractions. For example, in Germany prices are given in Euro-Cents, so an amount of 123 means 1.23€.
The operator is the person who serves and advises the customer at the posps client.
Usually this is done by a pharmacist or a pharmacy technician. Since the posps
interface is used in circumstances where posps clients are operated by pharmacists
who are not usually working for the pharmacy where the client is installed (e. g.
service center pharmacists), a mapping from a posps operator to an operator
configured the posps server is problematic. The posps interface therefore defines no
mechanism to query, create or update operators of the the posps server. It instead
assumes that the posps client has its own mechanism for maintaining a database of
allowed operators. The operator authenticates with the client and the server is
merely informed about this by the client calling
setSaleOperator/setPickupOperator
.
It should also be noted that it is possible that a customer may be served by several operators consecutively in the same sale/pickup.