Aufgabe zur Task hinzugefügt :-)
This commit is contained in:
parent
586159a56d
commit
72df26d58e
403
readme.md
403
readme.md
@ -1,5 +1,6 @@
|
||||
# Bewerbungsaufgabe von Marco Kittel 2025
|
||||
# Vorraussetzungen
|
||||
|
||||
Docker und Docker Compose, Posix Compatibles System und Golang >= 1.24
|
||||
|
||||
# CsvService
|
||||
@ -30,3 +31,405 @@ Starten mit./starteWebservice
|
||||
|
||||
# Abschlussbesprechung der Aufgabe
|
||||
[Abschlussbesprechnung](https://www.youtube.com/watch?v=psz58bMyeMM)
|
||||
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user