Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions rodada-cases-semana4/backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
.env
package-lock
6,012 changes: 6,012 additions & 0 deletions rodada-cases-semana4/backend/package-lock.json

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions rodada-cases-semana4/backend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "metabackend",
"version": "1.0.0",
"description": "Projeto Backend com arquitetura em camada de serviços",
"main": "index.js",
"scripts": {
"dev": "ts-node-dev ./src/index.ts",
"start": "node ./build/index.js",
"build": "tsc",
"migrations": "tsnd ./src/data/migrations.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
"heroku-run-build-script": false,
"keywords": [],
"author": "grupo-metabackend",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"knex": "^0.21.5",
"mysql": "^2.18.1",
"nodemailer": "^6.7.5",
"uuid": "^8.3.1"
},
"devDependencies": {
"@types/bcryptjs": "^2.4.2",
"@types/cors": "^2.8.8",
"@types/express": "^4.17.8",
"@types/jsonwebtoken": "^8.5.0",
"@types/knex": "^0.16.1",
"@types/node": "^14.11.2",
"@types/nodemailer": "^6.4.4",
"@types/uuid": "^8.3.0",
"ts-node-dev": "^2.0.0-0",
"typescript": "^4.0.3"
}
}
62 changes: 62 additions & 0 deletions rodada-cases-semana4/backend/src/business/ProductBusiness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import ProductData from "../data/ProductData";
import Order from "../model/Order";
import { SendOrderInputDTO } from "../types/sendOrderInputDTO";
import { Authenticator } from "../services/Authenticator";
import { HashManager } from "../services/HashManager";
import { IdGenerator } from "../services/IdGenerator";


export default class ProductBusiness {
constructor(
private productData: ProductData,
private idGenerator: IdGenerator,
private hashManager: HashManager,
private authenticator: Authenticator
) {}

public async sendOrder(input: SendOrderInputDTO): Promise<void> {
if(!input.client_name || !input.delivery_date || !input.order_total || !input.products){
throw new Error("Dados inválidos");
}

const id = this.idGenerator.generateId();

const formatedDate = input.delivery_date.split("-");
const deliveryDate = new Date(
Number(formatedDate[0]),
Number(formatedDate[1]) - 1,
Number(formatedDate[2])
);


const order = new Order(
id,
input.client_name,
deliveryDate,
input.order_total,
input.products
);

await this.productData.insertOrder(order);

return;
}

public async getOrderById(id: string) {
if(!id){
throw new Error("Id inválido");
}

const order = await this.productData.getOrderById(id);

return order;

};

public async getAllOrders() {
const orders = await this.productData.getAllOrders();

return orders;
}

}
11 changes: 11 additions & 0 deletions rodada-cases-semana4/backend/src/config/smtp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import dotenv from 'dotenv';

dotenv.config();

export const SMTP_CONFIG = {
host: 'smtp.office365.com',
port: 587,
secure: false,
user: process.env.MAILER_USER,
pass: process.env.MAILER_PASSWORD
}
62 changes: 62 additions & 0 deletions rodada-cases-semana4/backend/src/controller/ProductController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Request, Response } from "express";
import ProductBusiness from "../business/ProductBusiness";
import { SendOrderInputDTO } from "../types/sendOrderInputDTO";


export default class ProductsController {
constructor(private productBusiness: ProductBusiness) {}

sendOrder = async (req: Request, res: Response) => {
const { client_name, delivery_date, order_total, products } = req.body;

const input: SendOrderInputDTO = {
client_name,
delivery_date,
order_total,
products,
};
try {
const order = await this.productBusiness.sendOrder(input);
res
.status(201)
.send({ message: "Pedido enviado com sucesso", order });
} catch (error) {
if (error instanceof Error) {
return res.status(400).send(error.message);
}
res.status(500).send("Erro ao enviar pedido");
}
};

getOrderById = async (req: Request, res: Response) => {

const { id } = req.params;

if (!id) {
return res.status(400).send("Id inválido");
}

try {
const order = await this.productBusiness.getOrderById(id);
res.status(200).send(order);
} catch (error) {
if (error instanceof Error) {
return res.status(400).send(error.message);
}
res.status(500).send("Erro ao buscar pedido");
}
};

getAllOrders = async (req: Request, res: Response) => {
try {
const orders = await this.productBusiness.getAllOrders();
res.status(200).send(orders);
} catch (error) {
if (error instanceof Error) {
return res.status(400).send(error.message);
}
res.status(500).send("Erro ao buscar pedidos");
}
};

}
19 changes: 19 additions & 0 deletions rodada-cases-semana4/backend/src/data/BaseDatabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import knex from "knex";
import dotenv from "dotenv";

dotenv.config();

export abstract class BaseDatabase {
protected connection = knex({
client: "mysql",
connection: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_SCHEMA,
port: 3306,
multipleStatements: true,
},
});
static connection: any;
}
66 changes: 66 additions & 0 deletions rodada-cases-semana4/backend/src/data/ProductData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import Order from "../model/Order";
import { BaseDatabase } from "./BaseDatabase";


export default class ProductData extends BaseDatabase {
protected PRODUCT_TABLE_NAME = "shopper_products";
protected ORDER_TABLE_NAME = "shopper_orders";

insertOrder(order: Order): Promise<void> {
try{
const result = this.connection.raw(`
INSERT INTO ${this.ORDER_TABLE_NAME} (
order_id,
client_name,
delivery_date,
order_total,
products
) VALUES (?, ?, ?, ?, ?)
`, [
order.getId(),
order.getClientName(),
order.getDeliveryDate(),
order.getOrderTotal(),
JSON.stringify(order.getProducts())
]);
return result;
} catch (error:any) {
throw new Error(error.sqlMessage || error.message);
}

};

getOrderById = async (id: string): Promise<Order> => {
try{
const queryResult: any = await this.connection(this.ORDER_TABLE_NAME)
.select()
.where({ order_id: id });

const order = new Order(
queryResult[0].order_id,
queryResult[0].client_name,
queryResult[0].delivery_date,
queryResult[0].order_total,
JSON.parse(queryResult[0].products)
);

return order;

} catch (error:any) {
throw new Error(error.sqlMessage || error.message);
}
};

getAllOrders() {
try{
const result = this.connection.raw(`
SELECT * FROM ${this.ORDER_TABLE_NAME}
`);
return result;

} catch (error:any) {
throw new Error(error.sqlMessage || error.message);
}
};

}
32 changes: 32 additions & 0 deletions rodada-cases-semana4/backend/src/data/migrations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { BaseDatabase } from "./BaseDatabase";

class Migrations extends BaseDatabase {
public createTables = async (): Promise<void> => {
try {
await this.connection.raw(`
CREATE TABLE shopper_products (
product_id VARCHAR(255) PRIMARY KEY,
product_name VARCHAR(255),
product_price FLOAT,
product_quantity_stock INT
);

CREATE TABLE shopper_orders (
order_id VARCHAR(255) PRIMARY KEY,
client_name VARCHAR(255),
delivery_date DATE,
order_total VARCHAR(255),
products VARCHAR(255)
);
`);

console.log("Tabelas criadas com sucesso");
await this.connection.destroy();
} catch (error: any) {
console.log(error.sqlMessage || error.message);
await this.connection.destroy();
}
};
}

new Migrations().createTables();
5 changes: 5 additions & 0 deletions rodada-cases-semana4/backend/src/error/BaseError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class BaseError extends Error {
constructor(message: string) {
super(message)
}
}
23 changes: 23 additions & 0 deletions rodada-cases-semana4/backend/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import express, { Express } from "express";
import dotenv from "dotenv";
import cors from "cors";
import { AddressInfo } from "net";
import {productRouter} from "./routes/productRouter";

dotenv.config();

export const app: Express = express();
app.use(express.json());
app.use(cors());

app.use("/order", productRouter);

const server = app.listen(process.env.PORT || 3003, () => {
if (server) {
const address = server.address() as AddressInfo;
console.log(`Server is running in http://localhost:${address.port}`);
} else {
console.error(`Failure upon starting server.`);
}
}
);
39 changes: 39 additions & 0 deletions rodada-cases-semana4/backend/src/model/Order.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export default class Order {
constructor(
private id: string,
private client_name: string,
private delivery_date: Date,
private order_total: number,
private products: Array<{
id: string,
product_name: string,
quantity: number,
price: number,
}>,
) {}

public getId(): string {
return this.id;
}

public getClientName(): string {
return this.client_name;
}

public getDeliveryDate(): Date {
return this.delivery_date;
}

public getOrderTotal(): number {
return this.order_total;
}

public getProducts(): Array<{
id: string,
product_name: string,
quantity: number,
price: number,
}> {
return this.products;
}
}
9 changes: 9 additions & 0 deletions rodada-cases-semana4/backend/src/model/Product.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default class Product{
constructor(
private product_id:string,
private product_name:string,
private product_price: number,
private product_quantity_stock:number
){}
}

Loading