{"id":26949714,"url":"https://github.com/connormaglynn/shopping-cart-typescript","last_synced_at":"2026-04-10T11:32:47.442Z","repository":{"id":144556108,"uuid":"562450740","full_name":"connormaglynn/shopping-cart-typescript","owner":"connormaglynn","description":"This repository is managed in Terraform","archived":false,"fork":false,"pushed_at":"2023-01-31T20:28:13.000Z","size":211,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-03T14:09:54.361Z","etag":null,"topics":["eslint","jest","npm","prettier","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/connormaglynn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-11-06T12:04:38.000Z","updated_at":"2023-12-31T14:57:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"a30b07ab-acc5-4f9b-84d1-b3371d455977","html_url":"https://github.com/connormaglynn/shopping-cart-typescript","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":"connormaglynn/typescript-template","purl":"pkg:github/connormaglynn/shopping-cart-typescript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/connormaglynn%2Fshopping-cart-typescript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/connormaglynn%2Fshopping-cart-typescript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/connormaglynn%2Fshopping-cart-typescript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/connormaglynn%2Fshopping-cart-typescript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/connormaglynn","download_url":"https://codeload.github.com/connormaglynn/shopping-cart-typescript/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/connormaglynn%2Fshopping-cart-typescript/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31641114,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-10T07:40:12.752Z","status":"ssl_error","status_checked_at":"2026-04-10T07:40:11.664Z","response_time":98,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["eslint","jest","npm","prettier","typescript"],"created_at":"2025-04-02T22:17:24.647Z","updated_at":"2026-04-10T11:32:47.435Z","avatar_url":"https://github.com/connormaglynn.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge\u0026logo=typescript\u0026logoColor=white)\n![Jest](https://img.shields.io/badge/Jest-323330?style=for-the-badge\u0026logo=Jest\u0026logoColor=white)\n![ESLINT](https://img.shields.io/badge/eslint-3A33D1?style=for-the-badge\u0026logo=eslint\u0026logoColor=white)\n![Prettier](https://img.shields.io/badge/prettier-1A2C34?style=for-the-badge\u0026logo=prettier\u0026logoColor=F7BA3E)\n\n# shopping-cart-typescript\n\nShopping Cart Scenario For a Senior Developer Interview. Written in Typescript.\n\n## Shopping Cart Checkout Scenario\n\n[Original Scenario File](assets/Supermarket.pdf)\n\n### Problem Description\n\nIn our quest to stay in touch with what's going on in the commercial world we've\ndecided to open a supermarket - we sell only three products:\n\n| Product code | Name         | Price  |\n|--------------|--------------|--------|\n| FR1          | Fruit Tea    | £3.11  |\n| SR1          | Strawberries | £5.00  |\n| CF1          | Coffee       | £11.23 |\n\nOur CEO is a big fan of buy-one-get-one-free offers. She wants us to add a rule to\napply this rule to fruit tea.\n\nThe COO, though, likes low prices and wants people buying strawberries to get a\nprice discount for bulk purchases. If you buy 3 or more strawberries, the price should\ndrop to £4.50 each.\n\nOur checkout can scan items in any order.\n\nThe CEO and COO change their minds often, so ideally this should be a flexible\nsolution (if you have time). For example, we might want to apply the offers to\ndifferent products, or add products to our range, as the supermarket grows.\n\n### Task\n\nYour goal is to implement a checkout that scans items in and calculates total prices\ncorrectly for any combination of the products and offers above.\n\nAfter your interview, you’ll be asked to talk through your code, and share your screen\nto demonstrate it. Don’t worry about using databases or a front end.\nPlease don’t spend more than an hour or two on this. An incomplete solution is ok,\nwe can talk through how you’d extend your solution at the interview. Thank you, and\ngood luck!\n\n---\n\n## 🙋 My Approach\n\n### 💡 Initial Ideas\n\nTo complete the above task, I think it is best to define a single (and simple) purpose for the application and start\nthere.\n\nFrom reading the task, I assume that the fundamental component of the system is to loop through a list of items and\nreturn the total of all prices.\n\nDue to this, I believe that this system would be better described as a `CostCalculator` rather than a `ShoppingCart` or\na `Checkout`.\n\nThat being said, I understand that describing it as a `CostCalculator` sheds responsibility of individually\nscanning/adding items into the system. Though I believe this is a fair compromise to keep the context well-defined and\nthe interface simple.\n\nAfter completing the single purpose of the system, I will look to add in the extra functionality of the different\ndiscounts as defined (BOGOF and BulkPurchases)\n\n#### ✅ Checklist\n\n- [x] ✨ Add `CostCalculator` which returns total given a list of items\n- [x] ♻️ Refactor `CostCalculator` for flexibility\n- [x] ✨ Add a `Buy One Get One Free (BOGOF) for Fruit Tea` discount mechanism\n- [x] ♻️ Refactor `Buy One Get One Free (BOGOF)` discount mechanism for flexibility of other products\n- [ ] ✨ Add a `BulkBuy For Strawberries` discount mechanism\n- [ ] ♻️ Refactor `BulkBuy` discount mechanism for flexibility of other products\n\n## 🤖 Solution\n\n### 📝 Notes\n\n- ❌ No `Scanning` functionality as defined by the requirements. Though this can be easily added with a `Checkout`\n  interface that passes the `CostCalculator` all _ScannedItems_.\n- 🔐 The current implementation could be a security risk depending on the client. Since the system expects `Items`, it\n  inherently trusts that the prices are correct. To mitigate this, the interface should be made simpler and only\n  expect `ProductCodes` then building `Items` with its own internal store (or external trusted source) of the `Item` the\n  codes relate to.\n- 🐛 Currently multiple of the same discount can be reapplied if specified within the system. Presumably this behaviour\n  is undesirable.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconnormaglynn%2Fshopping-cart-typescript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fconnormaglynn%2Fshopping-cart-typescript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconnormaglynn%2Fshopping-cart-typescript/lists"}