Skip to content

Commit

Permalink
Merge pull request #20 from FIAP-3SOAT-G15/adjust-to-orders
Browse files Browse the repository at this point in the history
Adjust to orders
  • Loading branch information
wellyfrs authored May 20, 2024
2 parents 16b3e56 + 94b0111 commit 6490c59
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 77 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
uses: aws-actions/amazon-ecr-login@v2

- name: Build, tag, and push docker image to Amazon ECR
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
#if: github.ref == 'refs/heads/main' && github.event_name == 'push'
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: ${{ vars.AWS_ECR_REPO_NAME }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import com.fiap.stock.application.domain.valueobjects.ProductCategory
import com.fiap.stock.application.driver.web.ProductAPI
import com.fiap.stock.application.driver.web.request.ProductComposeRequest
import com.fiap.stock.application.driver.web.request.ProductRequest
import com.fiap.stock.application.driver.web.request.ProductStockBatchChangeRequest
import com.fiap.stock.application.driver.web.response.ProductResponse
import com.fiap.stock.application.usecases.AdjustStockUseCase
import com.fiap.stock.application.usecases.AssembleProductsUseCase
import com.fiap.stock.application.usecases.LoadProductUseCase
import com.fiap.stock.application.usecases.SearchProductUseCase
Expand All @@ -17,29 +19,37 @@ class ProductController(
private val assembleProductsUseCase: AssembleProductsUseCase,
private val loadProductUseCase: LoadProductUseCase,
private val searchProductUseCase: SearchProductUseCase,
private val adjustStockUseCase: AdjustStockUseCase,
) : ProductAPI {
override fun getByProductNumber(productNumber: Long): ResponseEntity<ProductResponse> {
return loadProductUseCase.getByProductNumber(productNumber).let(::createResponse)
}

override fun findAll(): ResponseEntity<List<ProductResponse>> {
return loadProductUseCase.findAll().let(::respond)
}
override fun findAll(): ResponseEntity<List<ProductResponse>> =
loadProductUseCase.findAll().let(::respond)

override fun findByCategory(category: String): ResponseEntity<List<ProductResponse>> {
return loadProductUseCase.findByCategory(ProductCategory.fromString(category)).let(::respond)
}
override fun findAllByProductNumber(productNumbers: List<Long>): ResponseEntity<List<ProductResponse>> =
loadProductUseCase.findAllByProductNumber(productNumbers).let(::respond)

override fun searchByName(name: String): ResponseEntity<List<ProductResponse>> {
return searchProductUseCase.searchByName(name).let(::respond)
override fun incrementStockOfProducts(productStockBatchChangeRequest: ProductStockBatchChangeRequest): ResponseEntity<String> {
adjustStockUseCase.incrementStockOfProducts(productStockBatchChangeRequest.productNumberQuantityMap)
return ResponseEntity.ok().build()
}

override fun create(productRequest: ProductRequest): ResponseEntity<ProductResponse> {
val result =
assembleProductsUseCase.create(productRequest.toDomain(), productRequest.components).let(::createResponse)
return result
override fun decrementStockOfProducts(productStockBatchChangeRequest: ProductStockBatchChangeRequest): ResponseEntity<String> {
adjustStockUseCase.decrementStockOfProducts(productStockBatchChangeRequest.productNumberQuantityMap)
return ResponseEntity.ok().build()
}

override fun findByCategory(category: String): ResponseEntity<List<ProductResponse>> =
loadProductUseCase.findByCategory(ProductCategory.fromString(category)).let(::respond)

override fun searchByName(name: String): ResponseEntity<List<ProductResponse>> =
searchProductUseCase.searchByName(name).let(::respond)

override fun create(productRequest: ProductRequest): ResponseEntity<ProductResponse> =
assembleProductsUseCase.create(productRequest.toDomain(), productRequest.components).let(::createResponse)

override fun update(
productNumber: Long,
productRequest: ProductRequest,
Expand All @@ -48,22 +58,18 @@ class ProductController(
return assembleProductsUseCase.update(product, productRequest.components).let(::createResponse)
}

override fun delete(productNumber: Long): ResponseEntity<ProductResponse> {
return assembleProductsUseCase.delete(productNumber).let(::createResponse)
}
override fun delete(productNumber: Long): ResponseEntity<ProductResponse> =
assembleProductsUseCase.delete(productNumber).let(::createResponse)

override fun compose(productComposeRequest: ProductComposeRequest): ResponseEntity<ProductResponse> {
return assembleProductsUseCase.compose(
override fun compose(productComposeRequest: ProductComposeRequest): ResponseEntity<ProductResponse> =
assembleProductsUseCase.compose(
productComposeRequest.productNumber,
productComposeRequest.subItemsNumbers,
).let(::createResponse)
}

private fun createResponse(product: Product?): ResponseEntity<ProductResponse> {
return ResponseEntity.ok(product?.let { ProductResponse.fromDomain(product) })
}
private fun createResponse(product: Product?): ResponseEntity<ProductResponse> =
ResponseEntity.ok(product?.let { ProductResponse.fromDomain(product) })

private fun respond(products: List<Product>): ResponseEntity<List<ProductResponse>> {
return ResponseEntity.ok(products.map { ProductResponse.fromDomain(it) })
}
private fun respond(products: List<Product>): ResponseEntity<List<ProductResponse>> =
ResponseEntity.ok(products.map { ProductResponse.fromDomain(it) })
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import com.fiap.stock.application.StockApiApp
import com.fiap.stock.application.adapter.gateway.ComponentGateway
import com.fiap.stock.application.adapter.gateway.ProductGateway
import com.fiap.stock.application.adapter.gateway.StockGateway
import com.fiap.stock.application.adapter.gateway.TransactionalGateway
import com.fiap.stock.application.usecases.LoadComponentUseCase
import com.fiap.stock.application.services.ComponentService
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import com.fiap.stock.application.services.ProductService
import com.fiap.stock.application.services.StockService
import com.fiap.stock.application.usecases.LoadProductUseCase

@Configuration
@ComponentScan(basePackageClasses = [StockApiApp::class])
Expand Down Expand Up @@ -42,9 +44,15 @@ class ServiceConfig {
}

@Bean
fun createStockService(stockRepository: StockGateway): StockService {
return StockService(stockRepository)
fun createStockService(
stockRepository: StockGateway,
loadProductUseCase: LoadProductUseCase,
transactionalGateway: TransactionalGateway,
): StockService {
return StockService(
stockRepository,
loadProductUseCase,
transactionalGateway,
)
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import com.fiap.stock.application.domain.valueobjects.ProductCategory

interface ProductGateway {
fun findAll(): List<Product>

fun findAllByProductNumber(productNumbers: List<Long>): List<Product>

fun findByProductNumber(productNumber: Long): Product?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,23 @@ class ProductGatewayImpl(
) : ProductGateway {
private val mapper: ProductMapper = Mappers.getMapper(ProductMapper::class.java)

override fun findAll(): List<Product> {
return productJpaRepository.findAll()
.map(mapper::toDomain)
}
override fun findAll(): List<Product> =
productJpaRepository.findAll().map(mapper::toDomain)

override fun findByProductNumber(productNumber: Long): Product? {
return productJpaRepository.findById(productNumber)
.map { mapper.toDomain(it) }
.orElse(null)
}
override fun findAllByProductNumber(productNumbers: List<Long>): List<Product> =
productJpaRepository.findAllById(productNumbers).map(mapper::toDomain)

override fun findByCategory(category: ProductCategory): List<Product> {
return productJpaRepository.findByCategoryIgnoreCase(category.toString())
.map { mapper.toDomain(it) }
}
override fun findByProductNumber(productNumber: Long): Product? =
productJpaRepository.findById(productNumber).map { mapper.toDomain(it) }.orElse(null)

override fun searchByName(name: String): List<Product> {
return productJpaRepository.findByNameContainingIgnoreCase(name)
.map(mapper::toDomain)
}
override fun findByCategory(category: ProductCategory): List<Product> =
productJpaRepository.findByCategoryIgnoreCase(category.toString()).map { mapper.toDomain(it) }

override fun create(product: Product): Product {
return persist(product.copy(number = null))
}
override fun searchByName(name: String): List<Product> =
productJpaRepository.findByNameContainingIgnoreCase(name).map(mapper::toDomain)

override fun create(product: Product): Product =
persist(product.copy(number = null))

override fun update(product: Product): Product {
val number =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.fiap.stock.application.driver.web

import com.fiap.stock.application.driver.web.request.ProductComposeRequest
import com.fiap.stock.application.driver.web.request.ProductRequest
import com.fiap.stock.application.driver.web.request.ProductStockBatchChangeRequest
import com.fiap.stock.application.driver.web.response.ProductResponse
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter
Expand All @@ -19,6 +20,7 @@ import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam

@Tag(name = "produto", description = "Produtos")
@RequestMapping("/admin/products")
Expand All @@ -43,6 +45,71 @@ interface ProductAPI {
@GetMapping
fun findAll(): ResponseEntity<List<ProductResponse>>

@Operation(
summary = "Retorna todos os produtos identificados por número",
parameters = [
Parameter(
name = "x-admin-token",
required = true,
`in` = ParameterIn.HEADER,
schema = Schema(type = "string", defaultValue = "token"),
),
],
)
@ApiResponses(
value = [
ApiResponse(responseCode = "200", description = "Operação bem-sucedida"),
],
)
@GetMapping("/batch")
fun findAllByProductNumber(
@Parameter(description = "IDs de produtos") @RequestParam("numbers") productNumbers: List<Long>,
): ResponseEntity<List<ProductResponse>>

@Operation(
summary = "Incrementa estoque disponível para os produtos identificados",
parameters = [
Parameter(
name = "x-admin-token",
required = true,
`in` = ParameterIn.HEADER,
schema = Schema(type = "string", defaultValue = "token"),
),
],
)
@ApiResponses(
value = [
ApiResponse(responseCode = "200", description = "Operação bem-sucedida"),
],
)
@PostMapping("/batch/increment")
fun incrementStockOfProducts(
@Parameter(description = "Relações de produto e quantidade a incrementar")
@RequestBody productStockBatchChangeRequest: ProductStockBatchChangeRequest,
): ResponseEntity<String>

@Operation(
summary = "Decrementa estoque disponível para os produtos identificados",
parameters = [
Parameter(
name = "x-admin-token",
required = true,
`in` = ParameterIn.HEADER,
schema = Schema(type = "string", defaultValue = "token"),
),
],
)
@ApiResponses(
value = [
ApiResponse(responseCode = "200", description = "Operação bem-sucedida"),
],
)
@PostMapping("/batch/decrement")
fun decrementStockOfProducts(
@Parameter(description = "Relações de produto e quantidade a decrementar")
@RequestBody productStockBatchChangeRequest: ProductStockBatchChangeRequest,
): ResponseEntity<String>

@Operation(
summary = "Retorna produtos por categoria",
parameters = [
Expand Down Expand Up @@ -127,7 +194,7 @@ interface ProductAPI {
ApiResponse(responseCode = "500", description = "Erro não esperado"),
],
)
@PostMapping()
@PostMapping
fun create(
@Parameter(description = "Cadastro do produto") @RequestBody productRequest: ProductRequest,
): ResponseEntity<ProductResponse>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.fiap.stock.application.driver.web.request

data class ProductStockBatchChangeRequest(
val productNumberQuantityMap: Map<Long, Long>
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import com.fiap.stock.application.domain.entities.Product
import com.fiap.stock.application.domain.errors.ErrorType
import com.fiap.stock.application.domain.errors.SelfOrderManagementException
import com.fiap.stock.application.domain.valueobjects.ProductCategory
import com.fiap.stock.application.usecases.*
import com.fiap.stock.application.usecases.AssembleProductsUseCase
import com.fiap.stock.application.usecases.LoadComponentUseCase
import com.fiap.stock.application.usecases.LoadProductUseCase
import com.fiap.stock.application.usecases.RemoveProductUseCase
import com.fiap.stock.application.usecases.SearchProductUseCase
import org.slf4j.LoggerFactory

class ProductService(
Expand All @@ -18,25 +22,24 @@ class ProductService(
RemoveProductUseCase {
private val log = LoggerFactory.getLogger(javaClass)

override fun getByProductNumber(productNumber: Long): Product {
return productRepository.findByProductNumber(productNumber)
override fun getByProductNumber(productNumber: Long): Product =
productRepository.findByProductNumber(productNumber)
?: throw SelfOrderManagementException(
errorType = ErrorType.PRODUCT_NOT_FOUND,
message = "Product [$productNumber] not found",
)
}

override fun findAll(): List<Product> {
return productRepository.findAll()
}
override fun findAll(): List<Product> =
productRepository.findAll()

override fun findByCategory(category: ProductCategory): List<Product> {
return productRepository.findByCategory(category)
}
override fun findAllByProductNumber(productNumbers: List<Long>): List<Product> =
productRepository.findAllByProductNumber(productNumbers)

override fun searchByName(productName: String): List<Product> {
return productRepository.searchByName(productName.trim())
}
override fun findByCategory(category: ProductCategory): List<Product> =
productRepository.findByCategory(category)

override fun searchByName(productName: String): List<Product> =
productRepository.searchByName(productName.trim())

override fun create(
product: Product,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package com.fiap.stock.application.services

import com.fiap.stock.application.adapter.gateway.StockGateway
import com.fiap.stock.application.adapter.gateway.TransactionalGateway
import com.fiap.stock.application.domain.entities.Stock
import com.fiap.stock.application.domain.errors.ErrorType
import com.fiap.stock.application.domain.errors.SelfOrderManagementException
import com.fiap.stock.application.usecases.AdjustStockUseCase
import com.fiap.stock.application.usecases.LoadProductUseCase
import com.fiap.stock.application.usecases.LoadStockUseCase
import org.slf4j.LoggerFactory

class StockService(
private val stockRepository: StockGateway,
private val loadProductUseCase: LoadProductUseCase,
private val transactionalGateway: TransactionalGateway,
) : LoadStockUseCase,
AdjustStockUseCase {
private val log = LoggerFactory.getLogger(javaClass)
Expand Down Expand Up @@ -45,4 +49,24 @@ class StockService(
}
return stockRepository.update(stock.copy(quantity = stock.quantity - quantity))
}

override fun incrementStockOfProducts(productNumberQuantityMap: Map<Long, Long>) {
transactionalGateway.transaction {
productNumberQuantityMap.forEach{ (productId, quantity) ->
loadProductUseCase.getByProductNumber(productId).components.forEach { component ->
increment(component.number!!, quantity)
}
}
}
}

override fun decrementStockOfProducts(productNumberQuantityMap: Map<Long, Long>) {
transactionalGateway.transaction {
productNumberQuantityMap.forEach{ (productId, quantity) ->
loadProductUseCase.getByProductNumber(productId).components.forEach { component ->
decrement(component.number!!, quantity)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ interface AdjustStockUseCase {
fun increment(componentNumber: Long, quantity: Long): Stock

fun decrement(componentNumber: Long, quantity: Long): Stock

fun incrementStockOfProducts(productNumberQuantityMap: Map<Long, Long>)

fun decrementStockOfProducts(productNumberQuantityMap: Map<Long, Long>)
}
Loading

0 comments on commit 6490c59

Please sign in to comment.