Commit 79762029 authored by Aléxia Dorneles's avatar Aléxia Dorneles 💻
Browse files

Merge branch 'apolo/feature/endpoint-finalizar-compra' into 'dev'

endpoint de finalizar compra

See merge request !45
2 merge requests!51merge dev into main,!45endpoint de finalizar compra
Pipeline #16049 passed with stage
in 7 seconds
Showing with 117 additions and 11 deletions
+117 -11
......@@ -139,4 +139,11 @@ export class CartItemsService {
{ quantity },
);
}
async savePrice(order_id: number, product_id: number, price: number) {
await this.cartItemRepository.update(
{ order: { id: order_id }, product: { id: product_id } },
{ price },
);
}
}
......@@ -91,4 +91,11 @@ export class ClientService {
async findByEmail(email: string): Promise<ClientEntity> {
return this.clientsRepository.findOne({ where: { email } });
}
async isOng(id: number): Promise<boolean> {
const client = await this.clientsRepository.findOne({
where: { id },
});
return client.isOng;
}
}
......@@ -56,10 +56,15 @@ export class OrdersService {
}
async getOpenOrderCart(client_id: number): Promise<any[]> {
const order = this.getOpenOrder(client_id);
const orderItems = await this.cartItemService.getOrderItems(
(await order).id,
);
const order = await this.getOpenOrder(client_id);
if (!order) {
throw new NotFoundException(
`Carrinho aberto não encontrado para o cliente com ID ${client_id}`,
);
}
const orderItems = await this.cartItemService.getOrderItems(order.id);
const date = new Date(Date.now());
const cart = await Promise.all(
......@@ -87,7 +92,7 @@ export class OrdersService {
let total: number;
total = 0;
order.forEach((item) => {
total += item.price;
total += item.price * item.quantity;
});
return total;
}
......@@ -241,10 +246,80 @@ export class OrdersService {
};
}
// O endpoint de finalizar compra deve:
// - setar o status do carrinho como fechado.
// - calcular o preço de cada item, e atualizar o cartItem correspondente
// - somar os preços dos cartItems, e setar totalValue da order para esta soma
// - atualizar orderDate para a data atual
// - gerar um codigo int aleatorio, e setar em code na order
async finishOrder(client_id: number): Promise<any> {
const order = await this.orderRepository.findOne({
where: { client: { id: client_id }, open: true },
});
if (!order) {
throw new NotFoundException(
`Carrinho aberto não encontrado para o cliente com ID ${client_id}`,
);
}
const orderItems = await this.cartItemService.getOrderItems(order.id);
if (orderItems.length == 0) {
throw new NotFoundException(
`Nenhum produto encontrado no carrinho do cliente com ID ${client_id}`,
);
}
const isOng = await this.clientService.isOng(client_id);
const date = new Date(Date.now());
let totalPrice = 0;
for (const item of orderItems) {
const product = await this.productService.findOne(item.product.id);
const expirationDate = new Date(product.expiration_date);
const daysToExpiration = Math.ceil(
(expirationDate.getTime() - date.getTime()) / (1000 * 3600 * 24),
);
if (daysToExpiration <= 0) {
throw new NotFoundException(
`Produto com ID ${item.product.id} está expirado e não pode ser comprado`,
);
}
if (!isOng && daysToExpiration <= 3) {
throw new NotFoundException(
`Produto com ID ${item.product.id} está perto da expiração e não pode ser comprado por este usuário`,
);
}
if (product.quantity < item.quantity) {
throw new NotFoundException(
`Produto com ID ${item.product.id} não possui quantidade suficiente em estoque`,
);
}
}
for (const item of orderItems) {
const price: number = this.productService.calculateDynamicPrice(
item.product,
date,
);
await this.cartItemService.savePrice(order.id, item.product.id, price);
totalPrice += price * item.quantity;
this.productService.detractStock(item.product.id, item.quantity);
}
order.total_value = totalPrice;
order.order_date = date;
order.open = false;
order.code = Math.floor(Math.random() * 1000000);
await this.orderRepository.save(order);
const updatedOrderItems = await this.getOrderCart(order.id);
return {
message: 'Compra finalizada com sucesso',
order: {
id: order.id,
client_id: client_id,
code: order.code,
total_value: order.total_value,
order_date: order.order_date,
items: updatedOrderItems,
},
};
}
}
......@@ -5,6 +5,7 @@ import {
Get,
HttpException,
Param,
Patch,
Post,
Put,
Request,
......@@ -95,6 +96,14 @@ export class OrdersController {
return await this.service.getPastOrder(req.user.sub, id);
}
@ApiOperation({ summary: 'Finaliza a compra do carrinho atual do usuário' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@Patch('/buy/')
async finishOrder(@Request() req: AuthenticatedRequest): Promise<OrderDto[]> {
return await this.service.finishOrder(req.user.sub);
}
@ApiOperation({ summary: 'Atualiza a quantidade de um produto no carrinho' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
......
......@@ -248,6 +248,14 @@ export class ProductsService {
return true;
}
async detractStock(id: number, numBought: number) {
const entity = await this.productRepository.findOne({
where: { id },
});
entity.quantity = entity.quantity - numBought;
await this.productRepository.save(entity);
}
async getSeller(id: number): Promise<{ id: number; name: string }> {
const product = await this.productRepository.findOne({
where: { id },
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment