3.3 KiB
MyFreight Assessment
How to run
Easiest way to run this project is using docker compose:
docker compose up
It is possible that this will give some database connection issues on the first try, but after a couple of seconds, it should automatically reconnect.
Alternatively, it is possible to use your own mysql database, and run the code locally:
- Import the
database/entrypoint/init.sqlinto your own database - Update the
.envfile with the database credentials - Run
npm cito install all npm packages - Run
npm run buildto build the nestjs application - Run
npm run start:prodto start the nestjs application
After starting the application will run on http://localhost:3000/
Documentation
The full endpoint documentation can be found on http://localhost:3000/api. Here you can find which endpoints there are, and how to authenticate.
Authentication
For the Authentication I went with an base64 encoded authentication string consisting of 2 parts. The first part is the ApiKey, which is stored in the authentication database. The second part is a secret that is being used as a password.
In the database we have stored 2 values, the ApiKey and a digest. This digest is creating by using HMAC with the api secret as password, using a sha256 to hash the ApiKey.
This way there is no full api key stored in the database.
Demo example
In this demo you can use eG5nVnZGaWtCMFN6NjRRaWQ2TUJsUTJWaDpjeGg1R3FKRUl0UTlzSGRQdElGMGg0bFJp for the requests.
This decodes to xngVvFikB0Sz64Qid6MBlQ2Vh:cxh5GqJEItQ9sHdPtIF0h4lRi.
The first part xngVvFikB0Sz64Qid6MBlQ2Vh is stored in the database, but the second part is not stored anywhere.
Receiving Tracking information
When receiving Tracking information, the following steps need to be completed to process the data
flowchart TD
receiveTracking(["Receive Tracking"])
findContainerAndShipment["SELECT container JOIN Shipment"]
updateShipment[/Update shipment\]
isArrivingSoon{{"Is arrival estimate between now and now + 24h?"}}
hasArrived{{"Is arrival estimate <=now?"}}
isDelayed{{Is arrival estimate > original arrival + 24h?}}
sendNotification[/Send notification\]
receiveTracking -- "`**Tracking data**
carrierName:**string**
destinationUnLoCode:**string**
departureDate:**string[_datetime_]**
arrivalDateEstimate:**string[_datetime_]**
containerNumber:**string**
`" --> findContainerAndShipment
findContainerAndShipment --> |WHERE containers.containerNumber = :trackingData.containerNumber| updateShipment
updateShipment --> isArrivingSoon & hasArrived & isDelayed
isDelayed -->|set delayed flag| sendNotification
hasArrived --> |set has arrived flag| sendNotification
isArrivingSoon -->|set is arriving soon flag| sendNotification
%% isArrivingSoon -->|yes| sendArriveSoon
Possible improvements
- Sending the actual notification, there should be a more general way to setup notifiers
- Moving some variables to config files
- when is a shipment "arriving soon"
- mock date
- Use the uuid package
- was not possible since the uuid's from the sample data were invalid uuid's
- Add end-to-end tests as well
- Get shipments should be paginated
- Could use a package like typeorm-crud
- Cleanup duplicate OpenApi decorators, perhaps consolidate them in a custom decorator