**Admin**
**Regras de negócio:**
1. Limitar o title em 40 caracteres
2. Limitar a description em 90 caracteres
3. Texto do Botão call to action limitar em 12 caracteres
4. Limitar o título da Ilha de 2 a 30 caracteres
5. Título da oferta com no máximo 90 caracteres
**Api pública**
Definições de tipos de entidades:
```typescript=
enum PositionContent {
center,
left,
right
}
enum TextColor {
light,
dark
}
interface Island {
id: string;
title: string;
slug: string;
position: number;
}
interface Specifications {
name: string;
value: string;
}
interface Offer {
id: string;
title: string;
description: string;
slug: string;
score: number; //Iremos retornar somente quando formos subir a avaliação
total: number; // valor total da oferta
discount_percent: string; //porcentagem de desconto da oferta
total_without_discount: // valor total sem desconto a ser exibido
hasDiscount: boolean // retorna se existe desconto para a oferta
collapse_specifications: Specification[],
bullet_specifications: Specification[]
}
interface Category {
id: string;
name: string;
id_parent?: string; // auto relacionamento
url_redirect: string;
position: number;
}
interface MenuResponse {
...Category;
children: Category[];
}
interface CategoryFilter {
...MenuResponse;
count: number;
}
interface Customer {
id: string;
firstname: string;
lastname: string;
email: string;
phone: string;
phone2: string;
cpf: string;
cnpj: string;
}
interface Banner {
id: string;
title?: string;
description?: string;
label_action_button?: string;
position_content: PositionContent;
url_redirect: string;
is_open_blank: boolean;
text_color: TextColor;
public_url: string;
}
interface Store {
id: string;
name: string;
carrousel_time: number;
show_carousel_pagination: boolean;
placeholder_search: string;
}
enum SectionType {
Island,
FlatIsland,
Banner
}
interface SectionResponse {
id_section: string;
type: SectionType;
id_content: string;
}
```
1. Api para listar banners:
**GET /stores/:slug/banners**
Response:
```typescript=
interface Response {
count: number;
rows: Banner[]
}
```
2. Api para listagem do menu com base na ordem do item pai para item filho e no campo position:
**GET /stores/:slug**
Response:
```typescript=
interface Response {
store: Store;
menu: MenuResponse[];
sections: SectionResponse[]
}
```
3. Api para listar ilhas e suas ofertas limitando em 11 ofertas por ilha e ordenadas pelo campo position e as ofertas ordenadas também pela posição:
**GET stores/:slug/islands**
Response:
```typescript=
interface IslandResponse {
rows: Offer[];
title: string;
count: number;
}
```
**GET stores/:slug/islands/:id**
Response:
```typescript=
interface Response {
count: number;
rows: Offer[];
}
```
Api para busca de ofertas, a busca pelo parâmetro "search" deverá ser realizada pelo nome do produto ou descrição da oferta. O limit irá ficar como responsabilidade do bff, com uma valor fixo. O limit não poderá ser um valor muito alto, deveremos adicionar um limit
**GET stores/:slug/offers?filter=[{"id_category":"123"}, {"carga-horaria": ["8 horas"]}]&search=""&limit=10&offset=0**
Possíveis parâmetros de ordenação:
Passar na querystring o parâmetro sort podendo conter os seguintes parâmetros:
**&sort={"field": "createdAt": "sort": "asc"}**
**&sort={"field": "total": "sort": "asc"}**
**&sort={"field": "title": "sort": "asc"}**
Response:
```typescript=
interface Response {
count: number;
rows: Offer[];
categories: CategoryFilter[];
}
```
**GET stores/:slug/offers/:offer_slug**
Response:
```typescript=
interface Response {
...Offer
}
```
4. Criar uma API para receber a avaliação da oferta:
Ao salvar uma avaliação, atualizar a oferta com o novo score (realizar em background de forma assíncrona?)
**POST stores/:slug/offers/:offer_slug/evaluations**
Corpo da requisição
```typescript=
score: number;
title: string;
comment: string;
id_offer: string;
id_customer: string;
```
```typescript=
interface Rating {
id: string;
score: number;
title: string;
comment: string;
offer: Offer;
customer: Customer;
score: number;
comment: string;
}
```
**GET stores/:slug/offers/:offer_slug/evaluations**
```typescript=
interface Rating {
id: string;
score: number;
title: string;
comment: string;
customer: Customer;
}
```
Request body:
```typescript=
{
comment: string;
score: number;
}
```
Response:
```typescript=
201 [created]
```
5. Api para retornar os filtros da página de categoria
**GET api/stores/:slug/filters**
Response:
```typescript=
{
data: [
{
'title': 'Carga horária',
'id': 'carga-horaria'
'content': String[]
},
{
'title': 'Preço',
'id': 'total'
'content': String[]
},
{
'title': 'Modalidade',
'id': 'modalidade'
'content': String[]
}
]
}
```
6. Rota para adicionar item ao carrinho:
**POST /api/stores/:slug/cart/add-item**
Request body:
```typescript=
{
id_cart?: string; // caso não exista um id de carrinho no localStorage, não será passado esse valor, consequentemente o back vai criar um novo carrinho e adicionar esse item
id_offer: string;
}
```
Response body:
```typescript=
{
id: string; // retorna o id do carrinho e o front salva no localStorage
}
```
**PUT /api/stores/:slug/cart/:id/update-item**
Request body:
```typescript=
{
id_offer: string;
qty: number;
}
```
Remover item do carrinho
**DELETE /api/stores/:slug/cart/:id/remove-item/:id_offer**
Limpar todos os itens do carrinho
**DELETE /api/stores/:slug/cart/:id/clean**
Response: 200 OK
7. Rota para listagem do carrinho e seus itens:
**GET /api/stores/:slug/cart/:id**
Response body:
```typescript=
{
total: number;
subtotal: number;
discount: number;
code_coupon: string;
coupon_message: string; // mensagem do cupom "30% de desconto nos 3 primeiros....."
message: {
type: string; // 'warning'
text: string; // Mensagens que indicarão se o cupom está expirado
},
store: {
modal_cart_message: string;
},
rows: [
{
id: string;
slug: string;
name: string;
qty: number;
total_without_discount: number;
hasDiscount: boolean;
total: number;
payment_condition: string;
}
]
}
```
8. Rota para aplicar cupom de desconto em um carrinho
**POST /api/stores/:slug/cart/:id/coupon**
Request body:
```typescript=
{
code_coupon: string;
}
```
9. Rota para aplicar cupom de desconto em um carrinho
**DELETE /api/stores/:slug/cart/:id/coupon**
10. Rota para validar o carrinho
**GET /api/stores/:slug/cart/:id/validate**
Response body:
```typescript=
{
code: number;
message: string;
httpStatus: number;
}
```
Response Codes:
- 404
- Cupom inválido ou incorreto
- 400
- Este cupom não é mais válido
- Uso de cupom excedido
- Um desconto já está sendo aplicado. Você não pode aplicar mais um código promocional
11. Rota para gerar um carrinho compartilhado
-> Ao acessar a url de compartilhamento de carrinho, caso já exista um carrinho para o "cliente" vamos apenas atualizar os dados do carrinho e os itens dele
-> Caso tenha o objeto data, enviar o carrinho por e-mail, com o link de compartilhamento
**POST /api/stores/:slug/cart/:id_cart**
Request body:
```typescript=
{
shared: true;
data?: {
sender_name: string;
recipient_name: string;
recipient_email: string;
}
}
```
Response body:
```typescript=
{
id: string;
url: "https://shop.dev.store.totvs.com/{loja}/cart/id_cart"
}
```
12. Rota para atualizar o carrinho baseado em outro (compartilhado) - Ao acessar o link será cahamada essa rota, irá basicamente atualizar o carrinho atual pelos mesmos itens do compartilhado
**PUT /api/stores/:slug/cart**
Request body:
```typescript=
{
id_shared_cart: string; // id do carrinho compartilhado
id_cart?: string; // id do carrinho atual do usuário ao qual será atualizado
}
```
Response:
```typescript=
200 ok
```
13. Rota para listar formas de pagamento:
**GET /api/stores/:slug/cart/:id/payment**
Response:
```typescript=
[
{
id: string;
name: string;
type: 'credit-card' | 'billet',
quota: [
{
id: string;
name: string; // 1x
value: number; //10.000,00
}
]
}
]
```
14. Rota para listar os termos:
**GET /api/stores/:slug/cart/:id/terms**
Response:
```typescript=
[
{
id: string;
url: string;
name: string;
}
]
```
15. Rota para finalizar o pedido:
**POST /api/stores/:slug/order**
Request:
```typescript=
{
id_cart: string;
payment: {
id_payment_form: string;
card_number?: string;
card_cvv?: string;
card_date?: date; // MM/yy
holder_name?: string;
quota:{
id: string;
name: string; // 1x
value: number; //10.000,00
}
}
}
```
Response:
```typescript=
{
id: string;
}
```
16. Rota para buscar uma ordem pelo id:
**GET /api/stores/:slug/order/:id**
Response:
```typescript=
{
id: string;
sale_number: string;
created_sale_message: string;
infos_sale_message: string;
}
```
## Integração com identity ##
**POST /api/shop/customer/identity/verify**
Request body
```typescript=
{
"KeyInfo": string;
"SAMLResponse": string;
"SigAlg": string;
"Signature": string;
}
```
Response
```typescript=
{
"jwt": string;
"email": "string;
}
```
**GET /api/shop/customer/identity**
Query params
```typescript=
{
"theme": string;
"stsignup": string;
"sthome": string;
}
```
**Pontos de dúvida:**
- Desconto, como será efetuado o desconto. Por ilha, oferta ou categoria ?
- **O desconto poderá ser por categoria e por valor**
- Com base em uma porcentagem ?
- Haverá uma data/hora de validade para o desconto ?
- Quando clicar em "ver todos" na ilha, não tem a informação para o cliente mostrando que ele está visualizando as ofertas daquela ilha.
- O texto "Ligamos para você" das ofertas click to lead, serão parametrizados por oferta, ou pela modalidade da oferta?
- **A oferta é com base na modalidade**
- A modalidade é quem define se a oferta é "click to lead" ?
- A exibição do desconto será parametrizável ? Ex: Exibir o desconto desde que a oferta contenha um, ou um parâmetro que irá definir se o desconto será exibido ou não