Skip to content

Types and territories

Types

Types restrict which Drivers are allowed to do which Jobs

This is often used for:

  • Ensuring certain deliveries are performed by refrigerated vehicles
  • Ensuring that the driver has the right qualifications to perform a service (e.g. she is a level 2 qualified electrician)
  • Ensuring that large parcels are delivered by large enough vehicles, or vehicles with a tail lift
  • Forcing a Job to be performed by a specific Driver (because the customer requested her, for example)
  • Ensuring only certain vehicle types (e.g. small trucks, bicycles, electric vehicles) perform deliveries in city areas

If you are looking to create "Territories" or "Delivery Zones", please use Territories.

You can use this constraint by setting the spec_type on Jobs and Drivers.

A Job with spec_type omitted or set to null or "" (empty string) can be served by any Driver. Any white space in spec_type fields is ignored.

Note

We refer to this constraint as Types, yet in the code this is called spec_type, an abbreviation of Specialisation Type.

type is a reserved word in most programming languages, so we didn't want to use it.

Simple Types

If a Job has one or more types, it may only be served by a Driver who has the same type.

For example a Job with type electrician cannot be served by a driver without a type, or a driver with type plumber. However, it can be served by a Driver with type electrician.

Examples

{
  "drivers": [
    {
      "uid": "driver_1",
      "shift_start": 8,
      "shift_end": 17,
      "start": {"lat": -33.867798, "lon": 151.166256},
      "end": "start",
      "spec_type": "plumber"
    }
  ],
  "jobs": [
    {
      "uid": "job_1",
      "duration": 2,
      "location": {"lat": -33.849489, "lon": 151.127482},
      "spec_type": "plumber"
    },
    {
      "uid": "job_2",
      "duration": 2,
      "location": {"lat": -33.880661, "lon": 151.183096},
      "spec_type": "electrician"
    },
    {
      "uid": "job_3",
      "duration": 2,
      "location": {"lat": -33.913168, "lon": 151.262267},
      "spec_type": null
    }
  ],
  "settings": {}
}

Multiple Types

Multiple types should be separated by commas ,.

A Job with type cert1,cert2 could be served by a Driver with any of the following types:

  • cert1
  • cert2
  • cert1,cert2
  • cert1,cert8
  • plumber,cert2,cert8

but it cannot be served by a driver with any of the following types:

  • (blank)
  • cert8
  • cert8,cert9
  • plumber
  • plumber,cert8

Examples

{
  "drivers": [
    {
      "uid": "driver_1",
      "shift_start": 8,
      "shift_end": 17,
      "start": {"lat": -33.867798, "lon": 151.166256},
      "end": "start",
      "spec_type": "plumber,cert2,cert3"
    }
  ],
  "jobs": [
    {
      "uid": "job_1",
      "duration": 2,
      "location": {"lat": -33.849489, "lon": 151.127482},
      "spec_type": "cert2"
    },
    {
      "uid": "job_2",
      "duration": 2,
      "location": {"lat": -33.880661, "lon": 151.183096},
      "spec_type": "plumber"
    },
    {
      "uid": "job_3",
      "duration": 2,
      "location": {"lat": -33.913168, "lon": 151.262267},
      "spec_type": "electrician,cert3"
    },
    {
      "uid": "job_4",
      "duration": 2,
      "location": {"lat": -33.913168, "lon": 151.262267},
      "spec_type": "electrician,cert4"
    },
  ],
  "settings": {}
}

Logical Types

If you need to be more specific about who can do what, use logical types

Logical types can only be applied to Jobs. The Driver spec_type must be expressed using Multiple Types or Simple Types as above.

Logical types are expressed in our DSL:

  • AND constraints (all of which must be true) are expressed using &
  • OR constraints (at least one must be true) are expressed using |
  • Parentheses are used to ( group logical sections )

For example, imagine all of your internal Drivers are qualified to do all Jobs. But sometimes you use subcontracted drivers, and it is important to ensure they have the appropriate qualification for each Job.

A Job with spec_type internal|(subcontractor&cert3) could be served by any Driver with one of the following types:

  • internal
  • internal,plumber
  • subcontractor,cert3
  • subcontractor,cert1,cert2,cert3,cert4

but cannot be served by a Driver with one of the following types:

  • (blank)
  • subcontractor
  • cert3
  • subcontractor,cert1,cert2,cert4

Examples

{
  "drivers": [
    {
      "uid": "driver_1",
      "shift_start": 8,
      "shift_end": 17,
      "start": {"lat": -33.867798, "lon": 151.166256},
      "end": "start",
      "spec_type": "internal"
    },
    {
      "uid": "driver_2",
      "shift_start": 8,
      "shift_end": 17,
      "start": {"lat": -33.867798, "lon": 151.166256},
      "end": "start",
      "spec_type": "subcontractor,cert4"
    },
    {
      "uid": "driver_3",
      "shift_start": 8,
      "shift_end": 17,
      "start": {"lat": -33.867798, "lon": 151.166256},
      "end": "start",
      "spec_type": "subcontractor,cert3,cert4"
    }
  ],
  "jobs": [
    {
      "uid": "job_1",
      "duration": 2,
      "location": {"lat": -33.849489, "lon": 151.127482},
      "spec_type": "internal|(subcontractor&cert3)"
    }
  ],
  "settings": {}
}

Territories

Many Delivery and Field Services companies divide their serviceable area into "zones" or "territories".

Companies often adopt this approach because:

  • Each Driver gets to know their geographic area well
  • You immediately know which Route a new Job falls into based on its location
  • Warehouses can prepare shipments on the dock before the last order is made, before the optimisation is run.

Warning

Routes planned with Territories are usually 10% to 35% longer (KMs and hours) than without.

However, this feature exists because we know that many companies cannot make the operational trade-offs required to receive that benefit.

Internally, Territories are implemented using Types, so you'll notice the syntax is the same as Multiple Types.

A Driver with driver.territories = 'North,East' can serve Jobs with:

  • job.territories = 'North'
  • job.territories = 'East'
  • job.territories = 'North,East'
  • job.territories = ''
  • job.territories = null

but cannot serve Jobs with:

  • job.territories = 'West'
  • job.territories = 'NorthEast'

Jobs Outside Territories

Sometimes you will have a job that is not in any territory.

By default any Driver can serve this Job.

However, you may desire all Jobs outside of your predefined Territories to be unserved. To put this in place, simply set the job.territories = 'JOB_OUTSIDE_TERRITORIES'

  • This effectively creates an extra Territory which no driver can serve.
  • It doesn't matter what you call it. It just needs a territory name that no Drivers have.