Browse Source

new: API port, Register, Login, OrderBook, Commodities with all CRUDs

EduLascala 2 months ago
parent
commit
72b359462d
37 changed files with 1084 additions and 323 deletions
  1. 14 0
      .gitignore
  2. 4 0
      mvnw
  3. 233 0
      routes.md
  4. 0 1
      src/main/java/com/platform2easy/genesis/blockchain/build/DocumentManager.abi
  5. 0 0
      src/main/java/com/platform2easy/genesis/blockchain/build/DocumentManager.bin
  6. 0 33
      src/main/java/com/platform2easy/genesis/blockchain/contract/CreateSmartContract.sol
  7. 0 2
      src/main/java/com/platform2easy/genesis/blockchain/script/BuildSmartContract.sh
  8. 0 7
      src/main/java/com/platform2easy/genesis/blockchain/script/GenerateWeb3J.sh
  9. 0 31
      src/main/java/com/platform2easy/genesis/blockchain/service/DeployNFT.java
  10. 71 0
      src/main/java/com/platform2easy/genesis/domain/model/AppUser.java
  11. 8 15
      src/main/java/com/platform2easy/genesis/domain/model/Commoditiy.java
  12. 59 0
      src/main/java/com/platform2easy/genesis/domain/model/Orderbook.java
  13. 10 0
      src/main/java/com/platform2easy/genesis/domain/repository/AppUserRepository.java
  14. 7 0
      src/main/java/com/platform2easy/genesis/domain/repository/OrderbookRepository.java
  15. 2 1
      src/main/java/com/platform2easy/genesis/domain/service/CommodityService.java
  16. 2 1
      src/main/java/com/platform2easy/genesis/domain/service/CompraService.java
  17. 2 2
      src/main/java/com/platform2easy/genesis/domain/service/cerc/ContratoValorCprService.java
  18. 2 2
      src/main/java/com/platform2easy/genesis/domain/service/cerc/EmissaoCprService.java
  19. 2 1
      src/main/java/com/platform2easy/genesis/domain/service/cerc/SolicitacaoRegistroCprService.java
  20. 48 0
      src/main/java/com/platform2easy/genesis/infra/security/SecurityConfig.java
  21. 49 0
      src/main/java/com/platform2easy/genesis/infra/security/SecurityFilter.java
  22. 38 0
      src/main/java/com/platform2easy/genesis/infra/security/TokenService.java
  23. 1 0
      src/main/java/com/platform2easy/genesis/security/config/SecurityConfiguration.java
  24. 1 2
      src/main/java/com/platform2easy/genesis/security/service/TokenService.java
  25. 109 0
      src/main/java/com/platform2easy/genesis/web/controller/AuthenticationController.java
  26. 35 35
      src/main/java/com/platform2easy/genesis/web/controller/CommodityController.java
  27. 33 51
      src/main/java/com/platform2easy/genesis/web/controller/CompraController.java
  28. 36 43
      src/main/java/com/platform2easy/genesis/web/controller/cerc/ContratoValorCprController.java
  29. 39 45
      src/main/java/com/platform2easy/genesis/web/controller/cerc/EmissaoCprController.java
  30. 39 51
      src/main/java/com/platform2easy/genesis/web/controller/cerc/SolicitacaoRegistroCprController.java
  31. 20 0
      src/main/java/com/platform2easy/genesis/web/dto/AuthenticationDTO.java
  32. 47 0
      src/main/java/com/platform2easy/genesis/web/dto/RegisterDTO.java
  33. 14 0
      src/main/java/com/platform2easy/genesis/web/dto/TokenDTO.java
  34. 16 0
      src/main/resources/application-postgres.properties
  35. 2 0
      src/main/resources/application.properties
  36. 138 0
      src/main/resources/db/migration/postgresql/V1__init.sql
  37. 3 0
      src/main/resources/db/migration/postgresql/V2__seed_company_role.sql

+ 14 - 0
.gitignore

@@ -31,3 +31,17 @@ build/
 
 ### VS Code ###
 .vscode/
+
+# Environment and secrets
+.env
+.env.*
+!.env.example
+*.jks
+*.keystore
+*.p12
+*.pem
+*.key
+*.crt
+*.cer
+application-*.local.properties
+application-*.local.yml

+ 4 - 0
mvnw

@@ -68,6 +68,10 @@
             <artifactId>postgresql</artifactId>
             <scope>runtime</scope>
         </dependency>
+        <dependency>
+            <groupId>org.flywaydb</groupId>
+            <artifactId>flyway-core</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>

+ 233 - 0
routes.md

@@ -0,0 +1,233 @@
+# Too Easy Genesis API Routes
+
+## INICIATE THE SERVER
+
+cd /home/uriri/Projetos/tooeasy/backend/too-easy-genesis
+
+```bash
+./mvnw -DskipTests spring-boot:run
+```
+```bash
+java -jar target/too-easy-trader-genesis-0.0.1-SNAPSHOT.jar --server.port=8080
+```
+## STOP THE SERVER
+
+```bash
+pkill -f too-easy-trader-genesis-0.0.1-SNAPSHOT.jar
+```
+
+Base URL: http://localhost:8080
+
+Set Postman collection variables:
+- baseUrl = http://localhost:8080
+
+Default headers for protected routes:
+- Authorization: Bearer {{token}}
+- Content-Type: application/json
+
+## Register
+## POST {{baseUrl}}/auth/register
+- Body (application/json) — fields from `RegisterDTO` (`src/main/java/com/platform2easy/genesis/web/dto/RegisterDTO.java`):
+```json
+{
+  "name": "John Doe",
+  "email": "john@example.com",
+  "password": "Str0ng!Pass",
+  "phone": "+55 11 99999-9999",
+  "address": "Av. Paulista, 1000",
+  "city": "São Paulo",
+  "state": "SP",
+  "zip": "01310-100",
+  "country": "BR",
+  "kyc": 1,
+  "birthdate": 19900101,
+  "cpf": "123.456.789-00",
+  "companyId": 1,
+  "roleId": 1,
+  "flag": "ACTIVE"
+}
+```
+- Response 201 Created:
+```json
+{ "token": "<JWT>" }
+```
+## Login
+#### POST {{baseUrl}}/auth/login
+- Body — `AuthenticationDTO` (`src/main/java/com/platform2easy/genesis/web/dto/AuthenticationDTO.java`):
+```json
+{ "email": "john@example.com", "password": "Str0ng!Pass" }
+```
+- Response 200 OK:
+```json
+{ "token": "<JWT>" }
+```
+
+## Commodity API (`com.platform2easy.genesis.web.controller.CommodityController`)
+#### Base path: {{baseUrl}}/api/commodity
+
+- GET {{baseUrl}}/api/commodity
+  - List all commodities.
+
+- GET {{baseUrl}}/api/commodity/{id}
+  - Path params: id (Long)
+
+- POST {{baseUrl}}/api/commodity
+  - Body — entity `Commoditiy` (`domain/model/Commoditiy.java`):
+```json
+{
+  "tipoCommodity": "SACA_GRAOS",
+  "descricao": "Soja",
+  "quantidade": 100,
+  "preco": 125.50,
+  "vencimentoPagamento": "2025-12-31",
+  "dataLimiteEntrega": "2026-01-15",
+  "cedulaProdutoRural": "CPR-123456"
+}
+```
+
+#### - PUT {{baseUrl}}/api/commodity/{id}
+  - Body: same as POST
+
+#### - DELETE {{baseUrl}}/api/commodity/{id}
+
+Notes:
+- `tipoCommodity` enum values: see `domain/enums/TipoCommodity.java` (e.g., "SACA_GRAOS").
+- Dates use ISO-8601: LocalDate `yyyy-MM-dd`.
+
+
+## Compra API (`com.platform2easy.genesis.web.controller.CompraController`)
+#### Base path: {{baseUrl}}/api/compra
+
+#### - GET {{baseUrl}}/api/compra
+
+#### - GET {{baseUrl}}/api/compra/{id}
+  - Path params: id (Long)
+
+#### - POST {{baseUrl}}/api/compra
+  - Body — entity `Compra` with nested `ItemCompra` list:
+```json
+{
+  "fornecedor": "Fornecedor XYZ",
+  "itens": [
+    { "quantidade": 10, "valor": 35.5, "descricao": "Item A" },
+    { "quantidade": 5, "valor": 100.0, "descricao": "Item B" }
+  ]
+}
+```
+
+#### - PUT {{baseUrl}}/api/compra/{id}
+  - Body: same as POST
+
+#### - DELETE {{baseUrl}}/api/compra/{id}
+
+Notes:
+- `Compra` and `ItemCompra` live in `domain/model/Compra.java` and `domain/model/ItemCompra.java`.
+- IDs are generated; omit `id` in POST bodies.
+
+
+## CPR - Emissão (`com.platform2easy.genesis.web.controller.cerc.EmissaoCprController`)
+#### Base path: {{baseUrl}}/api/cpr/emission
+
+#### - GET {{baseUrl}}/api/cpr/emission
+
+#### - GET {{baseUrl}}/api/cpr/emission/{id}
+
+#### - POST {{baseUrl}}/api/cpr/emission
+  - Body — entity `EmissaoCpr`:
+```json
+{
+  "dataEntrega": "2025-11-01",
+  "localEmissao": "São Paulo",
+  "razaoSocialEmissor": "Empresa Emissora SA",
+  "tipoCpr": "FISICO"
+}
+```
+
+#### - PUT {{baseUrl}}/api/cpr/emission/{id}
+  - Body: same as POST
+
+#### - DELETE {{baseUrl}}/api/cpr/emission/{id}
+
+Notes:
+- `tipoCpr` enum values: `FISICO`, `FINANCEIRO` (`domain/model/cerc/TipoCpr.java`).
+- `dataEntrega` is ISO LocalDate.
+
+
+## CPR - Contrato de Valor (`com.platform2easy.genesis.web.controller.cerc.ContratoValorCprController`)
+Base path: {{baseUrl}}/api/cpr/contract
+
+#### - GET {{baseUrl}}/api/cpr/contract
+
+#### - GET {{baseUrl}}/api/cpr/contract/{id}
+
+#### - POST {{baseUrl}}/api/cpr/contract
+  - Body — entity `ContratoValorCpr` (all fields optional except as required by business rules):
+```json
+{
+  "autorizoRegistroEDeclaroQueFoiDadoBaixaNoRegistroEmQuaisquerOutrasIf": true,
+  "codigoContratoOperacaoCredito": "OP123",
+  "codigoContratoScr": "SCR-456",
+  "codigoMoeda": "BRL",
+  "dataBaixaOutraIf": "2025-10-01T10:00:00",
+  "dataContratoSistemaIF": "2025-09-15T09:30:00",
+  "dataRegistroOriginal": "2025-09-01T08:00:00",
+  "dataTransacao": "2025-10-02",
+  "identificacaoPadronizadaOperacaoCredito": "ID-789",
+  "indexacao": "CDI",
+  "naturezaOperacao": "CREDITO_RURAL",
+  "percentualIndexador": 0.12,
+  "quantidadeParcelaContratada": 12,
+  "referenciaExterna": "REF-2025",
+  "taxaJurosOperacao": 0.15,
+  "tipoAtivo": "CPR",
+  "valorFinanciadoContrato": 100000.00,
+  "valorLiquidoCredito": 95000.00,
+  "valorTotalCredito": 110000.00
+}
+```
+
+#### - PUT {{baseUrl}}/api/cpr/contract/{id}
+  - Body: same as POST
+
+#### - DELETE {{baseUrl}}/api/cpr/contract/{id}
+
+Notes:
+- Date/time fields use ISO-8601: LocalDate `yyyy-MM-dd`, LocalDateTime `yyyy-MM-dd'T'HH:mm:ss`.
+
+
+## CPR - Solicitação de Registro (`com.platform2easy.genesis.web.controller.cerc.SolicitacaoRegistroCprController`)
+Base path: {{baseUrl}}/api/cpr/register
+
+#### - GET {{baseUrl}}/api/cpr/register
+
+#### - GET {{baseUrl}}/api/cpr/register/{id}
+
+#### - POST {{baseUrl}}/api/cpr/register
+  - Body — entity `SolicitacaoRegistroCpr` (references other entities by id):
+```json
+{
+  "aditivo": "Aditivo 1",
+  "contratoValorCpr": { "id": 1 },
+  "emissaoCpr": { "id": 1 },
+  "status": "NOVO"
+}
+```
+
+#### - PUT {{baseUrl}}/api/cpr/register/{id}
+  - Body: same as POST
+
+#### - POST {{baseUrl}}/api/cpr/register/{id}/send
+  - Effect: loads record by id and sets `status` to `ACEITO`.
+
+#### - DELETE {{baseUrl}}/api/cpr/register/{id}
+
+Notes:
+- `status` enum values: `NOVO`, `ACEITO`, `LIQUIDADO`, `RECUSADO`, `CANCELADO`.
+
+
+## Quick Postman steps
+1. Choose a login:
+   #### - POST `/auth/login` with email/password, OR
+   #### - POST `/authentication/login` with login/password.
+2. Copy `token` from response and set Postman variable `token`.
+3. Use protected endpoints under `/api/**` with header `Authorization: Bearer {{token}}`.

+ 0 - 1
src/main/java/com/platform2easy/genesis/blockchain/build/DocumentManager.abi

@@ -1 +0,0 @@
-[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"uri","type":"string"},{"indexed":false,"internalType":"bytes32","name":"documentHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"DocumentAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"DocumentRemoved","type":"event"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"getDocument","outputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"removeDocument","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"uri","type":"string"},{"internalType":"bytes32","name":"documentHash","type":"bytes32"}],"name":"setDocument","outputs":[],"stateMutability":"nonpayable","type":"function"}]

File diff suppressed because it is too large
+ 0 - 0
src/main/java/com/platform2easy/genesis/blockchain/build/DocumentManager.bin


+ 0 - 33
src/main/java/com/platform2easy/genesis/blockchain/contract/CreateSmartContract.sol

@@ -1,33 +0,0 @@
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.0;
-
-contract DocumentManager {
-
-    struct Document {
-        string uri;
-        bytes32 documentHash;
-        uint256 lastModified;
-    }
-
-    mapping(string => Document) private documents;
-
-    event DocumentAdded(string indexed name, string uri, bytes32 documentHash, uint256 timestamp);
-    event DocumentRemoved(string indexed name, uint256 timestamp);
-
-    function setDocument(string memory name, string memory uri, bytes32 documentHash) external {
-        documents[name] = Document(uri, documentHash, block.timestamp);
-        emit DocumentAdded(name, uri, documentHash, block.timestamp);
-    }
-
-    function getDocument(string memory name) external view returns (string memory, bytes32, uint256) {
-        Document memory doc = documents[name];
-        require(doc.lastModified != 0, "Documento nao encontrado");
-        return (doc.uri, doc.documentHash, doc.lastModified);
-    }
-
-    function removeDocument(string memory name) external {
-        require(documents[name].lastModified != 0, "Documento nao encontrado");
-        delete documents[name];
-        emit DocumentRemoved(name, block.timestamp);
-    }
-}

+ 0 - 2
src/main/java/com/platform2easy/genesis/blockchain/script/BuildSmartContract.sh

@@ -1,2 +0,0 @@
-#!/bin/bash
-solc --bin --abi --optimize --overwrite -o ../build ../contract/CreateSmartContract.sol

+ 0 - 7
src/main/java/com/platform2easy/genesis/blockchain/script/GenerateWeb3J.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-web3j solidity generate \
-  build/DocumentManager.bin \
-  build/DocumentManager.abi \
-  -p com.platform2easy.genesis.blockchain.service \
-  -o src/main/java/
-  

+ 0 - 31
src/main/java/com/platform2easy/genesis/blockchain/service/DeployNFT.java

@@ -1,31 +0,0 @@
-package com.platform2easy.genesis.blockchain.service;
-
-import org.web3j.crypto.Credentials;
-import org.web3j.protocol.Web3j;
-import org.web3j.protocol.http.HttpService;
-import org.web3j.tx.gas.DefaultGasProvider;
-
-public class DeployNFT {
-
-    public static void main(String[] args) throws Exception {
-        Web3j web3j = Web3j.build(new HttpService("https://sepolia.infura.io/v3/SUA_API_KEY"));
-        Credentials credentials = Credentials.create("SUA_PRIVATE_KEY");
-
-        // Deploy do contrato
-        /*MeuNFT contrato = MeuNFT.deploy(
-                web3j,
-                credentials,
-                new DefaultGasProvider()
-        ).send();
-
-        System.out.println("Contrato implantado em: " + contrato.getContractAddress());
-
-        // Mint de um NFT
-        contrato.mintNFT(
-                credentials.getAddress(),
-                "https://meusite.com/nft/1.json"
-        ).send();
-
-        System.out.println("NFT mintado!");*/
-    }
-}

+ 71 - 0
src/main/java/com/platform2easy/genesis/domain/model/AppUser.java

@@ -0,0 +1,71 @@
+package com.platform2easy.genesis.domain.model;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Entity
+@Table(name = "\"user\"")
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class AppUser {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "user_id")
+    private Long userId;
+
+    @Column(name = "user_name", nullable = false)
+    private String userName;
+
+    @Column(name = "user_email", nullable = false, unique = true)
+    private String userEmail;
+
+    @Column(name = "user_password", nullable = false)
+    private String userPassword;
+
+    @Column(name = "user_phone", nullable = false)
+    private String userPhone;
+
+    @Column(name = "user_address", nullable = false)
+    private String userAddress;
+
+    @Column(name = "user_city", nullable = false)
+    private String userCity;
+
+    @Column(name = "user_state", nullable = false)
+    private String userState;
+
+    @Column(name = "user_zip", nullable = false)
+    private String userZip;
+
+    @Column(name = "user_country", nullable = false)
+    private String userCountry;
+
+    @Column(name = "user_kyc", nullable = false)
+    private Integer userKyc;
+
+    @Column(name = "user_birthdate", nullable = false)
+    private Integer userBirthdate;
+
+    @Column(name = "user_cpf", nullable = false)
+    private String userCpf;
+
+    @Column(name = "company_id", nullable = false)
+    private Integer companyId;
+
+    @Column(name = "role_id", nullable = false)
+    private Integer roleId;
+
+    @Column(name = "user_flag", nullable = false)
+    private String userFlag;
+}

+ 8 - 15
src/main/java/com/platform2easy/genesis/domain/model/Commoditiy.java

@@ -1,9 +1,8 @@
 package com.platform2easy.genesis.domain.model;
 
-import com.platform2easy.genesis.domain.enums.TipoCommodity;
 import jakarta.persistence.Entity;
-import jakarta.persistence.EnumType;
-import jakarta.persistence.Enumerated;
+import jakarta.persistence.Table;
+import jakarta.persistence.Column;
 import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.GenerationType;
 import jakarta.persistence.Id;
@@ -13,10 +12,8 @@ import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
 
-import java.math.BigDecimal;
-import java.time.LocalDate;
-
 @Entity
+@Table(name = "commodities")
 @Getter
 @Setter
 @AllArgsConstructor
@@ -27,18 +24,14 @@ public class Commoditiy {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @EqualsAndHashCode.Include
+    @Column(name = "commodities_id")
     private Long id;
 
-    @Enumerated(EnumType.STRING)
-    private TipoCommodity tipoCommodity;
-
-    private String descricao;
-    private Integer quantidade;
-    private BigDecimal preco;
-    private LocalDate vencimentoPagamento;
-    private LocalDate dataLimiteEntrega;
+    @Column(name = "commodities_name", nullable = false)
+    private String name;
 
-    private String cedulaProdutoRural;
+    @Column(name = "commodities_flag", nullable = false)
+    private String flag;
 
 
 

+ 59 - 0
src/main/java/com/platform2easy/genesis/domain/model/Orderbook.java

@@ -0,0 +1,59 @@
+package com.platform2easy.genesis.domain.model;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Entity
+@Table(name = "orderbook")
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
+public class Orderbook {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @EqualsAndHashCode.Include
+    @Column(name = "orderbook_id")
+    private Long id;
+
+    @Column(name = "orderbook_flag", nullable = false)
+    private String flag;
+
+    @Column(name = "orderbook_ts", nullable = false)
+    private Integer ts;
+
+    @Column(name = "orderbook_is_token", nullable = false)
+    private Boolean isToken;
+
+    @Column(name = "orderbook_amount", nullable = false)
+    private String amount;
+
+    @Column(name = "status_id", nullable = false)
+    private Long statusId;
+
+    @Column(name = "user_id", nullable = false)
+    private Long userId;
+
+    @Column(name = "wallet_id", nullable = false)
+    private Long walletId;
+
+    @Column(name = "token_id")
+    private Long tokenId;
+
+    @Column(name = "currency_id")
+    private Long currencyId;
+
+    @Column(name = "chain_id", nullable = false)
+    private Long chainId;
+}

+ 10 - 0
src/main/java/com/platform2easy/genesis/domain/repository/AppUserRepository.java

@@ -0,0 +1,10 @@
+package com.platform2easy.genesis.domain.repository;
+
+import com.platform2easy.genesis.domain.model.AppUser;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.Optional;
+
+public interface AppUserRepository extends JpaRepository<AppUser, Long> {
+    Optional<AppUser> findByUserEmail(String userEmail);
+}

+ 7 - 0
src/main/java/com/platform2easy/genesis/domain/repository/OrderbookRepository.java

@@ -0,0 +1,7 @@
+package com.platform2easy.genesis.domain.repository;
+
+import com.platform2easy.genesis.domain.model.Orderbook;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface OrderbookRepository extends JpaRepository<Orderbook, Long> {
+}

+ 2 - 1
src/main/java/com/platform2easy/genesis/domain/service/CommodityService.java

@@ -15,9 +15,10 @@ public class CommodityService {
     private final CommodityRepository repository;
 
     @Transactional
-    public void salvar(Commoditiy commoditiy) {
+    public Commoditiy salvar(Commoditiy commoditiy) {
 
         repository.save(commoditiy);
+        return commoditiy;
     }
 
     public List<Commoditiy> listarTodos() {

+ 2 - 1
src/main/java/com/platform2easy/genesis/domain/service/CompraService.java

@@ -15,11 +15,12 @@ public class CompraService {
     private final CompraRepository repository;
 
     @Transactional
-    public void salvar(Compra compra) {
+    public Compra salvar(Compra compra) {
 
         compra.getItens().forEach(itemCompra -> itemCompra.setCompra(compra));
 
         repository.save(compra);
+        return compra;
     }
 
     public List<Compra> listarTodos() {

+ 2 - 2
src/main/java/com/platform2easy/genesis/domain/service/cerc/ContratoValorCprService.java

@@ -1,7 +1,6 @@
 package com.platform2easy.genesis.domain.service.cerc;
 
 import com.platform2easy.genesis.domain.model.cerc.ContratoValorCpr;
-import com.platform2easy.genesis.domain.model.cerc.SolicitacaoRegistroCpr;
 import com.platform2easy.genesis.domain.repository.cerc.ContratoValorCprRepository;
 import jakarta.transaction.Transactional;
 import lombok.AllArgsConstructor;
@@ -16,8 +15,9 @@ public class ContratoValorCprService {
     private final ContratoValorCprRepository repository;
 
     @Transactional
-    public void save(ContratoValorCpr entity) {
+    public ContratoValorCpr save(ContratoValorCpr entity) {
         repository.save(entity);
+        return entity;
     }
     public ContratoValorCpr getById(Long id) {
         return repository.findById(id).orElse(new ContratoValorCpr());

+ 2 - 2
src/main/java/com/platform2easy/genesis/domain/service/cerc/EmissaoCprService.java

@@ -1,7 +1,6 @@
 package com.platform2easy.genesis.domain.service.cerc;
 
 import com.platform2easy.genesis.domain.model.cerc.EmissaoCpr;
-import com.platform2easy.genesis.domain.model.cerc.SolicitacaoRegistroCpr;
 import com.platform2easy.genesis.domain.repository.cerc.EmissaoCprRepository;
 import jakarta.transaction.Transactional;
 import lombok.AllArgsConstructor;
@@ -16,8 +15,9 @@ public class EmissaoCprService {
     private final EmissaoCprRepository repository;
 
     @Transactional
-    public void save(EmissaoCpr enity) {
+    public EmissaoCpr save(EmissaoCpr enity) {
         repository.save(enity);
+        return enity;
     }
     public EmissaoCpr getById(Long id) {
         return repository.findById(id).orElse(new EmissaoCpr());

+ 2 - 1
src/main/java/com/platform2easy/genesis/domain/service/cerc/SolicitacaoRegistroCprService.java

@@ -16,10 +16,11 @@ public class SolicitacaoRegistroCprService {
     private final SolicitacaoRegistroCprRepository repository;
 
     @Transactional
-    public void save(SolicitacaoRegistroCpr entity) {
+    public SolicitacaoRegistroCpr save(SolicitacaoRegistroCpr entity) {
         if (entity.getId() == null) entity.setStatus(StatusSolicitacaoRegistroCpr.NOVO);
 
         repository.save(entity);
+        return entity;
     }
 
     public SolicitacaoRegistroCpr getById(Long id) {

+ 48 - 0
src/main/java/com/platform2easy/genesis/infra/security/SecurityConfig.java

@@ -0,0 +1,48 @@
+package com.platform2easy.genesis.infra.security;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+@Configuration
+@EnableWebSecurity
+public class SecurityConfig {
+
+    private final SecurityFilter securityFilter;
+
+    public SecurityConfig(SecurityFilter securityFilter) {
+        this.securityFilter = securityFilter;
+    }
+
+    @Bean
+    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+        http
+            .csrf(csrf -> csrf.disable())
+            .headers(headers -> headers.frameOptions(frame -> frame.disable()))
+            .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+            .authorizeHttpRequests(auth -> auth
+                .requestMatchers("/auth/**", "/h2-console/**", "/banco/**").permitAll()
+                .anyRequest().authenticated()
+            )
+            .addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class);
+        return http.build();
+    }
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Bean
+    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
+        return configuration.getAuthenticationManager();
+    }
+}

+ 49 - 0
src/main/java/com/platform2easy/genesis/infra/security/SecurityFilter.java

@@ -0,0 +1,49 @@
+package com.platform2easy.genesis.infra.security;
+
+import com.platform2easy.genesis.domain.repository.AppUserRepository;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+import java.util.Collections;
+
+@Component
+public class SecurityFilter extends OncePerRequestFilter {
+
+    private final TokenService tokenService;
+    private final AppUserRepository appUserRepository;
+
+    public SecurityFilter(TokenService tokenService, AppUserRepository appUserRepository) {
+        this.tokenService = tokenService;
+        this.appUserRepository = appUserRepository;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+            throws ServletException, IOException {
+        String authHeader = request.getHeader("Authorization");
+        if (authHeader != null && authHeader.startsWith("Bearer ")) {
+            String token = authHeader.substring(7);
+            try {
+                String subject = tokenService.getSubject(token);
+                appUserRepository.findByUserEmail(subject).ifPresent(appUser -> {
+                    User principal = new User(appUser.getUserEmail(), appUser.getUserPassword(),
+                            Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
+                    UsernamePasswordAuthenticationToken authentication =
+                            new UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities());
+                    SecurityContextHolder.getContext().setAuthentication(authentication);
+                });
+            } catch (Exception ignored) {
+            }
+        }
+        filterChain.doFilter(request, response);
+    }
+}

+ 38 - 0
src/main/java/com/platform2easy/genesis/infra/security/TokenService.java

@@ -0,0 +1,38 @@
+package com.platform2easy.genesis.infra.security;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.platform2easy.genesis.domain.model.AppUser;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+@Service("infraTokenService")
+public class TokenService {
+
+    @Value("${api.security.token.secret}")
+    private String secret;
+
+    public String generateToken(AppUser user) {
+        Algorithm algorithm = Algorithm.HMAC256(secret);
+        return JWT.create()
+                .withIssuer("genesis")
+                .withSubject(user.getUserEmail())
+                .withClaim("role_id", user.getRoleId())
+                .withClaim("company_id", user.getCompanyId())
+                .withExpiresAt(Instant.now().plus(2, ChronoUnit.HOURS))
+                .sign(algorithm);
+    }
+
+    public String getSubject(String token) {
+        Algorithm algorithm = Algorithm.HMAC256(secret);
+        DecodedJWT decoded = JWT.require(algorithm)
+                .withIssuer("genesis")
+                .build()
+                .verify(token);
+        return decoded.getSubject();
+    }
+}

+ 1 - 0
src/main/java/com/platform2easy/genesis/security/config/SecurityConfiguration.java

@@ -45,6 +45,7 @@ public class SecurityConfiguration {
                 .authorizeHttpRequests(auth -> auth
                         .requestMatchers("/login", "/images/**", "/css/**", "/error/**").permitAll()
                         .requestMatchers(HttpMethod.POST, "/authentication/login").permitAll()
+                        .requestMatchers("/auth/**").permitAll()
                         .requestMatchers("/api/**").authenticated()
                         .requestMatchers("/compra", "/compra/**").hasRole(UserRole.ADMIN.toString())
                         .anyRequest().authenticated())

+ 1 - 2
src/main/java/com/platform2easy/genesis/security/service/TokenService.java

@@ -12,8 +12,7 @@ import java.time.Instant;
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
 
-
-@Service
+@Service("securityTokenService")
 public class TokenService {
     @Value("${api.security.token.secret}")
     private String secret;

+ 109 - 0
src/main/java/com/platform2easy/genesis/web/controller/AuthenticationController.java

@@ -0,0 +1,109 @@
+package com.platform2easy.genesis.web.controller;
+
+import com.platform2easy.genesis.domain.model.AppUser;
+import com.platform2easy.genesis.domain.repository.AppUserRepository;
+import com.platform2easy.genesis.infra.security.TokenService;
+import com.platform2easy.genesis.web.dto.AuthenticationDTO;
+import com.platform2easy.genesis.web.dto.RegisterDTO;
+import com.platform2easy.genesis.web.dto.TokenDTO;
+import jakarta.validation.Valid;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Optional;
+
+@RestController("webAuthenticationController")
+@RequestMapping("/auth")
+public class AuthenticationController {
+
+    private final AppUserRepository appUserRepository;
+    private final PasswordEncoder passwordEncoder;
+    private final TokenService tokenService;
+
+    public AuthenticationController(AppUserRepository appUserRepository, PasswordEncoder passwordEncoder, TokenService tokenService) {
+        this.appUserRepository = appUserRepository;
+        this.passwordEncoder = passwordEncoder;
+        this.tokenService = tokenService;
+    }
+
+    @PostMapping("/register")
+    public ResponseEntity<?> register(@Valid @RequestBody RegisterDTO dto) {
+        Optional<AppUser> existing = appUserRepository.findByUserEmail(dto.getEmail());
+        if (existing.isPresent()) {
+            return ResponseEntity.status(HttpStatus.CONFLICT).build();
+        }
+        AppUser user = new AppUser();
+        user.setUserName(dto.getName());
+        user.setUserEmail(dto.getEmail());
+        user.setUserPassword(passwordEncoder.encode(dto.getPassword()));
+        user.setUserPhone(dto.getPhone());
+        user.setUserAddress(dto.getAddress());
+        user.setUserCity(dto.getCity());
+        user.setUserState(dto.getState());
+        user.setUserZip(dto.getZip());
+        user.setUserCountry(dto.getCountry());
+        user.setUserKyc(dto.getKyc());
+        user.setUserBirthdate(dto.getBirthdate());
+        user.setUserCpf(dto.getCpf());
+        user.setCompanyId(dto.getCompanyId());
+        user.setRoleId(dto.getRoleId());
+        user.setUserFlag(dto.getFlag());
+        AppUser saved = appUserRepository.save(user);
+        String token = tokenService.generateToken(saved);
+        return ResponseEntity.status(HttpStatus.CREATED).body(new TokenDTO(token));
+    }
+
+    @PostMapping("/login")
+    public ResponseEntity<?> login(@Valid @RequestBody AuthenticationDTO dto) {
+        Optional<AppUser> existing = appUserRepository.findByUserEmail(dto.getEmail());
+        if (existing.isEmpty()) {
+            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
+        }
+        AppUser user = existing.get();
+        if (!passwordEncoder.matches(dto.getPassword(), user.getUserPassword())) {
+            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
+        }
+        String token = tokenService.generateToken(user);
+        return ResponseEntity.ok(new TokenDTO(token));
+    }
+
+    @PostMapping("/register/default")
+    public ResponseEntity<?> registerDefault() {
+        final String email = "tester@tooeasy.local";
+        final String rawPassword = "ChangeMe123!";
+
+        Optional<AppUser> existing = appUserRepository.findByUserEmail(email);
+        AppUser user;
+        HttpStatus status;
+        if (existing.isPresent()) {
+            user = existing.get();
+            status = HttpStatus.OK;
+        } else {
+            user = new AppUser();
+            user.setUserName("Tester");
+            user.setUserEmail(email);
+            user.setUserPassword(passwordEncoder.encode(rawPassword));
+            user.setUserPhone("0000000000");
+            user.setUserAddress("N/A");
+            user.setUserCity("N/A");
+            user.setUserState("NA");
+            user.setUserZip("00000");
+            user.setUserCountry("BR");
+            user.setUserKyc(1);
+            user.setUserBirthdate(19900101);
+            user.setUserCpf("00000000000");
+            user.setCompanyId(1);
+            user.setRoleId(1);
+            user.setUserFlag("ACTIVE");
+            user = appUserRepository.save(user);
+            status = HttpStatus.CREATED;
+        }
+        String token = tokenService.generateToken(user);
+        return ResponseEntity.status(status).body(new TokenDTO(token));
+    }
+}

+ 35 - 35
src/main/java/com/platform2easy/genesis/web/controller/CommodityController.java

@@ -3,52 +3,52 @@ package com.platform2easy.genesis.web.controller;
 import com.platform2easy.genesis.domain.model.Commoditiy;
 import com.platform2easy.genesis.domain.service.CommodityService;
 import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-@Controller
-@RequestMapping("commodity")
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/commodity")
 @AllArgsConstructor
 public class CommodityController {
 
-    private final CommodityService service;
+    private final CommodityService service; // Injeção de dependência mantida
 
-    private String abrirFormulario(Commoditiy commoditiy, String titulo, Model model) {
-        model.addAttribute("titulo", titulo);
-        model.addAttribute("commodity", commoditiy);
-        return "commodity/form";
+    // GET /api/commodity: Lista todos
+    @GetMapping
+    @ResponseStatus(HttpStatus.OK)
+    public List<Commoditiy> listAll() {
+        return service.listarTodos(); // Chamada ao método Service original
     }
 
-    @GetMapping()
-    public String iniciar(Commoditiy commoditiy, Model model) {
-        return abrirFormulario(commoditiy, "Cadastrar Commodity", model);
+    // GET /api/commodity/{id}: Busca por ID
+    @GetMapping("/{id}")
+    @ResponseStatus(HttpStatus.OK)
+    public Commoditiy getById(@PathVariable Long id) {
+        return service.buscarPorId(id); // Chamada ao método Service original
     }
 
-    @GetMapping("edit/{id}")
-    public String editar(@PathVariable Long id, Model model) {
-        return abrirFormulario(service.buscarPorId(id), "Editar Commodity", model);
+    // POST /api/commodity: Cria um novo recurso
+    @PostMapping
+    @ResponseStatus(HttpStatus.CREATED) // Retorna 201 Created
+    public Commoditiy create(@RequestBody Commoditiy commodity) {
+        commodity.setId(null);
+        return service.salvar(commodity);
     }
 
-    @PostMapping()
-    public String salvar(Commoditiy commoditiy, Model model) {
-        service.salvar(commoditiy);
-        return "redirect:/commodity/all";
+    // PUT /api/commodity/{id}: Atualiza um recurso existente
+    @PutMapping("/{id}")
+    @ResponseStatus(HttpStatus.OK)
+    public Commoditiy update(@PathVariable Long id, @RequestBody Commoditiy commodity) {
+        commodity.setId(id);
+        return service.salvar(commodity);
     }
 
-    @GetMapping("remove/{id}")
-    public String remover(@PathVariable Long id, Model model) {
+    // DELETE /api/commodity/{id}: Deleta um recurso
+    @DeleteMapping("/{id}")
+    @ResponseStatus(HttpStatus.NO_CONTENT)
+    public void delete(@PathVariable Long id) {
         service.deletarPorId(id);
-        return "redirect:/commodity/all";
-    }
-
-    @GetMapping("all")
-    public String listar(Model model) {
-        model.addAttribute("titulo", "Commodities");
-        model.addAttribute("commodities", service.listarTodos());
-        return "commodity/list";
     }
-}
+}

+ 33 - 51
src/main/java/com/platform2easy/genesis/web/controller/CompraController.java

@@ -1,73 +1,55 @@
 package com.platform2easy.genesis.web.controller;
 
 import com.platform2easy.genesis.domain.model.Compra;
-import com.platform2easy.genesis.domain.model.ItemCompra;
 import com.platform2easy.genesis.domain.service.CompraService;
 import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
 
-import java.util.Arrays;
+import java.util.List;
 
-@Controller
-@RequestMapping("compra")
+@RestController
+@RequestMapping("/api/compra")
 @AllArgsConstructor
 public class CompraController {
 
     private final CompraService service;
 
-    @GetMapping()
-    public String iniciar(Compra compra, Model model) {
-        return abrirFormulario(compra, "Comprar", model);
+    // GET /api/compra: Lista todas as Compras
+    @GetMapping
+    @ResponseStatus(HttpStatus.OK)
+    public List<Compra> listAll() {
+        return service.listarTodos();
     }
 
-    @PostMapping()
-    public String inserir(Compra compra, ItemCompra itemCompra, Model model) {
-        itemCompra.setId(null);
-
-        if (compra.getItens() == null) compra.setItens(Arrays.asList(itemCompra));
-        else compra.getItens().add(itemCompra);
-
-        return iniciar(compra, model);
-    }
-
-    @PostMapping("{index}")
-    public String removerItem(@PathVariable int index, Compra compra, Model model) {
-        compra.getItens().remove(index);
-        return iniciar(compra, model);
-    }
-
-    @GetMapping("editar/{id}")
-    public String alterar(@PathVariable Long id, Model model) {
-        return abrirFormulario(service.buscarPorId(id), "Editar Compra", model);
-    }
-
-    private String abrirFormulario(Compra compra, String titulo, Model model) {
-        model.addAttribute("titulo", titulo);
-        model.addAttribute("compra", compra);
-        return "compra/formulario";
+    // GET /api/compra/{id}: Busca uma Compra por ID
+    @GetMapping("/{id}")
+    @ResponseStatus(HttpStatus.OK)
+    public Compra getById(@PathVariable Long id) {
+        return service.buscarPorId(id);
     }
 
-    @PostMapping("salvar")
-    public String salvar(Compra compra, Model model) {
-        service.salvar(compra);
-        return "redirect:/compra/listar";
+    // POST /api/compra: Cria uma nova Compra
+    @PostMapping
+    @ResponseStatus(HttpStatus.CREATED) // Retorna 201 Created
+    public Compra create(@RequestBody Compra compra) {
+        compra.setId(null);
+        return service.salvar(compra);
     }
 
-    @GetMapping("listar")
-    public String listar(Model model) {
-        model.addAttribute("titulo", "Compras");
-        model.addAttribute("compras", service.listarTodos());
-        return "compra/lista";
+    // PUT /api/compra/{id}: Atualiza uma Compra existente
+    @PutMapping("/{id}")
+    @ResponseStatus(HttpStatus.OK)
+    public Compra update(@PathVariable Long id, @RequestBody Compra compra) {
+        compra.setId(id);
+        return service.salvar(compra);
     }
 
-    @GetMapping("remover/{id}")
-    public String remover(@PathVariable Long id, Model model) {
+    // DELETE /api/compra/{id}: Deleta uma Compra
+    @DeleteMapping("/{id}")
+    // Retorna 204 (No Content) após exclusão
+    @ResponseStatus(HttpStatus.NO_CONTENT)
+    public void delete(@PathVariable Long id) {
         service.deletarPorId(id);
-        return "redirect:/compra/listar";
     }
-}
+}

+ 36 - 43
src/main/java/com/platform2easy/genesis/web/controller/cerc/ContratoValorCprController.java

@@ -3,61 +3,54 @@ package com.platform2easy.genesis.web.controller.cerc;
 import com.platform2easy.genesis.domain.model.cerc.ContratoValorCpr;
 import com.platform2easy.genesis.domain.service.cerc.ContratoValorCprService;
 import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-@Controller
-@RequestMapping("cpr/contract")
-@AllArgsConstructor
-public class ContratoValorCprController {
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
 
-    private static final String FORM = "cpr/contract/form";
-    private static final String LIST = "cpr/contract/list";
-    private static final String REDIRECT_ALL = "redirect:/cpr/contract/all";
-    private static final String TITLE_PAGE = "titlePage";
+import java.util.List;
 
+@RestController
+@RequestMapping("/api/cpr/contract")
+@AllArgsConstructor
+public class ContratoValorCprController {
 
     private final ContratoValorCprService service;
 
-    private String openForm(ContratoValorCpr cprContract, String title, Model model) {
-        model.addAttribute(TITLE_PAGE, title);
-        model.addAttribute("cprContract", cprContract);
-        return FORM;
+    // GET /api/cpr/contract: Lista todos os contratos
+    @GetMapping
+    @ResponseStatus(HttpStatus.OK)
+    public List<ContratoValorCpr> listAll() {
+        return service.listAll();
     }
 
-    @GetMapping()
-    public String init(ContratoValorCpr cprContract, Model model) {
-        return openForm(cprContract, "Cadastrar Contrato de CPR", model);
+    // Antiga lógica de 'edit' (busca por ID)
+    // GET /api/cpr/contract/{id}: Busca um contrato por ID
+    @GetMapping("/{id}")
+    @ResponseStatus(HttpStatus.OK)
+    public ContratoValorCpr getById(@PathVariable Long id) {
+        // Mapeia a lógica do antigo método 'edit'
+        return service.getById(id);
     }
 
-    @GetMapping("edit/{id}")
-    public String edit(@PathVariable Long id, Model model) {
-        return openForm(service.getById(id), "Editar Contrato de CPR", model);
+    // POST /api/cpr/contract: Cria um novo contrato
+    @PostMapping
+    @ResponseStatus(HttpStatus.CREATED)
+    public ContratoValorCpr create(@RequestBody ContratoValorCpr cprContract) {
+        cprContract.setId(null);
+        return service.save(cprContract);
     }
 
-    @PostMapping()
-    public String save(@ModelAttribute ContratoValorCpr cprContract) {
-        service.save(cprContract);
-        return REDIRECT_ALL;
+    // PUT /api/cpr/contract/{id}:
+    @PutMapping("/{id}")
+    @ResponseStatus(HttpStatus.OK)
+    public ContratoValorCpr update(@PathVariable Long id, @RequestBody ContratoValorCpr cprContract) {
+        cprContract.setId(id);
+        return service.save(cprContract);
     }
 
-    @GetMapping("remove/{id}")
-    public String remove(@PathVariable Long id, Model model) {
+    // DELETE /api/cpr/contract/{id}: Deleta um contrato
+    @DeleteMapping("/{id}")
+    @ResponseStatus(HttpStatus.NO_CONTENT)
+    public void delete(@PathVariable Long id) {
         service.delete(id);
-        return REDIRECT_ALL;
     }
-
-    @GetMapping("all")
-    public String listAll(Model model) {
-        model.addAttribute(TITLE_PAGE, "Contratos de CPR's");
-        model.addAttribute("cprContracts", service.listAll());
-        return LIST;
-    }
-
-
-}
+}

+ 39 - 45
src/main/java/com/platform2easy/genesis/web/controller/cerc/EmissaoCprController.java

@@ -1,65 +1,59 @@
 package com.platform2easy.genesis.web.controller.cerc;
 
-import com.platform2easy.genesis.domain.model.cerc.ContratoValorCpr;
 import com.platform2easy.genesis.domain.model.cerc.EmissaoCpr;
-import com.platform2easy.genesis.domain.service.cerc.ContratoValorCprService;
 import com.platform2easy.genesis.domain.service.cerc.EmissaoCprService;
 import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
 
-@Controller
-@RequestMapping("cpr/emission")
+import java.util.List;
+
+// 1. Mudar para @RestController para retornar JSON
+@RestController
+// 2. Rota base da API
+@RequestMapping("/api/cpr/emission")
 @AllArgsConstructor
 public class EmissaoCprController {
 
-    private static final String FORM = "cpr/emission/form";
-    private static final String LIST = "cpr/emission/list";
-    private static final String REDIRECT_ALL = "redirect:/cpr/emission/all";
-    private static final String TITLE_PAGE = "titlePage";
-
+    private final EmissaoCprService service; // Injeção de dependência mantida [cite: 13]
 
-    private final EmissaoCprService service;
-
-    private String openForm(EmissaoCpr cprEmission, String title, Model model) {
-        model.addAttribute(TITLE_PAGE, title);
-        model.addAttribute("cprEmission", cprEmission);
-        return FORM;
+    // GET /api/cpr/emission: Lista todas as emissões
+    @GetMapping
+    @ResponseStatus(HttpStatus.OK)
+    public List<EmissaoCpr> listAll() {
+        return service.listAll();
     }
 
-    @GetMapping()
-    public String init(EmissaoCpr cprEmission, Model model) {
-        return openForm(cprEmission, "Cadastrar Emissão de CPR", model);
+    // GET /api/cpr/emission/{id}: Busca uma emissão por ID
+    @GetMapping("/{id}")
+    @ResponseStatus(HttpStatus.OK)
+    public EmissaoCpr getById(@PathVariable Long id) {
+        return service.getById(id);
     }
 
-    @GetMapping("edit/{id}")
-    public String edit(@PathVariable Long id, Model model) {
-        return openForm(service.getById(id), "Editar Emissão de CPR", model);
+    // POST /api/cpr/emission: Cria uma nova emissão
+    @PostMapping
+    @ResponseStatus(HttpStatus.CREATED) // Retorna 201 Created
+    public EmissaoCpr create(@RequestBody EmissaoCpr cprEmission) {
+        // Assume que service.save() foi ajustado para retornar EmissaoCpr (como discutido anteriormente)
+        cprEmission.setId(null);
+        return service.save(cprEmission);
     }
 
-    @PostMapping()
-    public String save(@ModelAttribute EmissaoCpr cprEmission) {
-        service.save(cprEmission);
-        return REDIRECT_ALL;
+    // PUT /api/cpr/emission/{id}: Atualiza uma emissão existente
+    @PutMapping("/{id}")
+    @ResponseStatus(HttpStatus.OK)
+    public EmissaoCpr update(@PathVariable Long id, @RequestBody EmissaoCpr cprEmission) {
+        // Garante que o ID do caminho seja usado para a atualização
+        cprEmission.setId(id);
+        return service.save(cprEmission);
     }
 
-    @GetMapping("remove/{id}")
-    public String remove(@PathVariable Long id, Model model) {
+    // DELETE /api/cpr/emission/{id}: Deleta uma emissão
+    @DeleteMapping("/{id}")
+    // Retorna 204 (No Content) após exclusão
+    @ResponseStatus(HttpStatus.NO_CONTENT)
+    public void delete(@PathVariable Long id) {
         service.delete(id);
-        return REDIRECT_ALL;
     }
-
-    @GetMapping("all")
-    public String listAll(Model model) {
-        model.addAttribute(TITLE_PAGE, "Emissões de CPR's");
-        model.addAttribute("cprEmissions", service.listAll());
-        return LIST;
-    }
-
-
-}
+}

+ 39 - 51
src/main/java/com/platform2easy/genesis/web/controller/cerc/SolicitacaoRegistroCprController.java

@@ -6,73 +6,61 @@ import com.platform2easy.genesis.domain.service.cerc.ContratoValorCprService;
 import com.platform2easy.genesis.domain.service.cerc.EmissaoCprService;
 import com.platform2easy.genesis.domain.service.cerc.SolicitacaoRegistroCprService;
 import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
 
-@Controller
-@RequestMapping("cpr/register")
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/cpr/register")
 @AllArgsConstructor
 public class SolicitacaoRegistroCprController {
 
-    private static final String FORM = "cpr/register/form";
-    private static final String LIST = "cpr/register/list";
-    private static final String REDIRECT_ALL = "redirect:/cpr/register/all";
-    private static final String TITLE_PAGE = "titlePage";
-
-
     private final SolicitacaoRegistroCprService service;
-    private final ContratoValorCprService contratoValorCprService;
-    private final EmissaoCprService emissaoCprService;
 
-    private String openForm(SolicitacaoRegistroCpr cprRegister, String title, Model model) {
-        model.addAttribute(TITLE_PAGE, title);
-        model.addAttribute("cprRegister", cprRegister);
-        model.addAttribute("contracts", contratoValorCprService.listAll());
-        model.addAttribute("emissions", emissaoCprService.listAll());
-        return FORM;
+    // GET /api/cpr/register: Lista todos os registros
+    @GetMapping
+    @ResponseStatus(HttpStatus.OK)
+    public List<SolicitacaoRegistroCpr> listAll() {
+        return service.listAll();
     }
 
-    @GetMapping()
-    public String init(SolicitacaoRegistroCpr cprRegister, Model model) {
-        return openForm(cprRegister, "Registrar CPR", model);
+    // GET /api/cpr/register/{id}: Busca um registro por ID
+    @GetMapping("/{id}")
+    @ResponseStatus(HttpStatus.OK)
+    public SolicitacaoRegistroCpr getById(@PathVariable Long id) {
+        return service.getById(id);
     }
 
-    @GetMapping("edit/{id}")
-    public String edit(@PathVariable Long id, Model model) {
-        return openForm(service.getById(id), "Registro de CPR", model);
+    // POST /api/cpr/register: Cria um novo registro
+    @PostMapping
+    @ResponseStatus(HttpStatus.CREATED) // Retorna 201 Created
+    public SolicitacaoRegistroCpr create(@RequestBody SolicitacaoRegistroCpr cprRegister) {
+        cprRegister.setId(null);
+        return service.save(cprRegister);
     }
 
-    @GetMapping("send/{id}")
-    public String send(@PathVariable Long id, Model model) {
-        var registro = service.getById(id);
-        registro.setStatus(StatusSolicitacaoRegistroCpr.ACEITO);
-        service.save(registro);
-        return REDIRECT_ALL;
-    }
 
-    @PostMapping()
-    public String save(@ModelAttribute SolicitacaoRegistroCpr cprRegister) {
-        service.save(cprRegister);
-        return REDIRECT_ALL;
+    // PUT /api/cpr/register/{id}: Atualiza um registro existente
+    @PutMapping("/{id}")
+    @ResponseStatus(HttpStatus.OK)
+    public SolicitacaoRegistroCpr update(@PathVariable Long id, @RequestBody SolicitacaoRegistroCpr cprRegister) {
+        cprRegister.setId(id);
+        return service.save(cprRegister);
     }
 
-    @GetMapping("remove/{id}")
-    public String remove(@PathVariable Long id, Model model) {
-        service.delete(id);
-        return REDIRECT_ALL;
+    @PostMapping("/{id}/send")
+    @ResponseStatus(HttpStatus.OK) // Retorna 200 OK após a modificação
+    public SolicitacaoRegistroCpr send(@PathVariable Long id) {
+        var registro = service.getById(id);
+        registro.setStatus(StatusSolicitacaoRegistroCpr.ACEITO);
+        return service.save(registro);
     }
 
-    @GetMapping("all")
-    public String listAll(Model model) {
-        model.addAttribute(TITLE_PAGE, "Registros de CPR's");
-        model.addAttribute("cprRegisters", service.listAll());
-        return LIST;
+    // DELETE /api/cpr/register/{id}: Deleta um registro
+    @DeleteMapping("/{id}")
+    @ResponseStatus(HttpStatus.NO_CONTENT)
+    public void delete(@PathVariable Long id) {
+        service.delete(id);
     }
-
-
 }

+ 20 - 0
src/main/java/com/platform2easy/genesis/web/dto/AuthenticationDTO.java

@@ -0,0 +1,20 @@
+package com.platform2easy.genesis.web.dto;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class AuthenticationDTO {
+    @Email
+    @NotBlank
+    private String email;
+    @NotBlank
+    private String password;
+}

+ 47 - 0
src/main/java/com/platform2easy/genesis/web/dto/RegisterDTO.java

@@ -0,0 +1,47 @@
+package com.platform2easy.genesis.web.dto;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class RegisterDTO {
+    @NotBlank
+    private String name;
+    @Email
+    @NotBlank
+    private String email;
+    @NotBlank
+    private String password;
+    @NotBlank
+    private String phone;
+    @NotBlank
+    private String address;
+    @NotBlank
+    private String city;
+    @NotBlank
+    private String state;
+    @NotBlank
+    private String zip;
+    @NotBlank
+    private String country;
+    @NotNull
+    private Integer kyc;
+    @NotNull
+    private Integer birthdate;
+    @NotBlank
+    private String cpf;
+    @NotNull
+    private Integer companyId;
+    @NotNull
+    private Integer roleId;
+    @NotBlank
+    private String flag;
+}

+ 14 - 0
src/main/java/com/platform2easy/genesis/web/dto/TokenDTO.java

@@ -0,0 +1,14 @@
+package com.platform2easy.genesis.web.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class TokenDTO {
+    private String token;
+}

+ 16 - 0
src/main/resources/application-postgres.properties

@@ -0,0 +1,16 @@
+spring.application.name=genesis
+
+server.port=8080
+
+api.security.token.secret=${JWT_SECRET:my-secret-key}
+
+spring.datasource.url=${DB_URL:jdbc:postgresql://localhost:5432/too_easy}
+spring.datasource.username=${DB_USERNAME:postgres}
+spring.datasource.password=${DB_PASSWORD:postgres}
+spring.datasource.driver-class-name=org.postgresql.Driver
+
+spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
+spring.jpa.hibernate.ddl-auto=validate
+
+spring.flyway.enabled=true
+spring.flyway.locations=classpath:db/migration/postgresql

+ 2 - 0
src/main/resources/application.properties

@@ -20,3 +20,5 @@ spring.jpa.hibernate.ddl-auto=update
 #h2
 spring.h2.console.enabled=true
 spring.h2.console.path=/banco
+spring.main.allow-bean-definition-overriding=true
+spring.flyway.enabled=false

+ 138 - 0
src/main/resources/db/migration/postgresql/V1__init.sql

@@ -0,0 +1,138 @@
+CREATE TABLE "chain" (
+    "chain_id"   SERIAL PRIMARY KEY,
+    "chain_name" TEXT NOT NULL
+);
+
+CREATE TABLE "company" (
+    "company_id" SERIAL PRIMARY KEY,
+    "company_name" TEXT NOT NULL,
+    "company_flag" TEXT NOT NULL
+);
+
+CREATE TABLE "role" (
+    "role_id" SERIAL PRIMARY KEY,
+    "company_id" INTEGER NOT NULL,
+    "role_name" TEXT NOT NULL,
+    "role_permission" JSONB NOT NULL,
+    "role_flag" TEXT NOT NULL,
+    CHECK (jsonb_typeof("role_permission") = 'object'),
+    FOREIGN KEY ("company_id") REFERENCES "company" ("company_id")
+);
+
+CREATE TABLE "status" (
+    "status_id" SERIAL PRIMARY KEY,
+    "status_status" TEXT NOT NULL
+);
+
+CREATE TABLE "cpr" (
+    "cpr_id" SERIAL PRIMARY KEY
+);
+
+CREATE TABLE "commodities" (
+    "commodities_id" SERIAL PRIMARY KEY,
+    "commodities_name" TEXT NOT NULL,
+    "commodities_flag" TEXT NOT NULL
+);
+
+CREATE TABLE "wallet" (
+    "wallet_id" SERIAL PRIMARY KEY,
+    "company_id" INTEGER NOT NULL,
+    "wallet_public_key" TEXT NOT NULL,
+    "wallet_private_key" TEXT NOT NULL,
+    "wallet_flag" TEXT NOT NULL,
+    "chain_id" INTEGER NOT NULL,
+    FOREIGN KEY ("company_id") REFERENCES "company" ("company_id"),
+    FOREIGN KEY ("chain_id") REFERENCES "chain" ("chain_id")
+);
+
+CREATE TABLE "currency" (
+    "currency_id"   SERIAL PRIMARY KEY,
+    "currency_external_id" TEXT NOT NULL,
+    "currency_name" TEXT NOT NULL,
+    "currency_digits" INTEGER NOT NULL,
+    "chain_id" INTEGER NOT NULL,
+    "currency_flag" TEXT NOT NULL,
+    FOREIGN KEY ("chain_id") REFERENCES "chain" ("chain_id")
+);
+
+CREATE TABLE "token" (
+    "token_id" SERIAL PRIMARY KEY,
+    "token_external_id" TEXT NOT NULL,
+    "token_commodities_amount" INTEGER NOT NULL,
+    "token_flag" TEXT NOT NULL,
+    "token_commodities_value" INTEGER NOT NULL,
+    "wallet_id" INTEGER NOT NULL,
+    "chain_id" INTEGER NOT NULL,
+    "commodities_id" INTEGER NOT NULL,
+    "cpr_id" INTEGER NOT NULL,
+    FOREIGN KEY ("wallet_id") REFERENCES "wallet" ("wallet_id"),
+    FOREIGN KEY ("chain_id") REFERENCES "chain" ("chain_id"),
+    FOREIGN KEY ("commodities_id") REFERENCES "commodities" ("commodities_id"),
+    FOREIGN KEY ("cpr_id") REFERENCES "cpr" ("cpr_id")
+);
+
+CREATE TABLE "user" (
+    "user_id" SERIAL PRIMARY KEY,
+    "user_name" TEXT NOT NULL,
+    "user_email" TEXT NOT NULL UNIQUE,
+    "user_password" TEXT NOT NULL,
+    "user_phone" TEXT NOT NULL,
+    "user_address" TEXT NOT NULL,
+    "user_city" TEXT NOT NULL,
+    "user_state" TEXT NOT NULL,
+    "user_zip" TEXT NOT NULL,
+    "user_country" TEXT NOT NULL,
+    "user_kyc" INTEGER NOT NULL,
+    "user_birthdate" INTEGER NOT NULL,
+    "user_cpf" TEXT NOT NULL,
+    "company_id" INTEGER NOT NULL,
+    "role_id" INTEGER NOT NULL,
+    "user_flag" TEXT NOT NULL,
+    FOREIGN KEY ("company_id") REFERENCES "company" ("company_id"),
+    FOREIGN KEY ("role_id") REFERENCES "role" ("role_id")
+);
+
+CREATE TABLE "tx_coin" (
+    "tx_coin_id" TEXT PRIMARY KEY,
+    "tx_coin_value" TEXT NOT NULL,
+    "tx_coin_flag" TEXT NOT NULL,
+    "tx_coin_ts" INTEGER NOT NULL,
+    "tx_coin_from_address" TEXT NOT NULL,
+    "tx_coin_to_address" TEXT NOT NULL,
+    "currency_id" INTEGER NOT NULL,
+    "chain_id" INTEGER NOT NULL,
+    FOREIGN KEY ("currency_id") REFERENCES "currency" ("currency_id"),
+    FOREIGN KEY ("chain_id") REFERENCES "chain" ("chain_id")
+);
+
+CREATE TABLE "tx_token" (
+    "tx_token_id" TEXT PRIMARY KEY,
+    "tx_token_flag" TEXT NOT NULL,
+    "tx_token_ts" INTEGER NOT NULL,
+    "tx_token_from_address" TEXT NOT NULL,
+    "tx_token_to_address" TEXT NOT NULL,
+    "token_id" INTEGER NOT NULL,
+    "chain_id" INTEGER NOT NULL,
+    FOREIGN KEY ("token_id") REFERENCES "token" ("token_id"),
+    FOREIGN KEY ("chain_id") REFERENCES "chain" ("chain_id")
+);
+
+CREATE TABLE "orderbook" (
+    "orderbook_id" SERIAL PRIMARY KEY,
+    "orderbook_flag" TEXT NOT NULL,
+    "orderbook_ts" INTEGER NOT NULL,
+    "orderbook_is_token" BOOLEAN NOT NULL,
+    "orderbook_amount" TEXT NOT NULL,
+    "status_id" INTEGER NOT NULL,
+    "user_id" INTEGER NOT NULL,
+    "wallet_id" INTEGER NOT NULL,
+    "token_id" INTEGER,
+    "currency_id" INTEGER,
+    "chain_id" INTEGER NOT NULL,
+    FOREIGN KEY ("status_id") REFERENCES "status" ("status_id"),
+    FOREIGN KEY ("user_id") REFERENCES "user" ("user_id"),
+    FOREIGN KEY ("wallet_id") REFERENCES "wallet" ("wallet_id"),
+    FOREIGN KEY ("token_id") REFERENCES "token" ("token_id"),
+    FOREIGN KEY ("currency_id") REFERENCES "currency" ("currency_id"),
+    FOREIGN KEY ("chain_id") REFERENCES "chain" ("chain_id")
+);

+ 3 - 0
src/main/resources/db/migration/postgresql/V2__seed_company_role.sql

@@ -0,0 +1,3 @@
+INSERT INTO "company" (company_name, company_flag) VALUES ('Too Easy', 'ACTIVE');
+INSERT INTO "role" (company_id, role_name, role_permission, role_flag) VALUES (1, 'TRADER_USER', '{}'::jsonb, 'ACTIVE');
+INSERT INTO "status" (status_status) VALUES ('OPEN');

Some files were not shown because too many files changed in this diff