-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
817 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
**/procuret.js | ||
**/procuret.js | ||
.DS_Store | ||
**/test.html | ||
*.pyc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,205 @@ | ||
# Procuret JavaScript Library | ||
# Introduction | ||
|
||
This library provides JavaScript types for interacting with the Procuret | ||
API. | ||
Procuret API JavaScript (PJS) allows you to perform Procuret API operations in | ||
JavaScript code. Its only dependency is a "typical" browser-like environment. | ||
That is, it must run in an environment that has browser-like APIs available, | ||
such as `XMLHTTPRequest`. | ||
|
||
PJS is provided as raw JavaScript files which you can manually package as you | ||
see fit. For example, you might copy and paste relevant files for your use | ||
case and include them in your software. You can also use included Python tools | ||
to package PJS for include in HTML documents or for provision via a web server. | ||
(See "Packaging Tools" below.) | ||
|
||
Tests are provided for verification of functionality. | ||
|
||
## Versioning and public interfaces | ||
|
||
PJS follows [Semantic Versioning](https://semver.org) conventions. At any time, | ||
the repository may included an undocumented type in the `source` directory. | ||
These types should be considered unavailable and their function is not | ||
guaranteed. | ||
|
||
# Available Types | ||
|
||
## `PR_ProspectivePayment` | ||
|
||
A theoretical payment amount, and the number of months over which that payment | ||
would be made, if an applicant successfully applied for a Procuret Instalment | ||
Plan. | ||
|
||
### Properties | ||
|
||
- `.periods` - `Number` - The number of months over which payment would be made | ||
- `.amount` - `PR_Amount` - The monthly payment amount | ||
- `.supplierId` - `String` - The ID of the Procuret supplier for which this | ||
price is valid. | ||
|
||
### Static Methods | ||
|
||
#### .retrieve | ||
|
||
Retrieve a single `PR_ProspectivePayment` for given parameters. To use this | ||
method, you must know a valid `months` value in advance. If you don't know | ||
a valid `months` value in advance, prefer `.retrieveAllAvailable`. | ||
|
||
##### Parameters | ||
|
||
1. `callback` - `Function<Error?, PR_ProspectivePayment?>` - A function taking | ||
optional error and result parameters, in which you can handle the API response. | ||
2. `principal` - `String` - A string-encoded number representing the principal | ||
value of the prospective loan. For example, a total invoice value. Minimum | ||
value `500` currency units. | ||
3. `supplierId` - `String` - Your Supplier ID. Consult your Procuret | ||
partnership manager if you are unsure of this value. | ||
4. `denomination` - `PR_Currency` - The monetary denomination of the `principal` | ||
value. | ||
5. `months` - `Number` - The integer number of months over which the instalment | ||
plan would be paid. | ||
6. `endpoint` - `Optional<String>` - Optionally override the API endpoint. | ||
Useful in testing a demonstration environments. | ||
7. [undocumented, do not use, do not provide a value] | ||
|
||
##### Example Usage | ||
|
||
```javascript | ||
PR_ProspectivePayment.retrieve( | ||
(error, prospectivePayment) => { | ||
|
||
if (error) { console.log('An error occurred'); return; } | ||
|
||
console.log('A successful applicant would pay \ | ||
' + payment.amount.asDenominatedString + ' per month'); | ||
|
||
return; | ||
|
||
}, | ||
"600", // $600 | ||
"511291212", // some Supplier ID | ||
PR_Currency.AUD, // Australian dollars | ||
12 // 12 months | ||
); | ||
``` | ||
|
||
#### .retrieveAllAvailable | ||
|
||
Retrieve all available `PR_ProspectivePayment` for given parameters. This is | ||
a convenient way to display all potential instalment plan payment amounts to | ||
a potential applicant. | ||
|
||
##### Parameters | ||
|
||
1. `callback` - `Function<Error?, PR_ProspectivePayment?>` - A function taking | ||
optional error and result parameters, in which you can handle the API response. | ||
2. `principal` - `String` - A string-encoded number representing the principal | ||
value of the prospective loan. For example, a total invoice value. Minimum | ||
value `500` currency units. | ||
3. `denomination` - `PR_Currency` - The monetary denomination of the `principal` | ||
value. | ||
4. `supplierId` - `String` - Your Supplier ID. Consult your Procuret | ||
partnership manager if you are unsure of this value. | ||
5. `endpoint` - `Optional<String>` - Optionally override the API endpoint. | ||
Useful in testing a demonstration environments. | ||
6. [undocumented, do not use, do not provide a value] | ||
|
||
##### Example Usage | ||
|
||
```javascript | ||
PR_ProspectivePayment.retrieveAllAvailable( | ||
(error, availablePayments) => { | ||
|
||
if (error) { console.log('An error occurred'); return; } | ||
|
||
const availablePayments = payments.map((p) => { | ||
return p.amount.asDenominatedString | ||
}); | ||
|
||
console.log('Applicants may choose from the following payments \ | ||
' + availablePayments); | ||
|
||
return; | ||
|
||
}, | ||
"600", // $600 | ||
PR_Currency.AUD, // Australian dollars | ||
"511291212", // some Supplier ID | ||
12 // 12 months | ||
); | ||
``` | ||
--- | ||
## `PR_Currency` | ||
|
||
A unit of monetary denomination | ||
|
||
### Properties | ||
|
||
- `iso_4217` - `String` - The ISO 4217 code of this currency | ||
- `symbol` - `String` - The common-use symbol for this currency | ||
- `exponent` - `Number` - The integer exponent of the currency's subunits | ||
- `name` - `String` - The full-form name of this currency | ||
- `indexid` - `Number` - A unique integer identifier for the currency in the | ||
Procure context | ||
|
||
### Static Properties | ||
|
||
- `.AUD` - `PR_Currency` - Australian dollars | ||
- `.NZD` - `PR_Currency` - New Zealand dollars | ||
- `.allAvailable` - `Array<PR_Currency>` - All available currencies | ||
|
||
--- | ||
## `PR_Amount` | ||
|
||
A monetary amount, a combination of magnitude and currency denomination | ||
|
||
### Properties | ||
|
||
- `asNumber` - `Number` - The amount magnitude cast to a JavaScript `Number` | ||
- `asLocaleString` - `String` - A Locale-defined string representation | ||
- `asSymbolisedString` - `String` - The amount prefixed by its currency symbol | ||
- `asDenominatedString` - `String` - The amount prefixed by its ISO 4217 code | ||
- `magnitude` - `String` - The undenominated magnitude of the amount | ||
- `denomination` - `PR_Currency` - The denomination of the amount | ||
- `isGreaterThanZero` - `Boolean` - `true` if the magnitude of the amount is | ||
greater than zero, else `false` | ||
|
||
|
||
# Packaging Tools | ||
|
||
PJS includes built in Python tools for packaging. To compile the entire PJS | ||
library into a single JavaScript file, invoke the following Python commands | ||
from the `tools` directory: | ||
|
||
```bash | ||
$ cd tools | ||
$ python3 compile.py | ||
``` | ||
|
||
A `procuret.js` file will appear in the `tools` directory. | ||
|
||
# Running Tests | ||
|
||
PJS includes a built in test GUI. To run the tests, first compile the test | ||
tool: | ||
|
||
```bash | ||
$ cd tools | ||
$ python3 compile_tests.py | ||
``` | ||
|
||
A `test.html` document will appear in the `tools` directory. Serve `test.html` | ||
from a web server, and then interact with the tool via a web browser. For | ||
example, you can locally serve the tools directory using... | ||
|
||
```bash | ||
$ python3 -m http.server | ||
``` | ||
|
||
... Whereupon the test tool is available at http://127.0.0.1:8000/test.html. | ||
|
||
Note that you cannot open `test.html` in your browser from the file system | ||
with a modern security-standards-compliant browser. All tests will fail due to browser's Cross-Origin-Resource-Sharing requirements being unmet. | ||
|
||
# Get Help | ||
|
||
To get help integrating PJS into your software, write to your Procuret | ||
partnership manager, or write to our team at [email protected]. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
0.0.3 | ||
1.0.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* Procuret API JS - Amount JS Class */ | ||
|
||
|
||
class PR_Amount { | ||
|
||
constructor( | ||
magnitude, // String decimal number e.g. "4,000" or "4000" | ||
currency // PR_Currency | ||
) { | ||
|
||
if (!currency) { throw Error('Cannot init w/ falsey PR_Currency'); } | ||
|
||
this._magnitude = magnitude; | ||
this._currency = currency; | ||
|
||
return; | ||
} | ||
|
||
get asNumber() { return new Number(this._magnitude); } | ||
get asLocaleString() { | ||
return this.asNumber.toLocaleString(undefined, { | ||
minimumFractionDigits: this._currency.exponent | ||
}); | ||
} | ||
get asSymbolisedString() { | ||
return this._currency.symbol + this.asLocaleString; | ||
} | ||
get asDenominatedString() { | ||
return this._currency.iso_4217 + ' ' + this.asLocaleString; | ||
} | ||
|
||
get magnitude() { return this._magnitude; } | ||
get denomination() { return this._currency; } | ||
|
||
get isGreaterThanZero() { return Number(this._magnitude) > 0; } | ||
|
||
rounded(decimalPlaces) { | ||
return new PR_Amount( | ||
Number(this._magnitude).toFixed(decimalPlaces), | ||
this._currency | ||
); | ||
} | ||
|
||
magnitudeIsGreaterThan(value) { | ||
return Number(this._magnitude) > value; | ||
} | ||
|
||
encode() { | ||
return { | ||
'magnitude': this._magnitude, | ||
'denomination': this._currency.indexid | ||
} | ||
} | ||
|
||
static decode(data) { | ||
return new PR_Amount( | ||
data['magnitude'], | ||
PR_Currency.decode(data['denomination']) | ||
); | ||
} | ||
|
||
static optionallyDecode(data) { // -> Optional<Self> | ||
if (!data) { return null; } | ||
return PR_Amount.decode(data); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* Procuret JS - API error class */ | ||
|
||
const PR_ERROR_INFO_KEY = 'error-information'; | ||
const PR_ERROR_CUSTOMER_INFORMATION = { | ||
400: "Procuret's servers could not understand the information sent by \ | ||
your device. This likely indicates a bug in our application. Our support \ | ||
team has been notified automatically, but please feel free to contact \ | ||
us at [email protected]", | ||
500: "Procuret's servers encountered an error when processing information \ | ||
sent by your device. There may be a bug in our systems, or they may be \ | ||
experiencing a temporary service disruption. Our support team has been \ | ||
notified automatically.", | ||
503: "Procuret's servers encountered a service disruption while processing \ | ||
your request. This error may disappear if you try again in a few moments. \ | ||
Our support team has been notified automatically. If this error persists, \ | ||
please write to us at [email protected].", | ||
401: "Procuret's servers could not identify you when processing \ | ||
data sent by your device. This likely indicates a bug has crept into \ | ||
our application. Please contact us at [email protected].", | ||
403: "You don't appear to be authorised to perform the action you \ | ||
were attempting. This likely indicates a bug has crept into \ | ||
our application. Please contact us at [email protected].", | ||
429: "Procuret's servers have noticed unusually high activity levels \ | ||
from your device or the network it is connected to. Please try again in \ | ||
few minutes. If you continue to see this message, please contact \ | ||
[email protected]", | ||
404: "Procuret's servers were unable to find a resource needed to \ | ||
serve your request. This likely indicates a bug in our application. Our \ | ||
support team has been notified automatically, but please feel free to \ | ||
contact us at [email protected]", | ||
422: "Procuret was unable to process your request, due to a problem with \ | ||
the information sent by your device." | ||
} | ||
const PR_ERROR_FALLBACK_INFORMATION = "Procuret has encountered an error. There \ | ||
may be a bug in our systems, or they may be experiencing a temporary \ | ||
disruption. We will \ | ||
attempt to resolve the problem as quickly as possible"; | ||
|
||
class PR_ApiError extends Error { | ||
|
||
static get genericDescription() { return PR_ERROR_FALLBACK_INFORMATION; } | ||
|
||
constructor( | ||
code, // Integer | ||
data=null, // Optional<Object> | ||
requestSummary=null // Optional<Object> (Untyped) | ||
) { | ||
|
||
const description = PR_ERROR_CUSTOMER_INFORMATION[code]; | ||
let techInfo = (() => { | ||
if (code != 0) { return 'Generic ' + String(code); } | ||
return 'Client side error'; | ||
})(); | ||
if ( | ||
typeof(data) != 'undefined' | ||
&& data != null | ||
&& data[PR_ERROR_INFO_KEY] | ||
) { | ||
techInfo = data[PR_ERROR_INFO_KEY]; | ||
} | ||
const logMessage = 'API error (' + code + '), ' + techInfo; | ||
super(logMessage); | ||
|
||
const self = this; | ||
|
||
self._code = code; | ||
self._customerDescription = description | ||
|| PR_ERROR_FALLBACK_INFORMATION; | ||
self._technicalDescription = techInfo; | ||
self._requestSummary = requestSummary; | ||
|
||
return | ||
|
||
} | ||
|
||
get code() { return this._code } | ||
get customerDescription() { return this._customerDescription } | ||
get technicalDescription() { return this._technicalDescription } | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.