Skip to content
This repository was archived by the owner on Apr 26, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/application.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DataSource, Repository } from "typeorm"
import { SnakeNamingStrategy } from "typeorm-naming-strategies"
import CartDiscountAdder from "./application/CartDiscountAdder"
import CartLineAdder from "./application/CartlineAdder"
import Server from "./config/Server"
import CartController from "./controller/CartController"
import Cart from "./entity/Cart"
Expand All @@ -23,8 +24,9 @@ const connection : DataSource = new DataSource({
const cartRepository: Repository<Cart> = connection.getRepository(Cart)
const productRepository: Repository<Product> = connection.getRepository(Product)
const discountRepository: Repository<Discount> = connection.getRepository(Discount)
const cartLineAdder: CartLineAdder = new CartLineAdder(cartRepository, productRepository)
const cartDiscountAdder: CartDiscountAdder = new CartDiscountAdder(cartRepository, discountRepository)
const cartController = new CartController(cartRepository, productRepository, cartDiscountAdder)
const cartController = new CartController(cartLineAdder, cartDiscountAdder)
const server: Server = new Server(process.env.WEB_PORT, [cartController])

connection.initialize()
Expand Down
24 changes: 24 additions & 0 deletions src/application/CartlineAdder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Repository } from "typeorm"
import Cart from "../entity/Cart"
import Product from "../entity/Product"

class CartLineAdder {
private cartRepository: Repository<Cart>
private productRepository: Repository<Product>

constructor(cartRepository: Repository<Cart>, productRepository: Repository<Product>) {
this.cartRepository = cartRepository
this.productRepository = productRepository
}

public async add(cartId: number, sku: string, quantity: number): Promise<void> {
const cart: Cart = await this.cartRepository.findOneByOrFail({id: cartId})
const product: Product = await this.productRepository.findOneByOrFail({sku: sku})

cart.addLine(product, quantity)

await this.cartRepository.save(cart)
}
}

export default CartLineAdder
39 changes: 5 additions & 34 deletions src/controller/CartController.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,22 @@
import { Application, Request, Response } from "express"
import { Repository } from "typeorm"
import Controller from "../config/Controller"
import Cart from "../entity/Cart"
import Product from "../entity/Product"
import CartLine from "../entity/CartLine"
import CartDiscountAdder from "../application/CartDiscountAdder"
import CartLineAdder from "../application/CartlineAdder"

class CartController implements Controller {
private cartRepository: Repository<Cart>
private productRepository: Repository<Product>
private cartLineAdder: CartLineAdder
private cartDiscountAdder: CartDiscountAdder

constructor(cartRepository: Repository<Cart>, productRepository: Repository<Product>, cartDiscountAdder: CartDiscountAdder) {
this.cartRepository = cartRepository
this.productRepository = productRepository
constructor(cartLineAdder: CartLineAdder, cartDiscountAdder: CartDiscountAdder) {
this.cartLineAdder = cartLineAdder
this.cartDiscountAdder = cartDiscountAdder
}

private addLine = async (request: Request, response: Response): Promise<void> => {
const { id } = request.params
const { sku, quantity } = request.body

if (quantity < 0) {
throw "Negative quantity not allowed"
}

const cart: Cart = await this.cartRepository.findOneByOrFail({id: +id})
const product: Product = await this.productRepository.findOneByOrFail({sku: sku})
const cartLine: CartLine|undefined = cart.lines.find((cartLine: CartLine) => cartLine.product.sku == sku)

if (!cartLine) {
if (quantity > 0) {
const newCartLine: CartLine = new CartLine()
newCartLine.product = product
newCartLine.cart = cart
newCartLine.quantity = quantity
cart.lines.push(newCartLine)
}
} else {
if (quantity == 0) {
cart.lines.splice(cart.lines.indexOf(cartLine), 1)
} else {
cartLine.quantity = quantity
}
}

await this.cartRepository.save(cart)
await this.cartLineAdder.add(+id, sku, +quantity)

response.status(200).send()
}
Expand Down
46 changes: 46 additions & 0 deletions src/entity/Cart.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Entity, JoinTable, ManyToMany, OneToMany, PrimaryGeneratedColumn } from "typeorm"
import CartLine from "./CartLine"
import Discount from "./Discount"
import Product from "./Product"

@Entity("carts")
class Cart {
Expand All @@ -23,6 +24,51 @@ class Cart {
}
})
discounts: Discount[]

public addLine(product: Product, quantity: number): void {
if (quantity < 0) {
throw "Negative quantity not allowed"
}

const cartLine: CartLine|undefined = this.lines.find((cartLine: CartLine) => cartLine.product.sku == product.sku)

if (!cartLine) {
if (quantity > 0) {
const newCartLine: CartLine = new CartLine()
newCartLine.product = product
newCartLine.cart = this
newCartLine.quantity = quantity
this.lines.push(newCartLine)
}
} else {
if (quantity == 0) {
this.lines.splice(this.lines.indexOf(cartLine), 1)
} else {
cartLine.quantity = quantity
}
}
}

private totalLinesPrice(): number {
return this.lines
.map((cartLine: CartLine) => cartLine.quantity * cartLine.product.price)
.reduce((carry: number, current: number) => carry + current, 0)
}

private totalDiscountsPrice(): number {
return this.discounts
.map((discount: Discount) => discount.value)
.reduce((carry: number, current: number) => carry + current, 0)
}

public totalPrice(): number {
return Math.round((this.totalLinesPrice() - this.totalDiscountsPrice()) * 100) / 100
}

public quantityOfProduct(sku: string): number {
const cartLine: CartLine|undefined = this.lines.find((cartLine: CartLine) => cartLine.product.sku == sku)
return cartLine ? cartLine.quantity : 0
}
}

export default Cart
19 changes: 3 additions & 16 deletions src/tests/steps/CartSteps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import myConnection from "../util/Connection"
import Cart from "../../entity/Cart"
import axios, { Axios } from 'axios'
import assert from "assert"
import CartLine from "../../entity/CartLine"
import Discount from "../../entity/Discount"

@binding()
class CartSteps {
Expand Down Expand Up @@ -50,30 +48,19 @@ class CartSteps {
@then("the cart's total cost should be {double} euro(s)")
public async cartTotalCost(totalCost: number) {
const cart: Cart = await this.currentCart()
const totalProducts: number = cart
.lines
.map((cartLine: CartLine) => cartLine.quantity * cartLine.product.price)
.reduce((carry: number, current: number) => carry + current, 0)
const totalDiscounts = cart
.discounts
.map((discount: Discount) => discount.value)
.reduce((carry: number, current: number) => carry + current, 0)
assert.equal(Math.round((totalProducts - totalDiscounts) * 100) / 100, totalCost)
assert.equal(cart.totalPrice(), totalCost)
}

@then("there should be {int} unit(s) of product {string} in my cart")
public async thereShouldBeProductUnitsInMyCart(quantity: number, sku: string) {
const cart: Cart = await this.currentCart()
const cartLine: CartLine|undefined = cart.lines.find((cartLine: CartLine) => cartLine.product.sku == sku)
assert.equal(cartLine ? true : false, true, `Product ${sku} not found`)
assert.equal(cartLine?.quantity, quantity)
assert.equal(cart.quantityOfProduct(sku), quantity)
}

@then("there shouldn't be product {string} in my cart")
public async thereShouldNotBeProductInCart(sku: string) {
const cart: Cart = await this.currentCart()
const cartLine: CartLine|undefined = cart.lines.find((cartLine: CartLine) => cartLine.product.sku == sku)
assert.equal(undefined, cartLine, `Product ${sku} should not be present`)
assert.equal(cart.quantityOfProduct(sku), 0)
}

private currentCart(): Promise<Cart> {
Expand Down