From 6f032133b6b7e49ae7c5e76075246371c446aad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20G=2E=20Rodr=C3=ADguez?= Date: Mon, 13 Jun 2022 11:27:15 +0200 Subject: [PATCH] refactoring (step2) --- src/application.ts | 4 ++- src/application/CartlineAdder.ts | 24 +++++++++++++++++ src/controller/CartController.ts | 39 ++++----------------------- src/entity/Cart.ts | 46 ++++++++++++++++++++++++++++++++ src/tests/steps/CartSteps.ts | 19 +++---------- 5 files changed, 81 insertions(+), 51 deletions(-) create mode 100644 src/application/CartlineAdder.ts diff --git a/src/application.ts b/src/application.ts index 7bfefa0..395782b 100644 --- a/src/application.ts +++ b/src/application.ts @@ -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" @@ -23,8 +24,9 @@ const connection : DataSource = new DataSource({ const cartRepository: Repository = connection.getRepository(Cart) const productRepository: Repository = connection.getRepository(Product) const discountRepository: Repository = 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() diff --git a/src/application/CartlineAdder.ts b/src/application/CartlineAdder.ts new file mode 100644 index 0000000..40c8367 --- /dev/null +++ b/src/application/CartlineAdder.ts @@ -0,0 +1,24 @@ +import { Repository } from "typeorm" +import Cart from "../entity/Cart" +import Product from "../entity/Product" + +class CartLineAdder { + private cartRepository: Repository + private productRepository: Repository + + constructor(cartRepository: Repository, productRepository: Repository) { + this.cartRepository = cartRepository + this.productRepository = productRepository + } + + public async add(cartId: number, sku: string, quantity: number): Promise { + 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 \ No newline at end of file diff --git a/src/controller/CartController.ts b/src/controller/CartController.ts index 74b639e..9b4a015 100644 --- a/src/controller/CartController.ts +++ b/src/controller/CartController.ts @@ -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 - private productRepository: Repository + private cartLineAdder: CartLineAdder private cartDiscountAdder: CartDiscountAdder - constructor(cartRepository: Repository, productRepository: Repository, 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 => { 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() } diff --git a/src/entity/Cart.ts b/src/entity/Cart.ts index f70c53b..64bd97a 100644 --- a/src/entity/Cart.ts +++ b/src/entity/Cart.ts @@ -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 { @@ -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 diff --git a/src/tests/steps/CartSteps.ts b/src/tests/steps/CartSteps.ts index 06fb788..e823664 100644 --- a/src/tests/steps/CartSteps.ts +++ b/src/tests/steps/CartSteps.ts @@ -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 { @@ -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 {