Skip to content

Commit

Permalink
Merge pull request #7 from diegosneves/develop
Browse files Browse the repository at this point in the history
release v0.7.0
  • Loading branch information
diegosneves authored Dec 23, 2023
2 parents 66b4c51 + d54293c commit 836fde2
Show file tree
Hide file tree
Showing 46 changed files with 1,762 additions and 16 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/ci-main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,14 @@ jobs:
# with:
# push: true
# tags: diegoneves/racha-pedido:latest


# - name: Build and push
# id: docker_build
# uses: docker/build-push-action@v4
# with:
# push: true
# tags: diegoneves/racha-pedido:latest
# build-args: MY_ENV_VAR=${{ env.MY_ENV_VAR }}
# env:
# MY_ENV_VAR: my_value
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
<img align="center" alt="Diego-Docker" height="30" width="40" src="https://raw.githubusercontent.com/devicons/devicon/master/icons/docker/docker-plain.svg">
</div>

---
[![Linkedin badge](https://img.shields.io/badge/-Linkedin-blue?flat-square&logo=Linkedin&logoColor=white&link=https://www.linkedin.com/in/diego-neves-224208177/)](https://www.linkedin.com/in/diego-neves-224208177/)
[![CI Racha Pedido](https://github.com/diegosneves/racha-pedido/actions/workflows/ci-main.yml/badge.svg)](https://github.com/diegosneves/racha-pedido/actions/workflows/ci-main.yml)
[![CI Racha Pedido](https://github.com/diegosneves/racha-pedido/actions/workflows/ci-main.yaml/badge.svg)](https://github.com/diegosneves/racha-pedido/actions/workflows/ci-main.yaml)

---
O **Racha Pedido** é uma solução inteligente para resolver o desafio comum enfrentado por equipes de trabalho ao dividir
lanches ou refeições solicitados por meio de aplicativos de entrega como iFood ou Uber Eats.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
package diegosneves.github.rachapedido.config;

import diegosneves.github.rachapedido.dto.ExceptionDTO;
import diegosneves.github.rachapedido.exceptions.CalculateInvoiceException;
import diegosneves.github.rachapedido.exceptions.CloseOrderException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
* A classe {@link ControllerExceptionHandler} é um manipulador de exceções global para controladores.
* Ela lida com as exceções lançadas durante o processamento de solicitações e gera respostas de erro apropriadas.
* A classe é anotada com {@link RestControllerAdvice} para aplicar o tratamento de exceção globalmente
* a todas as classes de controlador.
*
* @author diegosneves
*/
@RestControllerAdvice
public class ControllerExceptionHandler {

Expand All @@ -15,4 +25,16 @@ public ResponseEntity<ExceptionDTO> generalError(Exception exception) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(dto);
}

@ExceptionHandler(CloseOrderException.class)
public ResponseEntity<ExceptionDTO> orderRelatedFaileures(CloseOrderException exception) {
ExceptionDTO dto = new ExceptionDTO(exception.getMessage(), CloseOrderException.ERROR.getStatusCodeValue());
return ResponseEntity.status(CloseOrderException.ERROR.getHttpStatusCode()).body(dto);
}

@ExceptionHandler(CalculateInvoiceException.class)
public ResponseEntity<ExceptionDTO> orderRelatedFaileures(CalculateInvoiceException exception) {
ExceptionDTO dto = new ExceptionDTO(exception.getMessage(), CalculateInvoiceException.ERROR.getStatusCodeValue());
return ResponseEntity.status(CalculateInvoiceException.ERROR.getHttpStatusCode()).body(dto);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ private Info getInfo() {
}

private List<Tag> getTags() { // TODO - Ajustar as tags do swagger
return List.of(new Tag().name("Racha-Pedido").description("Operações relacionadas a divisão dos valores do pedido"));
return List.of(new Tag().name("Racha Pedido").description("Operações relacionadas a divisão dos valores do pedido"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package diegosneves.github.rachapedido.controller;

import diegosneves.github.rachapedido.controller.contract.SplitInvoiceControllerContract;
import diegosneves.github.rachapedido.request.SplitInvoiceRequest;
import diegosneves.github.rachapedido.response.SplitInvoiceResponse;
import diegosneves.github.rachapedido.service.SplitInvoiceService;
import diegosneves.github.rachapedido.service.contract.SplitInvoiceServiceContract;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* A classe {@link SplitInvoiceController} é responsável por lidar com solicitações HTTP relacionadas à divisão de faturas.
* Implementa a interface {@link SplitInvoiceControllerContract}.
*
*/
@RestController
@RequestMapping("/split")
public class SplitInvoiceController implements SplitInvoiceControllerContract {

private final SplitInvoiceServiceContract service;

public SplitInvoiceController(@Autowired SplitInvoiceService service) {
this.service = service;
}


@Override
public ResponseEntity<SplitInvoiceResponse> splitInvoice(SplitInvoiceRequest request) {
SplitInvoiceResponse response = this.service.splitInvoice(request); // TODO - Criar a regra de negocio
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package diegosneves.github.rachapedido.controller.contract;

import diegosneves.github.rachapedido.request.SplitInvoiceRequest;
import diegosneves.github.rachapedido.response.SplitInvoiceResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

/**
* A interface {@link SplitInvoiceControllerContract} representa o contrato para lidar com solicitações HTTP relacionadas à divisão de faturas.
*/
public interface SplitInvoiceControllerContract {

@PostMapping(value = "/invoice", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Receber os dados para realizar a divisão da fatura", tags = "Racha Pedido", parameters = {
@Parameter(name = "referencia", description = "Tipos de descontos que devem ser aplicado no `discountType` do body",
schema = @Schema(enumAsRef = true, defaultValue = "cash", allowableValues = {"cash", "percentage", "no discount"}))
})
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Divisão da Fatura realizada com sucesso", content = @Content)
})
ResponseEntity<SplitInvoiceResponse> splitInvoice(@RequestBody SplitInvoiceRequest request);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package diegosneves.github.rachapedido.core;

import diegosneves.github.rachapedido.dto.InvoiceDTO;
import diegosneves.github.rachapedido.enums.DiscountType;
import diegosneves.github.rachapedido.mapper.BuilderMapper;
import diegosneves.github.rachapedido.model.Invoice;
import diegosneves.github.rachapedido.utils.RoundUtil;

public class CashDiscountStrategy extends DiscountStrategy {

@Override
public Invoice calculateDiscount(InvoiceDTO dto, Double discountAmount, DiscountType type, Double total, Double deliveryFee) {
if(DiscountType.CASH.name().equals(type.name())) {
dto.setPercentageConsumedTotalBill(dto.getValueConsumed() / total);
dto.setTotalPayable(RoundUtil.round(((total - type.discountAmount(discountAmount) + deliveryFee) * dto.getPercentageConsumedTotalBill())));
return BuilderMapper.builderMapper(Invoice.class, dto);
}
return this.checkNext(dto, discountAmount, type, total, deliveryFee);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package diegosneves.github.rachapedido.core;

import diegosneves.github.rachapedido.dto.InvoiceDTO;
import diegosneves.github.rachapedido.enums.DiscountType;
import diegosneves.github.rachapedido.model.Invoice;

public abstract class DiscountStrategy {

protected DiscountStrategy next;

public static DiscountStrategy link(DiscountStrategy first, DiscountStrategy... chain) {
DiscountStrategy current = first;
for (DiscountStrategy nextLink : chain) {
current.next = nextLink;
current = nextLink;
}
return first;
}
public abstract Invoice calculateDiscount(InvoiceDTO dto, Double discountAmount, DiscountType type, Double total, Double deliveryFee);

protected Invoice checkNext(InvoiceDTO dto, Double discountAmount, DiscountType type, Double total, Double deliveryFee) {
if (this.next == null) {
return new Invoice();
}
return next.calculateDiscount(dto, discountAmount, type, total, deliveryFee);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package diegosneves.github.rachapedido.core;

import diegosneves.github.rachapedido.dto.InvoiceDTO;
import diegosneves.github.rachapedido.enums.DiscountType;
import diegosneves.github.rachapedido.mapper.BuilderMapper;
import diegosneves.github.rachapedido.model.Invoice;
import diegosneves.github.rachapedido.utils.RoundUtil;

public class NoDiscountStrategy extends DiscountStrategy {

@Override
public Invoice calculateDiscount(InvoiceDTO dto, Double discountAmount, DiscountType type, Double total, Double deliveryFee) {
if (DiscountType.NO_DISCOUNT.name().equals(type.name())) {
dto.setPercentageConsumedTotalBill(dto.getValueConsumed() / total);
dto.setTotalPayable(RoundUtil.round((total - type.discountAmount(discountAmount) + deliveryFee) * dto.getPercentageConsumedTotalBill()));
return BuilderMapper.builderMapper(Invoice.class, dto);
}
return this.checkNext(dto, discountAmount, type, total, deliveryFee);
}
}
16 changes: 16 additions & 0 deletions src/main/java/diegosneves/github/rachapedido/core/PagBank.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package diegosneves.github.rachapedido.core;

import diegosneves.github.rachapedido.core.contract.PaymentStrategy;

public class PagBank implements PaymentStrategy {

@Override
public String generatedPaymentLink(Double paymentAmount) {
return String.format("Pagar: R$%,.2f", paymentAmount);
}

@Override
public void collectPaymentDetails() {
//TODO - Escrever aqui...
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package diegosneves.github.rachapedido.core;

import diegosneves.github.rachapedido.dto.InvoiceDTO;
import diegosneves.github.rachapedido.enums.DiscountType;
import diegosneves.github.rachapedido.mapper.BuilderMapper;
import diegosneves.github.rachapedido.model.Invoice;
import diegosneves.github.rachapedido.utils.RoundUtil;

public class PercentageDiscountStrategy extends DiscountStrategy {

@Override
public Invoice calculateDiscount(InvoiceDTO dto, Double discountAmount, DiscountType type, Double total, Double deliveryFee) {
if (DiscountType.PERCENTAGE.name().equals(type.name())) {
dto.setPercentageConsumedTotalBill(dto.getValueConsumed() / total);
dto.setTotalPayable(RoundUtil.round((total - (total * type.discountAmount(discountAmount)) + deliveryFee) * dto.getPercentageConsumedTotalBill()));
return BuilderMapper.builderMapper(Invoice.class, dto);
}
return this.checkNext(dto, discountAmount, type, total, deliveryFee);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package diegosneves.github.rachapedido.core.contract;

public interface PaymentStrategy {

String generatedPaymentLink(Double paymentAmount);
void collectPaymentDetails();
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
/**
* Esta classe representa um Data Transfer Object (DTO) para exceções.
* Contém a mensagem de exceção e o código de status.
*
* @see java.lang.Record
*/
public record ExceptionDTO(String message, int statusCode) {
}
17 changes: 17 additions & 0 deletions src/main/java/diegosneves/github/rachapedido/dto/InvoiceDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package diegosneves.github.rachapedido.dto;

import lombok.*;

@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Builder
public class InvoiceDTO {

private String consumerName;
private Double valueConsumed;
private Double totalPayable;
private Double percentageConsumedTotalBill;

}
27 changes: 27 additions & 0 deletions src/main/java/diegosneves/github/rachapedido/dto/PersonDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package diegosneves.github.rachapedido.dto;

import diegosneves.github.rachapedido.model.Item;
import lombok.*;

import java.util.ArrayList;
import java.util.List;

/**
* A classe {@link PersonDTO} é uma versão Data Transfer Object (DTO) de uma pessoa, contendo campos para {@link String nome}, {@link String e-mail} e uma lista de {@link Item itens}.
*
* Esta classe é usada principalmente para transferência de dados entre processos ou componentes e ajuda a evitar múltiplas chamadas ao projeto atual.
*
* @see diegosneves.github.rachapedido.model.Person Person
*/
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Builder
public class PersonDTO {

private String personName;
private String email;
private List<Item> items = new ArrayList<>();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package diegosneves.github.rachapedido.enums;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
* Representa os diferentes tipos de descontos que podem ser aplicados.
*
* @author diegosneves
*/
public enum DiscountType {

@JsonProperty(value = "cash")
CASH(1.0),
@JsonProperty(value = "percentage")
PERCENTAGE(100.0),
@JsonProperty(value = "no discount")
NO_DISCOUNT(0.0);

private final Double calculation;

DiscountType(Double calculation) {
this.calculation = calculation;
}

public Double discountAmount(Double value) {
return this.calculation == 0.0 ? 0.0 : value / this.calculation;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package diegosneves.github.rachapedido.exceptions;

/**
* A classe {@link CalculateInvoiceException} representa uma exceção que é acionada quando ocorre um erro
* durante o processo de fechamento da fatura. Esta classe é uma extensão da classe {@link RuntimeException}.
*
* @author diegosneves
* @see RuntimeException
*/
public class CalculateInvoiceException extends RuntimeException {

public static final ErroHandler ERROR = ErroHandler.INVOICE_FAILED;

/**
* Constrói uma nova instância de {@link CalculateInvoiceException} com a mensagem descritiva específica.
*
* @param message A mensagem detalhada. Deve fornecer informações complementares sobre a causa da exceção.
*/
public CalculateInvoiceException(String message) {
super(ERROR.errorMessage(message));
}

/**
* Cria uma nova instância de {@link CalculateInvoiceException} com a mensagem de detalhe especificada e a causa.
*
* @param message a mensagem de detalhes, fornecendo informações adicionais sobre a causa da exceção
* @param e a causa da exceção
*/
public CalculateInvoiceException(String message, Throwable e) {
super(ERROR.errorMessage(message), e);
}

}
Loading

0 comments on commit 836fde2

Please sign in to comment.