This package has been deprecated

Author message:

Package has been superceded by @entur/create-offer-configurations-from-offer-to-buy and @entur/reduce-customers-for-offer-configuration

@entur/add-customers-to-offer-configurations
TypeScript icon, indicating that this package has built-in type declarations

1.3.1 • Public • Published

@entur/add-customers-to-offer-configurations

Adds customers with possible entitlements to offer configurations so that they can be reserved using reserve-offers in the Entur Sales System.

Background

In the Entur Sales system, if an offer requires one or more entitlements to be purchased, the offer configurations that refer to this offer need to contain a customer with the said entitlements. And for all other offers, you can still supply a customer to an offer configuration if you want to attach that customer to the resulting order lines.

Calls to reserve-offers will fail if you supply an offer configuration with a customer with entitlements other than exactly the entitlements that are required to purchase the specified offer.

Installation

Using yarn:

yarn add @entur/add-customers-to-offer-configurations

Using npm:

npm install @entur/add-customers-to-offer-configurations

Usage

The module has a default export:

export default function addCustomersToOfferConfigurations(
  customers: Customer[],
  offerConfigurations: OfferConfiguration[],
  offers: Offer[]
): OfferConfiguration[];

And it is imported the way you import any other default import:

import addCustomersToOfferConfigurations from "@entur/add-customers-to-offer-configurations";

If you call this function supplying the correct data (see next parapgraph), the function should be able to assign customers to the offer configurations in the best possible way, supplying exactly the entitlements that the offers require for purchase.

The OfferConfiguration and Customer types are as found in the Reserve Offer API. The Offer type is as found in the Offers API. You will find examples of all of these types in the test/data/ folder. For your convenience, here is one example for each type, as well as example output:

Travelers and Customers

Note that throughout the documentation, we will refer to a "traveler" a lot, which refers to the Traveler type from the Offers API as well as the real-world concept of a named or an anonymous traveler. A Traveler and a Customer refer to the same person if Traveler.id is the same as Customer.customerId. For example, the example customer looked as follows when it was used to request offers:

{
  id: "3537054",
  userType: "ADULT",
  products: [
    { id: "NSB:EntitlementProduct:levelA1", version: "NSB:Version:V1" },
  ],
}

Use cases

The addCustomersToOfferConfigurations function has been designed to work for all reasonable use cases we could think of. It should therefore work with …

  • … offerConfigurations spanning several stretches (i.e. service journeys).
  • … offers that require entitlements and not.
  • … groups containing both anonymous and named travelers.
  • … offer configurations with supplement products.

See examples of usage in the corresponding test file.

Caveats

Known shortcomings

Due to the way the assignment problem algorithm works, the module's support for offer configurations that require multiple customers is limited. The algorithm is only guaranteed to work if such offers can be pruned as safe bets.

You can only add customers that were present in the offers request

The algorithm uses traveler IDs contained within the offers to attach customers to them (see Travelers and customers). The offers' traveler IDs are subsets of the traveler IDs that were supplied when requesting the offers. In other words, given a customer where customerId === "123", the algorithm will only be able to attach this customer to an offer that was requested with a traveler with id === "123" in its request body. As long as you keep the group of travelers unchanged from requesting offers until reserving them, which is standard procedure, you should be fine.

Use at your own risk, and tell us when things go wrong

We, the authors, have chosen to share this code because solving this problem took long. Sharing our solution will save time and money for Entur as a whole (as most clients accessing the Entur Sales System will have to solve the same problem).

We have made our best effort to ensure that our package solves the problem correctly and that the documentation (readme, code comments and tests) gives a fair impression of the risks and rewards of using the package. But we do not control of neither the Offers nor Reserve Offer API, so API changes may invalidate our assumptions and design choices. And we may have made honest mistakes.

If you ever experience problems, please report them to support@entur.org and help fixing the problem in any way you can (file a PR if you work inside Entur, or just mail us your suggestions)

How the module works

To solve the problem, we first assume that each stretch in the journey (each service journey) is independent of the others. That is to say, there is no information about which customers were assigned to what offerConfiguration for some earlier or later stretch of the journey that has any impact on how they should be assigned to the current stretch.

After making that assumption, the problem is solved by two algorithms in succession.

Pruning safe bets

If an offer has a minimum amount of travelers equal to the travellers it is meant for, assigning these customers to the offer's corresponding offer configuration is considered a safe bet. The function assignUsingSafeBets handles this.

This algorithm was invented to cope with group tickets, in a single ticket and a single fare product covers multiple travellers. We could not come up with an elegant modification to assignCustomersUsingMinimumCostFlow, but this algorithm seems to remove all offer configurations that would warrant a modification from its input.

Transforming the problem to a graph

Optimally assigning customers to offer configurations is an assignment problem (specifically, a balanced assignment problem), which is solvable as a minimum-cost flow problem.

We construct a flow network representing the problem in the following way:

  1. Every traveler and offer configuration on this service journey is considered a node.
  2. There is also a start node and an end node (a convention in flow problems)
  3. An edge goes from the start node to each traveler.
  4. An edge goes from a traveler to an offer configuration if the traveler is in the offer's traveler mapping.
    1. Edges from anonymous travelers to an offer have a higher cost than those from named travelers to the same offer (see detailed explanation below).
  5. An edge goes from each offer configuration to the end node.
    1. Its cost is equal to the cost of the offer configuration.
  6. All edges have capacity 1, except those going from an offer configuration (whose capacity is equal to the offer configuration's count).

Example

The following illustration shows a problem with three offer configurations and three travelers. Offer configurations oc1 and oc2 can be used by all travelers, while oc3 is only available to t3.
A graph containing a start node, three traveler nodes, three offer configuration nodes and an end node

One optimal assignment of customers to offerConfigurations has t3 assigned to oc3, t1 to oc1 and t2 assigned to oc2. The only other possible, optimal assignment is to switch t1 and t2 around.

Readme

Keywords

none

Package Sidebar

Install

npm i @entur/add-customers-to-offer-configurations

Weekly Downloads

21

Version

1.3.1

License

MIT

Unpacked Size

128 kB

Total Files

10

Last publish

Collaborators

  • phun-ky
  • ceciliehrr
  • tysseng-entur
  • martinbjerkeengen
  • frankwaldal
  • carljoachim
  • oysval
  • magnusrand
  • wfeiring
  • vages
  • enturas
  • kentandersen
  • testower