---
# System prepended metadata

title: E-commerce

---

**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

