Bewerbungsaufgabe von Marco Kittel 2025
Vorraussetzungen
Docker und Docker Compose, Posix Compatibles System und Golang >= 1.24
CsvService
Starte mit ./starteCsvService Zum Test einfach mal Testdaten in den New Folder bei laufendem Betrieb schieben
Web Api
Benötigt Datenbank Starten mit ./starteDatenbank Starten mit./starteWebservice
Produkte abrufen
curl -X POST localhost:8080/api/products -d '{ "products": { "A6053": 2, "B3009": 1200 }, "context": { "country": "EU", "state": "" } }'
Reservierung reservieren
curl -X POST localhost:8080/api/products/reserve -d '{ "products": { "A6053": 2, "B3009": 1200 }, "context": { "country": "EU", "state": "" } }'
Reservierung bestätigen
curl -X POST localhost:8080/api/products/confirm -d '{"id":"ab0d7184-a4ce-4802-897a-d8597335143a"}'
Reservierung abbrechen
curl -X POST localhost:8080/api/products/abort -d '{"id":"ab0d7184-a4ce-4802-897a-d8597335143a"}'
Reservierung freigeben
curl -X POST localhost:8080/api/products/release -d '{"id":"ab0d7184-a4ce-4802-897a-d8597335143a"}'
Abschlussbesprechung der Aufgabe
Aufgabe
Organisational requirements
Objective
Application Requirements
Task 1
Task 2 - Stock Import
Task 3 - Cross Country / State Delivery Times
Task 4 - Stock and Delivery Time API
Task 5 - Reservation API
Automatic Release Order Handling Target
Organisational requirements Share all your work with us by using a git-based version control platform like github.com or gitlab.com in private mode, so we can see your development progress and test your final results. Please always use the e-mail address for sharing code.
Objective Our customer is a global operator of online shops, with a presence spanning across numerous countries worldwide. They have established country-specific online shops tailored to serve the unique needs of customers in Germany, Austria, and Switzerland. Additionally, they operate expansive, nation-wide shops dedicated to serving customers across all other European Union countries, the United States, and the rest of the world.
This global reach is supported by an extensive network of warehouses, strategically located in several countries. These warehouses not only ensure efficient and effective distribution of products, but also contribute to a streamlined shopping experience for customers, regardless of their location.
For every product our customer sells, there exists a specific quantity available in each of their warehouses. However, the availability of these products can vary significantly; while some warehouses may hold a substantial stock of a particular product, others may have a limited quantity, or may not have the product in stock at all. One warehouse may provide products to several online shops.
The warehouses generate csv files that contain the information about the available stock per product. Right now each e-commerce application must process all of the given stock information individually. The stock information files generated by each warehouse are sent to all shops and are processed there. Each shop is holding its own copy of the stock information. This is causing the problem that false stocks and delivery times are advertise. E.g. both the Germany and Switzerland shop knows that we have x items present in the EU warehouse, if two customers are buying the same products in two individual shops we oversell the item.
To avoid this we want to introduce one central instance that processes the stock information and is asked by the shop instances via api about the currently available stock. This application should be written in golang.
Application Requirements The application must be written in golang
In case additional services (databases, message brokers, …) are used a docker-compose.yml must be provided.
A readme with instructions about how to run this project must be given
A documentation about how to use the api must be given (can be in readme, api spec, postman collection, …)
The import files used to test the application must be provided in the request
The approx duration for the implementation should be one day
Task 1 Before you start, please create a free account at https://gitlab.com/ and create a new repository there. You will share later the repository containing the source code with us.
Task 2 - Stock Import We maintain detailed knowledge of the specific products and their current stock levels in each of our warehouses. Each warehouse is operating their own database that holds that information. There is no centralized database that contains the stock per product and warehouse. The software used by each warehouse cannot be modified and only allows file exports.
Each warehouse is generating every hour a csv file with the current stocks. This csv file is synced with a centralized storage. Only full updates are supported, which means that each file generated every hour contains all products. The estimated size will be 700.000 products / lines per file.
Our application must read these csv files and import them into a local database.
Our application that we need to develop will read csv files from the local filesystem. There will be one directory where all files are saved in. We do not need to care about the centralized storage.
The filename created by each warehouse has the following structure Time[RFC-3339, ISO_8601]-WarehouseId-stock.csv
Examples:
$ ls -a | sort 2023-11-09T15:02:17+00:00-CH-stock.csv 2023-11-09T16:01:14+00:00-CH-stock.csv 2023-11-09T16:03:02+00:00-DE-stock.csv 2023-11-09T16:03:17+00:00-AT-stock.csv 2023-11-09T16:04:44+00:00-EU-stock.csv Text Copy In case there are multiple files from one warehouse present the latest file must be processed.
Files are always full exports.
The file contains the product id which is a string and the currently available quantity of this product in the warehouse that generated the export file.
product_id;quantity A1000;50 B3009;80 A8771;158
The file must be processed by our application. The contents must be saved in a database that we later use to query the currently available stocks. It is sufficient to save the WarehouseId, ProductId and the Quantity in our database. The data model you choose here is up to you.
Files that have been processed must be moved to another directory. For simplification we do not care about cleanup or failed imports.
├── new │ ├── 2023-11-09T16:03:17+00:00-AT-stock.csv │ └── 2023-11-09T16:04:44+00:00-EU-stock.csv └── processed ├── 2023-11-09T15:02:17+00:00-CH-stock.csv ├── 2023-11-09T16:01:14+00:00-CH-stock.csv └── 2023-11-09T16:03:02+00:00-DE-stock.csv Text Copy Target The target of task 1 is that our go application searches for new csv files in a predefined directory. Files are processed and the contents saved in our database.
Task 3 - Cross Country / State Delivery Times We have precise data on the average delivery time from each warehouse to every eligible country and state it serves. This information is provided via csv export that is generated by each warehouse. The exports are saved on the same centralized storage as in task 2. Files will be saved in the same directory.
As an example: We have a warehouse in Germany - in case one product is not available we can fallback to the european warehouse to serve the customer from there, but we cannot fallback to our US warehouse.
Our application that we need to develop will read csv files from the local filesystem. There will be one directory where all files are saved in.
├── new │ ├── 2023-11-09T16:00:10+00:00-CH-delivery.csv │ ├── 2023-11-09T16:00:20+00:00-DE-delivery.csv │ ├── 2023-11-09T16:00:37+00:00-EU-delivery.csv │ ├── 2023-11-09T16:01:56+00:00-AT-delivery.csv │ ├── 2023-11-09T16:03:17+00:00-AT-stock.csv │ └── 2023-11-09T16:04:44+00:00-EU-stock.csv └── processed ├── 2023-11-09T15:02:17+00:00-CH-stock.csv ├── 2023-11-09T16:01:14+00:00-CH-stock.csv └── 2023-11-09T16:03:02+00:00-DE-stock.csv Text Copy The delivery time files will be saved in the same directory as the stock files processed in task 2.
The filename created by each warehouse has the following structure Time[RFC-3339, ISO_8601]-WarehouseId-delivery.csv
$ ls -a | sort 2023-11-09T16:00:10+00:00-CH-delivery.csv 2023-11-09T16:00:20+00:00-DE-delivery.csv 2023-11-09T16:00:37+00:00-EU-delivery.csv 2023-11-09T16:01:56+00:00-AT-delivery.csv Text Copy In case there are multiple files from one warehouse present the latest file must be processed.
Files are always full exports.
The file contains the country iso, the state and the average delivery time in days regardless of the product.
// 2023-11-09T16:00:10+00:00-CH-delivery.csv country;state;delivery_time CH;;3 DE;BW;4
The here show file is generated by the swiss warehouse. The average delivery time in switzerland (CH) are 3 days. Nevertheless products can also be delivery to germany, but only to Baden Württemberg which will take 4 days. If a state is specified it means that we only delivery to this specific stage. All countries that are not present or all states that are not present are not served by this warehouse. If the state is not given, it means that we serve the whole country. Depending in the location of the warehouse it can be possible that for some states the delivery time is lower than for the remaining country. Due to that we can have an entry for the whole country and entries for the country and a state in the same file.
The file must be processed by our application. The contents must be saved in a database that we later need to query the currently delivery times.
Files that have been processed must be moved to another directory. For simplification we do not care about cleanup or failed imports.
Target The provided files are processed, the contents are stored in our database.
Task 4 - Stock and Delivery Time API The online shops the customer operates for each country and region are isolated. This means that their databased and the knowledge about the current stock and delivery times are not saved in a centralized database. Each shop must process the aforementioned file imports individually which is causing a high load on every system every hour. Furthermore as each shop is using its own source of truth more products than available can be sold or even wrong delivery times can be advertised.
We now want to remove the processing of the stock and delivery time imports in all online shop applications and replace that with an api call to our golang application. The result of your api call is displayed in the shipping cart. There we display per product the calculated delivery times and the available stocks.
For that we must provide a new api endpoint which is consumed by the online shops applications. For simplicity we do not care about authentication.
The api endpoint must accept the following parameters:
Product-IDs + Quantity: We submit the products for that we would like to know the current instock and delivery times.
Customer Country: As the delivery times depend on the country we submit this as part of our context
Customer State: As the delivery times may depend on the state we submit this as part of our context
{ "products": { "A1000": 20, "B3009": 1200 }, "context": { "country": "DE", "state": "BY" } } Jav CopyThe result of this api call should contain the product numbers that we submitted in the request and per product the information about the available stock in each warehouse that is required. The warehouses should be picked depending on the available stock and the lowest delivery time. If we for example can server the products from DE and EU warehouse, we pick the one with the lowest delivery time first and fill up the remaining quantities.
{ "products": { "A1000": [ {"warehouse": "DE", "quantity": "5", "delivery_time": 1}, {"warehouse": "EU", "quantity": "15", "delivery_time": 8} ], "B3009": [ {"warehouse": "DE", "quantity": "110", "delivery_time": 1} ] } }
As a result we receive per product the information about the possible quantities and the delivery times.
Target We have an api endpoint that accepts the aforementioned payload
Calculate the delivery times based in the previously imported data
Respond with the above shown result
No auth is required
Task 5 - Reservation API After implementing the stock api the customer is facing less problems with wrong stocks or delivery times, but the problem still exists for a small number of customers.
To prevent this we want to introduce a reserve, confirm and release api endpoint.
Reserve
The reservation api is called by the online shops during the checkout process. If the customer is navigating to the last checkout step before payment the online shop calls the reserve api endpoint. The payload will be exactly the same as for the stock and delivery time api.
{ "products": { "A1000": 20, "B3009": 1200 }, "context": { "country": "DE", "state": "BY" } }
The reservation will perform a stock and delivery time lookup and will reserve the stock in each required warehouse.
Our api must respond like before with the available stocks and the possible delivery times. Now we receive in addition a reservation id. This id can be used to confirm and release the reservation.
{ "id": "59e57f14-be24-43c4-8a8e-4c22f5f2154e", "products": { "A1000": [ {"warehouse": "DE", "quantity": "5", "delivery_time": 1}, {"warehouse": "EU", "quantity": "15", "delivery_time": 8} ], "B3009": [ {"warehouse": "DE", "quantity": "110", "delivery_time": 1} ] } }
Abort
In case the customer does not finish the checkout process in one of the online shops, the online shop calls the abort api endpoint. This removes the previously created reservation.
The following payload is submitted to this endpoint:
{ "id": "59e57f14-be24-43c4-8a8e-4c22f5f2154e" }
As there is no result in this api call our response will be 204 no content.
Confirm
In case the customer finishes the checkout and payment process the online shop will now call the confirm api endpoint including the previously given reservation id. After this request the information about the reserved stock stays permanently in our database.
{ "id": "59e57f14-be24-43c4-8a8e-4c22f5f2154e" }
As there is no result in this api call our response will be 204 no content.
Automatic Release In case the reservation is not released or confirmed within one day our application must automatically remove the reserved stock from the database.
Order Handling The online shops submit the orders to a centralized order management system. The online shops include the information provided by our reserve api endpoint. The order management system will now deliver the products based on the information our api provides. This prevents that more products than available are sold or wrong delivery times are shown.
If the order management system is processing the orders, stocks in the warehouses are changed. We receive the new stock information with the next file export. To release the reserved stock the order management system will call an api endpoint of our application (release api). The payload includes the reservation id that we created during the reservation.
{ "id": "59e57f14-be24-43c4-8a8e-4c22f5f2154e" }
As there is no result in this api call our response will be 204 no content.
Target Create 4 api endpoints (reserve, abort, confirm, release)
The reservation should block a specific amount in specific warehouses
All further api calls to our stock and delivery time api or the reserve api must use this information