PHPackages                             rjdeliveryomaha/courierinvoice - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. rjdeliveryomaha/courierinvoice

ActiveLibrary[API Development](/categories/api)

rjdeliveryomaha/courierinvoice
==============================

Tools for using the Courier Invoice API

2.7.7(7mo ago)049MITPHPPHP &gt;=7.0

Since Dec 7Pushed 1mo ago2 watchersCompare

[ Source](https://github.com/rjdeliveryomaha/courierinvoice)[ Packagist](https://packagist.org/packages/rjdeliveryomaha/courierinvoice)[ Docs](https://github.com/rjdeliveryomaha/courierinvoice)[ RSS](/packages/rjdeliveryomaha-courierinvoice/feed)WikiDiscussions master Synced today

READMEChangelog (10)Dependencies (4)Versions (62)Used By (0)

CourierInvoice
==============

[](#courierinvoice)

A set of classes for the Courier Invoice API

Instalation
===========

[](#instalation)

`composer require "rjdeliveryomaha/courierinvoice"`

Or add "rjdeliveryomaha/courierinvoice":"^2.0.0" to composer.json

Classes
=======

[](#classes)

- [SecureSessionHandler](https://github.com/rjdeliveryomaha/courierinvoice#securesessionhandler)
- [CommonFunctions](https://github.com/rjdeliveryomaha/courierinvoice#commonfunctions)
- [Query](https://github.com/rjdeliveryomaha/courierinvoice#query)
- [LoginHandler](https://github.com/rjdeliveryomaha/courierinvoice#loginhandler)
- [Ticket](https://github.com/rjdeliveryomaha/courierinvoice#ticket)
- [Route](https://github.com/rjdeliveryomaha/courierinvoice#route)
- [Scheduling](https://github.com/rjdeliveryomaha/courierinvoice#scheduling)
- [Invoice](https://github.com/rjdeliveryomaha/courierinvoice#invoice)
- [SearchHandler](https://github.com/rjdeliveryomaha/courierinvoice#searchHandler)
- [TicketChart](https://github.com/rjdeliveryomaha/courierinvoice#ticketChart)
- [InvoiceChart](https://github.com/rjdeliveryomaha/courierinvoice#invoiceChart)
- [Client](https://github.com/rjdeliveryomaha/courierinvoice#client)
- [InvoiceCron](https://github.com/rjdeliveryomaha/courierinvoice#invoiceCron)

[extras](https://github.com/rjdeliveryomaha/courierinvoice#extras)

---

SecureSessionHandler
====================

[](#securesessionhandler)

Extends PHPs [SessionHandler](https://secure.php.net/manual/en/class.sessionhandler.php) class.

Provides static functions for session management.

Throws exception on error.

Properties settable in $config
------------------------------

[](#properties-settable-in-config)

These properties are described in [extras/includes](https://github.com/rjdeliveryomaha/courierinvoice/tree/master/extras/includes#session_name).

- session\_name
- domain
- lifetime
- path
- samesite
- secure
- alternateHijackingTest

Public Methods:
---------------

[](#public-methods)

```
try {
  SecureSessionHandler::start_session($config);
} catch (Exception $e) {
  echo $e->getMessage();
  exit;
}
```

This function will try to use `ini_set()` to apply the following settings:

- [session.use\_only\_cookies](https://php.net/manual/en/session.configuration.php#ini.session.use-only-cookies) = 1
- [session.use\_strict\_mode](https://php.net/manual/en/session.configuration.php#ini.session.use-strict-mode) = 1
- [session.cookie\_secure](https://php.net/manual/en/session.configuration.php#ini.session.cookie-secure) = the configured value of `$config['secure']`
- [session.use\_trans\_sid](https://php.net/manual/en/session.configuration.php#ini.session.use-trans-sid) = 0

If these settings fail an exception will be thrown.

If a [valid session name](https://secure.php.net/manual/en/function.session-name.php) is not provided an exception will be thrown.

If a domain name is not provided `$_SERVER['SERVER_NAME']` will be used.

If `$config['alternateHijackingTest']` is `false` the users IP address and user agent will be stored in the session and compared to the values provided by the server upon each validation call which is done every time `SecureSessionHandler::start_session()` is called. It is not recommended that this value be set to `true` however, it may be necessary in situations where a users IP address is frequently changed due to network instability or service provider issues.

`$_SESSION['formKey']` is set to a value generated by `bin2hex(random_bytes(32))`. Validation will compare this value to `$_POST['formKey']` on every POST request then iterate the value. An exception with the message "Session Error" will be thrown if these values don't match.

```
echo SecureSessionHandler::outputKey();
```

Returns the current value of `$_SESSION['formKey']`.

```
SecureSessionHandler::destroySession();
```

- Clears session values.
- Preserves the value of `$_SESSION['formKey']`.
- Destroys the current session.
- Regenerates the session ID.

```
try {
  SecureSessionHandler::start_session($config);
} catch(Exception $e) {
  echo "{$e->getMessage()}";
  return FALSE;
}
echo SecureSessionHandler::outputKey();
return FALSE;
```

Sets and returns a new value for `$_SESSION['formKey']`.

If there is no active session an attempt will be made to create one.

---

CommonFunctions
===============

[](#commonfunctions)

Utility class with functions used throughout the project.

Throws exception on error.

Usage:
------

[](#usage)

```
try {
  $functions = new CommonFunctions($config, $data);
} catch(Exception $e) {
  return $e->getMessage();
}
```

Properties settable in `$data`
------------------------------

[](#properties-settable-in-data)

- noSession
    - Numeric
    - If set and equal to `1` the class will not try to use any session values.

Public Methods:
---------------

[](#public-methods-1)

```
$functions->getProperty($property);
```

Returns a value if the property exists.

Returns `false` if the property does not exist.

```
$functions->updateProperty($property, $value);
```

Sets property to new value.

Returns `true` on success.

Returns `false` if the property does not exist.

```
$functions->addToProperty($property, $value);
```

Adds `$value` to property.

Returns `true` on success.

Returns `false` if the property does not exists.

Returns `false` if `$value` or the property is not numeric.

```
$functions->substractFromProperty($property, $value);
```

Subtract `$value` from the property.

Returns `true` on success.

Returns `false` if the property does not exists.

Returns `false` if `$value` or the property is not numeric.

```
$functions->compareProperties($obj1, $obj2, $property, $strict=FALSE);
```

Returns `false` if property does not exist in both objects.

Returns `true` if the properties hold *equal* values.

`$strict` compares type as well as value.

Returns `true` is properties hold *identical* values.

```
$functions->debug();
```

Pretty print properties and values.

```
$functions->getError();
```

Return the last error.

---

Query
=====

[](#query)

Extends [CommonFunctions](https://github.com/rjdeliveryomaha/courierinvoice#commonfunctions)

This class handles the creation and execution of calls to the API.

Throws exception on error.

Usage:
------

[](#usage-1)

```
try {
  $query = new Query($config, $data);
} catch(Exception $e) {
  return $e->getMessage();
}
```

Properties settable in $data:
-----------------------------

[](#properties-settable-in-data-1)

- primaryKey

    - Integer
    - Should not be set unless using PUT or DELETE.
    - An Exception will be thrown if the PUT or DELETE method are used with this property being not set.
- endPoint

    - String
    - Valid end points:

        config, tickets, invoices, clients, o\_clients, contract\_locations, contract\_runs, schedule\_override, drivers, dispatchers
- method

    - String
    - Valid values:

        POST, PUT, GET, DELETE
- queryParams

    - Associative array
    - keys:

        - include / exclude:

            Indexed array of resources to retrieve / ignore from the end point. Include will be favored if both are provided. If omitted all resources are returned. Ex:

            Return only ticket number, billed client, and ticket price.

            ```
            $data['queryParams']['include'] = [ 'TicketNumber', 'BillTo', 'TicketPrice' ];
            ```

            Return all resources **except** pick up country.

            ```
            $data['queryParams']['exclude'] = [ 'pCountry' ];
            ```
        - filter:

            - simple "and" query:

                Indexed array of associative arrays. Ex:

                Select tickets with charge equal to 5 and billed to clients other than client 1.

                ```
                $data['queryParams']['filter'] = [];

                $data['queryParams']['filter'][] = ['Resource'=>'Charge', 'Filter'=>'eq', 'Value'=>5];

                $data['queryParams']['filter'][] = ['Resource'=>'BillTo', 'Filter'=>'neq', 'Value'=>1];
                ```
            - complex "and" &amp; "or" query:

                Indexed array of simple "and" queries. Ex:

                Select tickets with charge between 1 and 5 and billed to client 1 or tickets billed to client 2.

                ```
                $filter1 = [];

                $filter1[] = ['Resource'=>'Charge', 'Filter'=>'bt', 'Value'=>'1,5'];

                $filter1[] = ['Resource'=>'BillTo', 'Filter'=>'eq', 'Value'=>1];

                $filter2 = [ ['Resource'=>'BillTo', 'Filter'=>'eq', 'Value'=>2] ];

                $data['queryParams']['filter'] = [$filter1, $filter2];
                ```
            - available filters:

                - cs: contain string (string contains value)
                - sw: start with (string starts with value)
                - ew: end with (string end with value)
                - eq: equal (string or number matches exactly)
                - lt: lower than (number is lower than value)
                - le: lower or equal (number is lower than or equal to value)
                - ge: greater or equal (number is higher than or equal to value)
                - gt: greater than (number is higher than value)
                - bt: between (number is between two comma separated values)
                - in: in (number is in comma separated list of values)
                - is: is null (field contains "NULL" value)
                - You can negate all filters by prepending a 'n' character, so that 'eq' becomes 'neq'.
        - order

            Indexed array of ordering parameters. With the "order" parameter you can sort. By default the sort is in ascending order, but by specifying "desc" this can be reversed. Ex:

            ```
            $data['queryParams']['order'] = ['DispatchTimeStamp,desc'];
            ```

            or

            ```
            $data['queryParams']['order'] = ['BillTo', 'DispatchTimeStamp,desc'];
            ```
        - page

            - string
            - The "page" parameter holds the requested page. The default page size is 20, but can be adjusted (e.g. to 50). Pages that are not ordered cannot be paginated. EX:

            ```
            $data['queryParams']['page'] = '1';
            ```

            or

            ```
            $data['queryParams']['page'] = '1,50';
            ```
        - join

            - Indexed array of tables to join via Foreign Key Constraint.

            ```
              $data['endPoint'] = 'clients';
              $data['method'] = 'get';
              $data['queryParams']['filter'][] = ['Resource'=>'ClientID', 'Filter'=>'eq', 'Value'=>0];
              $data['queryParams']['join'] = [ 'config' ];
            ```

            This query will return the client with all resources plus an extra resource named 'config' with all of the resources from that end point.

            If the filter were left off all clients would have the extra resource however, it would only be populated for Client 0.

            - Joins currently available:

                - Client 0 to config
                - Invoice to tickets
                - Contract run to contract locations
                - Contract run to contract run schedule
                - Contract run to schedule override
                - Route to route schedule
                - Route to schedule override
                - Route to route tickets

Public Methods
--------------

[](#public-methods-2)

```
$query->buildURI();
```

Processes the queryParams property into a query string then returns itself so that it can be chained with the call method.

```
$query->call();
```

Uses the cURL library to execute the query string. Returns the result of the query or throws Exception on error. Ex:

```
try {
  $query->buildURI()->call();
} catch (Exception $e) {
  return $e->getMessage();
}
```

---

LoginHandler
============

[](#loginhandler)

Extends [CommonFunctions](https://github.com/rjdeliveryomaha/courierinvoice#commonfunctions)

Processes login credentials.

Populates `$_SESSION` with user data.

Returns string; either '/clients' or '/drivers'.

Throws exception on error.

Usage
-----

[](#usage-2)

```
try {
  $handler = new LoginHandler($config, $data);
} catch(Exception $e) {
  return $e->getMessage();
}
```

Properties settable in $data:
-----------------------------

[](#properties-settable-in-data-2)

- clientID

    Users login name.

    - Repeat clients: Integer. ClientID.
    - Non-repeat clients: String. ClientID preceded by the letter 't'. `t1`
    - Organizations: String. `orgLogin`
    - Drivers: String. DriverID preceded by the word 'driver'. `driver1`
    - Dispatchers: String. DispatchID preceded by the word 'dispatch'. `dispatch23`
- upw

    Users password.

Public Methods
--------------

[](#public-methods-3)

```
try {
  $type = $handler->login();
} catch(Exception $e) {
  echo $e->getMessage();
  return false;
}
echo $type;
return false;
```

Sets the following session values:

```
$_SESSION['config']
```

This associative array contains resources from the [config](https://rjdeliveryomaha.com/courierinvoice/apidoc#config) endpoint as well as all Client 0 resources except `Password`, `AdminPassword`, and `Deleted`.

```
$_SESSION['mobile']
```

If `true` this Boolean value indicates that the user logged in from a portal located at ../mobileLogin that passed the LoginHandler class a dataset that included the key "mobile" and will redirect there instead of / upon log out.

```
$_SESSION['ulevel']
```

Describes the type of user logged in:

- 0: Organization
- 1: Admin Client
- 2: Daily Client
- driver
- dispatch

All resources from the end point corresponding to the client, organization, driver, or dispatcher except `Deleted` and passwords.

Dispatchers have `$_SESSION['CanDispatch']` set to a value of 2.

Clients, Dispatchers, and Drivers with dispatch privileges have `$_SESSION['config']['ContractDiscount']` and `$_SESSION['config']['GeneralDiscount']` set. These are associative arrays with keys being Client IDs (preceded with the letter 't' for non-repeat clients) and the values being the discount values for each (or current) client.

Clients and organizations will have `$_SESSION['pwWarning']` set.

Integer

- 0: password did not match the default password for the login type.
- 1: daily client password is default
- 2: admin client password is default
- 3: both daily and admin clients are default
- 4: organization password is default

These values are used to notify the user that the password should be changed.

Organizations have `$_SESSION['members']` set. This is an associative array with the keys being client IDs (preceded by the letter 't' for non-repeat clients) and the values being an associative array containing the data stored at the clients end point for each client associated with the organization.

---

Ticket
======

[](#ticket)

Extends [CommonFunctions](https://github.com/rjdeliveryomaha/courierinvoice#commonfunctions)

Processes and displays tickets individually or batched

Usage:
------

[](#usage-3)

```
try {
  $ticket = new Ticket($config, $data);
} catch(Exception $e) {
  return $e->getMessage();
}
```

Properties settable in $data:
-----------------------------

[](#properties-settable-in-data-3)

A list of standard properties can be found in the [API Documentation](https://www.rjdeliveryomaha.com/courierinvoice/apidoc#tickets)

The `step` property is used by `$ticket->updateStep()`.

The `action` property is used by `$ticket->cancelTicket()`.

The special property `multiTicket` can contain an array of ticket data sets for batch creation or updating. Ex: Update two tickets; one is being delivered the other returned to the same address.

```
$data['multiTicket'] = [
  [
    'ticket_index': 1,
    'step': 'delivered',
    'notes': 'This ticket was delivered'
  ],
  [
    'ticket_index': 2,
    'step': 'returned'
  ]
]
```

Public Methods:
---------------

[](#public-methods-4)

```
echo $ticket->regenTicket();
```

Display single ticket for client review or for dispatch.

If coordinates are available for pick up, delivery, or return step the will be displayed in a span with the class coordinates.

```
echo $ticket->displaySingleTicket();
```

Display single ticket for drivers.

Addresses are displayed as `a.addressLink` that by default will open Google Maps searching the address in a new window.

```
echo $ticket->displayMultiTicket();
```

Display groups of tickets with common pick up or drop off location and time.

Addresses are displayed as `a.addressLink` that by default will open Google Maps searching the address in a new window.

```
echo $ticket->ticketsToDispatch();
```

Check database for tickets that have not been dispatched.

```
echo $ticket->ticketForm();
```

Has 4 states based on $data passed to Ticket.

1 initial: Generates an empty ticket entry form.

This form is followed by `` for use with a javascript map api.

This div is only generated on this step.

2 edit: Generates a ticket entry form populated with provided `$data`.

3 confirmation: Generates a read-only form for validation.

TicketPrice is solved here.

4 process: Submit ticket to the server.

TicketNumber is set here.

```
echo $ticket->runPriceForm();
```

Generates a simplified ticket form that only accepts 2 addresses, charge, and dry ice weight.

The data from this form should be passed to `$ticket->calculateRunPrice()`.

This form is followed by `` for use with a javascript map api.

```
echo $ticket->calculateRunPrice();
```

**Note**: The private method `self::getTicketBase()` is called here as well as when creating on call tickets and contract tickets that have a `PriceOverride` value of 0. This method uses [geocoder-php](https://github.com/geocoder-php/Geocoder) to get the coordinates of the pick up and delivery locations. It expects that the properties `$ticket->pAddress2` and `$ticket->dAddress2` will be in the format *Locality/City, State/Province Zip/Postal Code*. This format is important as the function tests the value between the first comma and the final whitespace in the string (the one prior to Zip/Postal Code) against values returned by the geocoder to determine if accurate data has been received.

Returns a json encoded array with the following properties:

- billTo: ClientID.
- address1: Pick up address.
- address2: Delivery address.
- result1: Coordinates of address1.
- result2: Coordinates of address2.
- center: Coordinates of mid-point between result1 and result2.
- pRangeTest: The distance between address1 and RangeCenter.
- dRangeTest: The distance between address2 and RangeCenter.
- rangeDisplay: The distance between address1 and address2.
- runPrice: The calculated price without dry ice.
- ticketPrice: The calculated price with dry ice.
- diWeight: The weight of dry ice provided for the calculation.
- diPrice: The calculated price of dry ice.

```
echo $ticket->fetchTodaysTickets();
```

Checks for tickets for a given client on the current date.

Returns the results of `$ticket->regenTicket()` for each ticket found, false if none exist.

```
$ticket->processRouteTicket();
```

**Note**: This does not display a map when calculating TicketPrice. Consult [geocoder providers](https://github.com/geocoder-php/Geocoder#providers) for limitations.

Process tickets generated by the Route class:

- Sets TicketNumber
- Solves TicketPrice or uses the resource stored at the contract\_runs end point if PriceOverride is `true`
- Submits tickets
- Updates LastCompleted date at the contract\_runs end point

Returns true on success, false, and optionally logs an error, on failure.

```
$ticket->processReturnTicket();
```

Processes and submits a change of charge from 5 to 6 using the value stored in TicketBase.

```
echo $ticket->updateTicketProperty();
```

Updates values in `$ticket->updateTicketDatabaseKeys` if provided.

```
$ticket->updateTicketDatabaseKeys = ['BillTo',
                                     'Charge',
                                     'EmailAddress',
                                     'EmailConfirm',
                                     'Telephone',
                                     'RequestedBy',
                                     'pClient',
                                     'pAddress1',
                                     'pAddress2',
                                     'pCountry',
                                     'pContact',
                                     'pTelephone',
                                     'dClient',
                                     'dAddress1',
                                     'dAddress2',
                                     'dCountry',
                                     'dContact',
                                     'dTelephone',
                                     'dryIce',
                                     'diWeight',
                                     'diPrice',
                                     'DispatchedTo',
                                     'Transfers',
                                     'TicketBase',
                                     'RunPrice',
                                     'TicketPrice',
                                     'Notes',
                                     'pSigReq',
                                     'dSigReq',
                                     'd2SigReq',
                                     'pLat',
                                     'pLng',
                                     'dLat',
                                     'dLng',
                                     'd2Lat',
                                     'd2Lng'
                                   ];
```

```
echo $ticket->stepTicket();
```

Sets the time stamp and submits that, notes and other values for the given `step` for a single ticket or multiTicket array.

Sends confirmation email if indicated.

Returns a string on success and error.

On error the string will contain the word 'error'.

Valid values:

- 'pickedUp'

    Checks for `$ticket->sigImage`

    Checks for `$ticket->latitude` and `$ticket->longitude`

    Submits pSigPrint, pSig, pSigType, pLat, and pLng
- 'delivered'

    Checks for `$ticket->sigImage`

    Checks for `$ticket->latitude` and `$ticket->longitude`

    Submits dSigPrint, dSig, dSigType, dLat, and dLng

    Solves for TicketPrice is Charge is 7 and d2SigReq is 0.
- 'returned'

    Checks for `$ticket->sigImage`

    Checks for `$ticket->latitude` and `$ticket->longitude`

    Submits d2SigPrint, d2Sig, d2SigType, d2Lat, and d2Lng

    Solves for TicketPrice if Charge is 7 and d2SigReq is 1.
- 'dispatched'

    Sets DispatchTimeStamp, DispatchMicroTime, DispatchedTo, and DispatchedBy.

```
echo $ticket->cancelTicket();
```

Processes the given `action` for a single ticket or multiTicket array.

Valid values:

- 'delete'

    The API uses a 'soft delete' method.

    The ticket will not be removed from the database. Instead the Charge will be set to 0.
- 'cancel'

    The tickets Charge will be set to 0.
- 'deadRun'

    The tickets Charge will be set to 8.
- 'declined'

    Only available on the delivery step.

    The tickets Charge will be set 6 and the TicketPrice recalculated.
- 'transfer'

    The tickets TransferState will be updated.

---

Route
=====

[](#route)

Extends [CommonFunctions](https://github.com/rjdeliveryomaha/courierinvoice#commonfunctions)

Creates contract tickets for a driver as defined on the Manage Runs page.

Checks for and displays contract tickets.

Updates LastSeen resource.

Checks for and displays on call tickets.

Checks for and displays transferred tickets.

Usage:
------

[](#usage-4)

```
try {
  $route = new Route($config, $data);
} catch(Exception $e) {
  echo $e->getMessage();
  return FALSE;
}
```

Properties settable in $data:
-----------------------------

[](#properties-settable-in-data-4)

All properties of this class are set by the session.

Public Methods:
---------------

[](#public-methods-5)

```
$route->routeTickets();
```

Checks drivers LastSeen resource. If it is not the current date a call is made to check for cancelations and rescheduling then tickets defined on the Manage Runs page are created. The LastSeen resource is then updated.

**Note**: The above order is overriding. Canceling a run on a given date supersedes rescheduling that run to the same date. Rescheduling a run supersedes its date, pick up time, delivery time, and return time defined on the Manage Runs page.

A call is made to fetch incomplete routine and round trip contract tickets. If this result is empty a call is made to check if any contract tickets were created for the driver on the current day.

Multiple tickets with the same location and scheduled step time will be grouped together.

Soft delete (setting the 'Deleted' property to 1) of contract runs, contract run schedules, rescheduling events, cancelations, and route schedules is respected.

Soft delete of contract locations that are associated with active contract runs is not respected.

A `span.timing` element is added to each `div.sortable` for use by javascript to order tickets based on their `ReadyDate` and `step`.

Returns HTML content.

```
$route->onCallTickets();
```

Checks for incomplete on call tickets that have been dispatched to the current driver in the past 7 days.

Returns HTML content.

```
$route->transferredTickets();
```

Checks for tickets that have been transferred to or by the current driver.

Returns HTML content.

---

Scheduling
==========

[](#scheduling)

Static Class with tools for interpreting scheduling codes, literals, and indices.

Public methods
--------------

[](#public-methods-6)

```
Scheduling::codeFromIndex($index);
```

Returns the schedule code (\[a-g\]\[1-9\] or h5 - h28) associated with a given schedule\_index (1-87).

```
Scheduling::literalFromIndex($index);
```

Returns the schedule literal (Every Day, Every Last Thursday, Every 22nd) associated with a given schedule\_index (1-87).

```
Scheduling::indexFromCode($code);
```

Returns the schedule\_index (1-87) associated with a given schedule code (\[a-g\]\[1-9\] or h5 - h28).

```
Scheduling::literalFromCode($code);
```

Returns the schedule literal (Every Day, Every Last Thursday, Every 22nd) associated with a schedule code (\[a-g\]\[1-9\] or h5 - h28).

```
Scheduling::indexFromLiteral($literal);
```

Returns the schedule\_index (1-87) associated with a given schedule literal (Every Day, Every Last Thursday, Every 22nd).

```
Scheduling::codeFromLiteral($literal);
```

Returns the schedule code (\[a-g\]\[1-9\] or h5 - h28) associated with a given schedule literal (Every Day, Every Last Thursday, Every 22nd).

```
Scheduling::testIndex($index, $startDate, $testDate);
Scheduling::testCode($code, $startDate, $testDate);
Scheduling::testLiteral($literal, $startDate, $testDate);
```

Compares two `DateTime` objects to determine if the scheduled interval has elapsed.

Returns `boolean`.

**Note**: For 'Every Other' schedules with day names, if the start date does not land on the named day, perhaps because the schedule changed, the date will be tested against the day of the scheduled name in the same Sunday through Saturday week as the start date.

For example if an Every Other Saturday schedule starting on 01 JUL 2017 were changed to an Every Other Tuesday schedule the current date would be tested against the Tuesday in the same week as 01 JUL 2017 which is 27 JUN 2017.

---

Invoice
=======

[](#invoice)

Extends [CommonFunctions](https://github.com/rjdeliveryomaha/courierinvoice#commonfunctions)

Displays invoices for review.

By default canceled thickets are not displayed. This behavior can be adjusted on a per client basis in the config file located at [extras/includes](https://github.com/rjdeliveryomaha/courierinvoice/tree/master/extras/includes).

By default contract tickets are consolidated by run number. This behavior can be adjusted on a per client basis in the config file located at [extras/includes](https://github.com/rjdeliveryomaha/courierinvoice/tree/master/extras/includes).

Usage:
------

[](#usage-5)

```
try {
  $invoice = new Invoice($config, $data);
} catch(Exception $e) {
  echo $e->getMessage();
  return FALSE;
}
```

Properties settable in $data:
-----------------------------

[](#properties-settable-in-data-5)

A list of standard properties can be found in the [API Documentation](https://www.rjdeliveryomaha.com/courierinvoice/apidoc#invoices)

The `invoiceQueryResult` property is an indexed array of invoice datasets used for receiving data from the [SearchHandler](https://github.com/rjdeliveryomaha/courierinvoice#searchHandler) class.

Public Methods:
---------------

[](#public-methods-7)

```
$invoice->regenInvoice();
```

Uses the data provided in `invoiceQueryResult` to display an invoice.

If [dompdf](https://github.com/dompdf/dompdf) is detected a button will be added to display/download the invoice as a pdf.

If multiple datasets are provided a form will be returned to select which invoice to recreate by invoice number.

Soft delete (setting the 'Deleted' property to 1) will result in a discreet message being displayed at the top of the invoice indicating that it has been flagged for deletion.

```
$invoice->invoiceQueryForm();
```

Creates a query form for admin and organization clients. The parameters provided by this form are processed by the [SearchHandler](https://github.com/rjdeliveryomaha/courierinvoice#searchHandler) class.

---

SearchHandler
=============

[](#searchhandler)

Extends [CommonFunctions](https://github.com/rjdeliveryomaha/courierinvoice#commonfunctions)

Accepts input from ticket and invoice query forms.

Returns html result of datasets processed by those respective classes.

Usage:
------

[](#usage-6)

```
try {
  $handler = new SearchHandler($config, $data);
} catch (Exception $e) {
  echo $e->getMessage();
  return false;
}
```

Properties settable in $data:
-----------------------------

[](#properties-settable-in-data-6)

- ticketNumber

    Used by the `ticketLookup()` method.
- endPoint

    - tickets
    - invoices
- display

    - tickets: displays the result of `$ticket->regenTicket()` for each ticket matching query parameters.
    - invoice: displays the result of `$invoice->regenInvoice()` for the matching invoice.
    - chart: displays a bar graph generated by either the [TicketChart](https://github.com/rjdeliveryomaha/courierinvoice#ticketchart) or [InvoiceChart](https://github.com/rjdeliveryomaha/courierinvoice#invoicechart) class.
- compare

    When a chart query is made that spans multiple months the default behavior is to display each month in the query. Setting this value to 1 will compare the first and last month of the query parameters.
- compareMembers

    When a chart query is made that includes multiple members of an organization the default behavior is to display charts for each member. Setting this value to 1 will compare members in a query set.
- clientID

    Client associated with an invoice.
- billTo

    Client associated with a ticket.
- repeatClient

    - 0: non-repeat client
    - 1: repeat client
- startDate

    Lower date boundary for a query. Format YYYY-mm-dd.
- endDate

    Upper boundary for a query. Format YYYY-mm-dd.
- invoiceNumber

    Specific invoice to query for a client.

    Expected formats:

    - \##EX####-## regex: `/(^[\d]{2}EX[\d]+-[\d]+$)/`
    - \##EX####-t## regex: `/(^[\d]{2}EX[\d]+-t[\d]+$)/`
- dateIssued

    Month to query for invoices for a given client. Format YYYY-mm.
- ticketNumber

    Specific ticket to query for a given client.
- charge

    Specific ticket charge to query for a given client.

    Values from 0 - 9.
- type

    Type of ticket to query for a given client.

    - 2: All
    - 1: Contract
    - 0: On Call
- allTime

    Default 0. If set to 1:

    - If display is "tickets" all tickets from account creation to current date will be displayed.
    - If display is "chart" data will be displayed for the period between the current date and the pervious `allTimeChartLimit` months.

Public Methods:
---------------

[](#public-methods-8)

` $handler->ticketLookup() ;`

Uses a ticket number to get ticket timing information.

Returns a JSON encoded string.

The object will have the property `queryError` if there was a problem with the query or if the tickets `Charge` property is 0 (canceled).

If no error and `Charge` does not equal 0 the object will have the following properties:

- Charge

    Integer

    The values of the `Charge` property for the queried ticket.
- pTimeStamp

    String

    The values of the `pTimeStamp` property for the queried ticket in the format `d M Y \a\t h:i A` or "Pending" if the value is `NULL`.
- dTimeStamp

    String

    The values of the `dTimeStamp` property for the queried ticket in the format `d M Y \a\t h:i A` or "Pending" if the value is `NULL`.
- d2TimeStamp

    String

    The values of the `d2TimeStamp` property for the queried ticket in the format `d M Y \a\t h:i A`, "Pending" if the value is `NULL` or "Not Scheduled" if `Charge` is not 6 or if `Charge` is 7 but `d2SigReq` is not 1.

`$handler->handleSearch();`

Returns the html content generated by the indicated class; Ticket, Invoice, TicketChart, or InvoiceChart.

---

TicketChart
===========

[](#ticketchart)

Extends [CommonFunctions](https://github.com/rjdeliveryomaha/courierinvoice#commonfunctions)

Receives a dataset of tickets grouped by month from the [SearchHandler](https://github.com/rjdeliveryomaha/courierinvoice#searchHandler) class.

Displays a table containing the number of each type of ticket over a given period.

Displays a simple bar chart depicting the number of each type of ticket over a given period.

Contract and On Call are always displayed.

With Ice and Without Ice are always displayed.

All other values are only displayed if they are not zero.

[example](extras/example_images/ticketChartExample.png?raw=true "Example of ticket chart.")

If [dompdf](https://github.com/dompdf/dompdf) is detected a button will be added to display/download the chart as a pdf.

Properties settable in $config can be found [here](https://github.com/rjdeliveryomaha/courierinvoice/tree/master/extras/includes#chart_height)

Usage:
------

[](#usage-7)

```
try {
  $ticketChart = new TicketChart($config, $data);
} catch(Exception $e) {
  echo $e->getMessage();
  return FALSE;
}
```

Properties settable in $data:
-----------------------------

[](#properties-settable-in-data-7)

- dataSet

    Associative array of data sorted by month.

    `$monthLabel` is the `ReceivedDate` of a ticket in the format 'M Y'.

    ```
    $this->months[$monthLabel][$ticket['BillTo']] = [
                                                     'billTo'=>$ticket['BillTo'],
                                                     'monthTotal'=>1,
                                                     'contract'=>0,
                                                     'credit'=>0,
                                                     'canceled'=>0,
                                                     'onCall'=>0,
                                                     'routine'=>0,
                                                     'fourHour'=>0,
                                                     'threeHour'=>0,
                                                     'twoHour'=>0,
                                                     'oneHour'=>0,
                                                     'roundTrip'=>0,
                                                     'deadRun'=>0,
                                                     'dedicatedRun'=>0,
                                                     'withIce'=>0,
                                                     'withoutIce'=>0,
                                                     'startDate'=>$receivedDate->format('Y-m-d'),
                                                     'endDate'=>$receivedDate->format('Y-m-d')
                                                   ];
    ```
- organizationFlag

    Boolean

    Indicates if the query if for an organization (`true`) or an individual client (`false`)
- clientID

    Array or Integer

    If `organizationFlag` is `true` this is an indexed array of members to be queried.

    If `organizationFlag` is `false` this is the ID of the current client.
- compare

    Boolean

    Indicates if dataset is two months compared or a series of months.
- compareMembers

    Boolean

    Indicates if members are being compared of displayed separately.

Public Methods:
---------------

[](#public-methods-9)

```
$chart = $ticketChart->displayChart();

if ($chart === false) {
  echo $ticketChart->getError();
} else {
  echo $chart;
}
```

Returns html content or `false` on error.

---

InvoiceChart
============

[](#invoicechart)

Extends [CommonFunctions](https://github.com/rjdeliveryomaha/courierinvoice#commonfunctions)

Receives a dataset of tickets grouped by month from the [SearchHandler](https://github.com/rjdeliveryomaha/courierinvoice#searchHandler) class.

Displays a table containing the expense of each type of ticket over a given period.

Displays a simple bar chart depicting the expense of each type of ticket over a given period.

Only non-zero values are displayed.

[example](extras/example_images/invoiceChartExample.png?raw=true "Example of invoice chart.")

If [dompdf](https://github.com/dompdf/dompdf) is detected a button will be added to display/download the chart as a pdf.

Properties settable in $config can be found [here](https://github.com/rjdeliveryomaha/courierinvoice/tree/master/extras/includes#chart_height)

Usage:
------

[](#usage-8)

```
try {
  $invoiceChart = new InvoiceChart($config, $data);
} catch(Exception $e) {
  echo $e->getMessage();
  return FALSE;
}
```

Properties settable in $data:
-----------------------------

[](#properties-settable-in-data-8)

- dataSet

    Associative array of data sorted by month.

    `$invoiceLabel` is the `DateIssued` of an invoice in the format 'M Y'.

```
$this->months[$invoiceLabel] = [
                                'invoices'=>[0 => $invoice['InvoiceNumber']],
                                'billTo'=>$invoice['ClientID'],
                                'monthTotal'=>$invoice['InvoiceSubTotal'] - $invoice['BalanceForwarded'],
                                'contract'=>0,
                                'credit'=>0,
                                'canceled'=>0,
                                'onCall'=>0,
                                'routine'=>0,
                                'fourHour'=>0,
                                'threeHour'=>0,
                                'twoHour'=>0,
                                'oneHour'=>0,
                                'roundTrip'=>0,
                                'deadRun'=>0,
                                'dedicatedRun'=>0,
                                'dryIce'=>0,
                                'iceDelivery'=>0,
                               ];
```

- organizationFlag

Boolean

Indicates if the query if for an organization (`true`) or an individual client (`false`)

- clientID

Array or Integer

If `organizationFlag` is `true` this is an indexed array of members to be queried.

If `organizationFlag` is `false` this is the ID of the current client.

- compare

Boolean

Indicates if dataset is two months compared or a series of months.

- compareMembers

Boolean

Indicates if members are being compared of displayed separately.

Public Methods:
---------------

[](#public-methods-10)

```
$chart = $invoiceChart->displayChart();

if ($chart === false) {
  echo $invoiceChart->getError();
} else {
  echo $chart;
}
```

Returns html content or `false` on error.

---

Client
======

[](#client)

Extends [CommonFunctions](https://github.com/rjdeliveryomaha/courierinvoice#commonfunctions)

Manages information for clients, drivers, and dispatchers.

Usage:
------

[](#usage-9)

```
try {
  $client = new Client($config, $data);
} catch(Exception $e) {
  echo $e->getMessage();
  return FALSE;
}
```

Properties settable in $data:
-----------------------------

[](#properties-settable-in-data-9)

A list of standard properties can be found in the [API Documentation](https://www.rjdeliveryomaha.com/courierinvoice/apidoc#clients)

- same

    Indicates that a clients billing information is identical to their shipping information.
- currentPw

    The current password of the user to be change.
- newPw1

    The new password.
- newPw2

    Confirmation of the new password.

Public methods:
---------------

[](#public-methods-11)

```
$client->getAllClientInfo();
```

Returns array of client information.

```
$client->changePassword();
```

`echo`s message and returns `false` on error.

Requires current password to be submitted.

Validates submitted current password against database stored hash.

Tests that newPw1 meets criteria

- At least 8 characters long.
- At least one upper case letter. A..Z
- At least one lower case letter. a..z
- At least one number. 0..9
- At least one special character. ! @ # $ % ^ &amp; \* ( ) { } \[ \] - \_ . : ; , = +

Compares newPw1 and newPw2 for confirmation.

Ensures that admin and daily user passwords do not match.

Hashes the new password using PASSWORD\_DEFAULT algorithm and a cost of 12.

```
$client->updateInfo();
```

`echo`s message and returns `false` on error.

If `$client->same` is equal to 1 billing information is set equal to shipping information.

Phone numbers are validated `preg_match('/(\d{3})-(\d{3})-(\d{4})x(\d+)/i', $val) || preg_match('/(\d{3})-(\d{3})-(\d{4})/', $val);`. These patters are slated for update.

```
$client->adminPasswordForm();
```

Returns a password update form with admin user values set.

```
$client->dailyPasswordForm();
```

Returns a password update form with daily user values set.

```
$client->orgPasswordForm();
```

Returns a password update form with organization user values set.

```
$client->driverPasswordForm();
```

Returns a password update form with driver values set.

```
$client->dispatchPasswordForm();
```

Returns a password update form with dispatch values set.

```
$client->updateInfoForm();
```

Only available to admin user level.

Returns an contact information update form.

---

InvoiceCron
===========

[](#invoicecron)

Extends [CommonFunctions](https://github.com/rjdeliveryomaha/courierinvoice#commonfunctions)

Automatically creates invoices with a [cron](https://en.wikipedia.org/wiki/Cron) job run on the day following the end of a monthly billing cycle.

Updates tickets with new invoice number.

Can be configured to ignore clients and non-repeat clients.

Checks for past due invoices according to the terms defined per invoice.

Respects soft delete (setting the 'Deleted' property to 1) when checking for past due invoices.

Usage:
------

[](#usage-10)

```
  require_once '../includes/api_config.php';
  require_once '../vendor/autoload.php';

  use rjdeliveryomaha\courierinvoice\InvoiceCron;

  try {
    $cron = new InvoiceCron($config);
  } catch(Exception $e) {
    // log $e->getMessage();
    exit;
  }

  try {
    $cron->createInvoices();
  } catch(Exception $e) {
    // log $e->getMessage();
    exit;
  }
  exit;
```

---

extras
======

[](#extras)

This is an extendable drop-in implementation of this set of classes using vanilla javascript.

Functionality is enclosed in a global variable: `rjdci`.

The [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API#Browser_compatibility) is used extensively and a template is provided. This will retry a call failing due to network issues 20 times waiting `n * 250` milliseconds between calls where n is the retry count. If a `FormData` instance is sent the headers `Content-Type` and `Content-Length` will be tested for and removed to prevent conflicts. If the postData property is not empty and the `Content-Type` header is set as `www-form-urlencoded` the post body will be encoded. If the Content-Type header is not defined and the postData property has a length greater than 0 the Content-Type will be set to "application/json". As a result the PHP `$_POST` super global is not populated; data must be read from the stream.

Ex:

```
  if (empty($_POST)) $_POST = json_decode(file_get_contents('php://input'),true);
```

```
  rjdci.fetch_template = async ({ url, method = "POST", headers = {}, postData = {}, retry = 0 }) => {
    if (!url) throw new Error("URL not defined");
    let fetchOptions = {
        method: method.toUpperCase(),
        headers: headers
      };
    if (postData instanceof FormData || Object.keys(postData).length > 0) {
      let body;
      if (postData instanceof FormData) {
        body = postData;
        fetchOptions.headers["Content-Type"] &&
        delete fetchOptions.headers["Content-Type"];
        fetchOptions.headers["Content-Length"] &&
        delete fetchOptions.headers["Content-Length"];
      } else if (fetchOptions.headers["Content-Type"].indexOf("x-www-form-urlencoded") != -1) {
        body = Object.entries(postData).map(([key, value]) =>
          `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&");
      } else {
        body = JSON.stringify(postData);
        if (!headers.hasOwnProperty("Content-Type")) {
          fetchOptions.headers["Content-Type"] = "application/json";
        }
      }
      fetchOptions.method = "POST";
      fetchOptions.body = body;
    }
    try {
      return await fetch(url, fetchOptions);
    } catch(err) {
      retry++;
      if (retry === 20) throw err;
      await rjdci.pause(250 * retry)
      return await rjdci.fetch_template({
        url: url,
        method: method,
        headers: headers,
        postData: postData,
        retry: retry
      });
    }
  }
```

The `rjdci.pause` function is setTimeout turned into a promise.

```
  rjdci.pause = duration => { return new Promise(resolve => setTimeout(resolve, duration)) };
```

Usage:

```
  // example taken from rjdci.refreshRoute()
  let postData =  { "formKey": document.querySelector("#formKey").value };
  await rjdci.fetch_templet({ url: "./refreshRoute.php", postData: postData })
  .then(result => {
    if (typeof result === "undefined") throw new Error("Result Undefined");
    if (result.ok) {
      return result.text();
    } else {
      throw new Error(result.status + " " + result.statusText);
    }
  })
  .then(data => {
    if (data.indexOf("error") !== -1) throw new Error(data);
    let parser = new DOMParser(),
      newDom = parser.parseFromString(data, "text/html"),
      docFrag = document.createDocumentFragment();
    Array.from(newDom.querySelectorAll(".sortable")).forEach(element => {
      docFrag.appendChild(element);
    });
    setTimeout(() => {
      document.querySelector("#route").appendChild(docFrag);
      rjdci.assignListeners();
      rjdci.fixDeadRunButton();
      sortRoute();
    }, 2000);
  })
  .then(rjdci.refreshFormKey)
  .catch(error => {
    document.querySelector("#route").innerHTML = 'Error: ' + error.message + "";
  });
```

A place holder for a map function is provided and should be redefined if a map api is implemented.

```
  rjdci.updateMap = ({ coords1, address1, coords2, address2, center, mapDivID }) => { return false; }
```

[Signature Pad v2.3.2](https://github.com/szimek/signature_pad) is preconfigured with [extras/public\_html/app\_js/sigPad.js](https://github.com/rjdeliveryomaha/courierinvoice/tree/master/extras/public_html/app_js/sigPad.js) to collect signatures in conjunction with the functions `$ticket->displaySingleTicket()` and `$ticket->displayMultiTicket()`.

The method `rjdci.toast(msg, options)` is available. It creates and deletes a toast-like div to show messages to the user.

Usage:

```
  let options = {},
      msg = "Test Message"; // or ['Test Message'] or [ 'Multi-line', 'Test Message' ];
  options.title = "sample div title"; // title attribute of toast div. default ""
  options.time = 3000; // milliseconds to show toast div. div will be removed 1 second after it is hidden. default 4000
  options.eleClass = "ticketOncallReceived"; // custom class for the toast div. The function will display only the newest of a custom class, removing previous messages. All default class divs will be displayed for the configured time. default "toast__msg"
  options.datatime = 1512574797926; // unix time stamp to parse for display with message. default new Date().getTime();
  rjdci.toast(msg, options);
```

The method `rjdci.getSpinner()` can be called to return a copy of the loading icon.

### Features

[](#features)

Uses ticket information from database to populate datalist elements to assist form completion.

Single page design navigated by either swipe or menu. Offers unique features based upon user type. Once each page has been loaded a window event `rjdci_loaded` is triggered.

[Swipe](https://github.com/lyfeyaj/swipe) is used for navigation. [Public methods](https://github.com/lyfeyaj/swipe#api) can be accessed via the `rjdci.Swipe` instance.

At the end of the transition between pages `scroll(0,0)` is called and a window event `rjdci_pageChange` is triggered.

Setting the order of menu items as well as adding custom menu items (with or without matching pages), and javascript files is handled in the config file located at [extras/includes](https://github.com/rjdeliveryomaha/courierinvoice/tree/master/extras/includes).

### Drivers

[](#drivers)

If the user agent supports both the [permissions](https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API) and [geolocation](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API) APIs an attempt will be made to get the coordinates when a ticket is picked up, delivered, returned, declined, or marked as a dead run. The above described function `rjdci.toast` is used to create notifications with the class `deliveryLocation` to inform the user of the status of updating the delivery location.

- Route

    - Uses Route class to create or fetch contract tickets for a given driver.
    - Groups tickets with matching location and time.
    - Displays single and grouped tickets with ability to:

        - collect signatures
        - update step
        - update notes
        - cancel
        - mark as dead run
        - transfer
    - Can be independently refreshed.

        - CustomEvent `rjdci_refreshed` with `e.detail.type() = "route"`
            is dispatched when the refresh is completed.
- On Call

    - Uses Route class to fetch on call tickets for a given driver.
    - Displays single tickets with ability to:

        - collect signatures
        - update step
        - update notes
        - cancel
        - mark as dead run
        - transfer
    - Can be independently refreshed.

        - CustomEvent `rjdci_refreshed` with `e.detail.type() = "oncall"`
            is dispatched when the refresh is completed.
- Transfers

    - Uses Route class to fetch tickets either transferred by or transferred to a given driver.
    - Groups contract tickets with matching location and time.
    - Displays single and grouped tickets with ability to:

        - accept transfer
        - decline transfer
        - cancel transfer
    - Can be independently refreshed.

        - CustomEvent `rjdci_refreshed` with `e.detail.type() = "transfers"`
            is dispatched when the refresh is completed.
- Ticket Entry and Dispatch page for drivers with dispatch privileges. Described below.
- Active Tickets page for drivers with dispatch privileges. Described below.
- Change Password

    - Provides a simple form to update the password

### Dispatchers

[](#dispatchers)

- Dispatch

    - Uses Ticket class to check for tickets that have not been dispatched.
    - Displays single tickets with ability to dispatch.
    - Can be independently refreshed.

        - CustomEvent `rjdci_refreshed` with `e.detail.type() = "dispatch"`
            is dispatched when the refresh is completed.
- Price Calculator

    - Compact ticket form
    - Accepts only pick up address, delivery address, charge, and dry ice information
    - Uses Ticket class to compute the price of a ticket
    - `` available to display a map
- Active Tickets

    - Query contract or on call tickets for a given driver
    - Displays single tickets with ability to edit
- Ticket Entry

    - Form to submit tickets to the API
    - `` available to display a map
    - Can be independently refreshed.

        - CustomEvent `rjdci_refreshed` with `e.detail.type() = "ticketEntry"`
            is dispatched when the refresh is completed.
- Change Password

    - Provides a simple form to update the password

### Clients

[](#clients)

- Admin User

    - Delivery request form

        - Form to submit tickets to the API
    - Ticket Query

        - Can search tickets by ticket number or by date
        - Displays either individual tickets or a bar graph depicting ticket volume
        - Bar graph can cover a range of months (maximum can be configured) or compare two months
        - Ticket charges available to be queried can be configured separately for admin and daily users
    - Invoice Query

        - Can search invoices by invoice number or by date
        - Displays either individual invoices or bar graph depicting expenses
        - Bar graph can cover a range of months (maximum can be configured) or compare two months
    - Password management

        - Update password for either admin or daily users
        - Warns to change from default password
    - Contact information management
    - Price Calculator
- Daily User

    - Delivery request form
    - Ticket Query
    - Price Calculator

### Organizations

[](#organizations)

- Price Calculator
- Ticket Query

    - Can search ticket by ticket number or by date
    - Can search by individual member or by groups of members
    - Displays either individual tickets or bar graph depicting ticket volume
    - Bar graph can cover a range of months (maximum can be configured) or compare two months
- Invoice Query

    - Can search invoices by invoice number or by date
    - Can search by individual member or by groups of members
    - Displays either individual invoices or bar graph depicting expenses
    - Bar graph can cover a range of months (maximum can be configured) or compare two months
- Password management

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance78

Regular maintenance activity

Popularity8

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity70

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~44 days

Recently: every ~177 days

Total

61

Last Release

51d ago

Major Versions

1.7.0 → 2.0.02019-11-07

2.7.7 → v3.0.0.x-dev2026-03-22

### Community

Maintainers

![](https://www.gravatar.com/avatar/c6144999ab6fa4f65e47c002a5f835e78843305840a5f8b9d9817f877e36474d?d=identicon)[resident0](/maintainers/resident0)

---

Top Contributors

[![resident0](https://avatars.githubusercontent.com/u/9022010?v=4)](https://github.com/resident0 "resident0 (617 commits)")

---

Tags

courier invoice

### Embed Badge

![Health badge](/badges/rjdeliveryomaha-courierinvoice/health.svg)

```
[![Health](https://phpackages.com/badges/rjdeliveryomaha-courierinvoice/health.svg)](https://phpackages.com/packages/rjdeliveryomaha-courierinvoice)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[tencentcloud/tencentcloud-sdk-php

TencentCloudApi php sdk

3731.2M42](/packages/tencentcloud-tencentcloud-sdk-php)[convertkit/convertkitapi

Kit PHP SDK for the Kit API

2167.1k1](/packages/convertkit-convertkitapi)[mapado/rest-client-sdk

Rest Client SDK for hydra API

1125.9k2](/packages/mapado-rest-client-sdk)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
