Complete name: Back to the Future in the Grocery Store Kata
This kata is about managing a special grocery store inventory. The task is to keep track of fruits and vegetables, organize and sort them, but with a twistβwe need to manage the inventory over time!
Every method in this kata requires a date parameter to indicate when the changes should take effect.
Your job is to create a system that can accept changes to the inventory at any date, and then allow us to see the state of the inventory at any given date.
In each iteration, there will be examples. Let's use these variables for all of them:
const yesterday = new Date("2024-11-14");
const today = new Date("2024-11-15");
const tomorrow = new Date("2024-11-16");
const future = new Date("2025-01-01");
β οΈ The signatures of the methods in the examples might be questionable. You might come up with better interfaces, use IDs for things that doesn't have in the example, wharever you want.
User Should Be Able To (USBAT from now on): Add products to the inventory
inventory.add(today, "π");
inventory.add(today, "π₯");
inventory.add(tomorrow, "π");
inventory.project(yesterday); // <empty>
inventory.project(today); // ππ₯
inventory.project(tomorrow); // ππ₯πUSBAT: Remove previously added products
inventory.add(today, "π");
inventory.add(today, "π₯");
inventory.remove(tomorrow, "π");
inventory.project(yesterday); // <empty>
inventory.project(today); // ππ₯
inventory.project(tomorrow); // π₯USBAT: Create groups of products
- If there is a group, the string representation should include "|"
- If products are separated from each other, the group must be created where the first product is located.
- Groups cannot be empty
- If you start removing elements from a group, the group must disappear
- You can only create groups of elements that are present at that moment
Simple example:
inventory.add(today, "π");
inventory.add(today, "π₯");
inventory.add(today, "π");
inventory.add(today, "π");
inventory.project(future); // ππ₯ππ
inventory.group(tomorrow, ["π₯", "π"]);
inventory.project(future); // π|π₯π|πExample with products separated from each other:
inventory.add(today, "π");
inventory.add(today, "π₯");
inventory.add(today, "π");
inventory.add(today, "π");
inventory.project(future); // ππ₯ππ
inventory.group(tomorrow, ["π", "π"]);
inventory.project(future); // |ππ|π₯πExample with temporal complications:
inventory.add(today, "π");
inventory.add(today, "π₯");
inventory.add(today, "π");
inventory.add(today, "π");
inventory.project(future); // ππ₯ππ
inventory.group(tomorrow, ["π", "π"]);
inventory.project(future); // |ππ|π₯π
inventory.remove(today, "π"); // we are removing an item today, but the group was created tomorrow
inventory.project(future); // |π|π₯π
inventory.remove(today, "π");
inventory.project(future); // π₯πSo far, we have been managing the inventory from a time perspective at a "global" level, without specifying any particular country. However, each country can have its own overrides. Generally, there will only be a few changes for specific countries, while the main management will still be at the global level.
inventory.add({ date: today }, "π"); // Global
inventory.add({ date: today }, "π₯"); // Global
inventory.add({ date: tomorrow, country: "spain" }, "π"); // Specific to Spain
inventory.add({ date: tomorrow, country: "uk" }, "π"); // Specific to the UK
inventory.project({ date: future }); // ππ₯
inventory.project({ date: future, country: "spain" }); // ππ₯π
inventory.project({ date: future, country: "uk" }); // ππ₯πEnsure that all previous scenarios continue to work. We should be able to add/remove products, create groups, and move items at any time at any scope level.
USBAT: Move products and groups in the inventory
- Both groups and products can be moved at the "root" level of the inventory
- Only products can be moved inside groups
inventory.add({date: today}, "π");
inventory.add({date: today}, "π₯");
inventory.add({date: today}, "π");
inventory.add({date: today}, "π");
inventory.group({date: today}, ["π", "π"]);
inventory.project({date: future}); // |ππ|π₯π
inventory.move({date: today}, "π₯", 0); // Move kiwi to index 0
inventory.project({date: future}); // π₯|ππ|π
inventory.move({date: today}, "π₯", 1); // Move kiwi to index 1
inventory.project({date: future}); // |ππ₯π|π